Compare commits

..
Author SHA1 Message Date
Fyren 0869fde119 Removing -dev for 1.2.3 release 2009-08-28 02:53:08 -07:00
Fyren 8e6166fa37 Changelog, build_type 2009-08-28 02:51:59 -07:00
Fyren 669b4cc69f Fix extension filename lookup 2009-08-28 02:44:30 -07:00
Matt Woodrow 22622ccafe Bumped versions, tree open again. 2009-08-27 18:39:41 -04:00
Matt Woodrow d25c68f0a6 Added tag sourcemod-1.2.2 for changeset f55c735efeef 2009-08-27 18:37:48 -04:00
Matt Woodrow ff38e3ded2 Removed -dev tags for release 2009-08-27 18:00:35 -04:00
Matt Woodrow 4f43f43297 Updated changelog, release preparations. 2009-08-27 17:59:42 -04:00
Matt Woodrow 60fccfface Will it ever end? 2009-08-26 12:23:01 +12:00
Matt Woodrow 98690df815 Where the hell did that come from... 2009-08-26 12:10:13 +12:00
Matt Woodrow 52c537b2ab Typo 2009-08-26 12:00:14 +12:00
Matt Woodrow bbec55d5f6 Build fix 2009-08-26 11:39:53 +12:00
David Anderson 0abdcb58cf Removed auto folders (bug 3949, r=pred) 2009-08-26 11:26:12 +12:00
Matt Woodrow 902672aa58 Build fix 2009-08-24 09:41:06 +12:00
DaFox aed47ac13d Added PointOutsideWorld native to sdktools (bug 3906, r=dvander) 2009-08-24 09:19:15 +12:00
Erik Minekus 6928d046f4 Added "motd" chat trigger to basetriggers (bug 2694, r=dvander) 2009-08-24 09:13:08 +12:00
Kornelijus Survila 6c396dfbef Added manual extension reloading command to root console menu (bug 3934, r=dvander) 2009-08-24 09:09:46 +12:00
Mr E. Unknown 4b66ca079d Fixed 'list' type custom menu entries overwriting admin restrictions (bug 3783, r=pred) 2009-08-24 09:01:23 +12:00
Downtown1 ea2e448dd6 Added sm_resetcvar command to basecommands (bug 3636, r=pred) 2009-08-24 08:54:46 +12:00
Erik Minekus d7fe14221b Updated DOD:S gamedata offsets 2009-08-17 09:57:39 +12:00
Fyren e89d3e5616 Fix ForceRespawn offset (bug 3950) 2009-08-14 02:37:41 -07:00
Matt Woodrow 253ed583e6 Fixed tf2 build config names (bug 3948 again) 2009-08-14 20:56:41 +12:00
Matt Woodrow 58cb84d0bf Loads succesfully on tf now, Initial offset testing looks good (bug 3948, what else) 2009-08-14 20:14:03 +12:00
David Anderson 65d34bdb55 Fixed SDKTools Makefile (bug 3948). 2009-08-14 04:05:38 -04:00
David Anderson 19fd09c102 Linux build fix, typo. Oh Lord, we bsearch thee. bug 3948 of course. 2009-08-14 03:50:43 -04:00
David Anderson 434d458a54 Build fixes (bug 3948). 2009-08-14 03:38:43 -04:00
David Anderson aaae36dbd3 Triggering build (bug 3948). 2009-08-14 03:22:10 -04:00
David Anderson 4427ec3a65 Build fix - typo (bug 3948 fallout). 2009-08-14 03:02:51 -04:00
Fyren 5f6c5cb4fb Updated build tool for orangebox fork (bug 3948, r=ds,dvander). 2009-08-14 02:56:19 -04:00
John Schoenick 6425484608 TF gamedata updates (bug 3948 fallout, r=dvander). 2009-08-14 02:48:14 -04:00
David Anderson 8e897f62a3 Updated gamedata engines for orangebox fork (bug 3948, r=ds). 2009-08-14 02:45:22 -04:00
Matt Woodrow d40423569a Updated Visual Studio project files for new orangebox fork (bug 3948, r=ds). 2009-08-14 02:42:31 -04:00
Matt Woodrow 7f28a15a5c Updated loader to "detect" orangebox fork (bug 3948, r=ds,dvander). 2009-08-14 02:38:39 -04:00
Fyren 669f1aefa6 Makefile updates for new orangebox fork (bug 3948, r=ds). 2009-08-14 02:35:28 -04:00
Fyren a65dfc4888 Compile-time check updates for new orangebox fork (bug 3948, r=ds,dvander). 2009-08-14 02:34:32 -04:00
David Anderson 60292fa424 Merge. 2009-08-10 22:15:23 -04:00
David Anderson 0303377f92 Fixed incorrect escaping in clientprefs SQLite queries (bug 3904, r+a12=pred). 2009-08-10 22:13:48 -04:00
psychonic bfd9b061f4 Synergy gamedata updates (bug 3315, r=dvander) 2009-07-30 17:19:05 -07:00
David Anderson b1bf2dece1 Upgraded to pcre-7.9, fixed linkage to msvcr90 (bug 3923). 2009-07-28 19:01:37 -04:00
Fyren b9e2d2b690 Make Insurgency use SayText for printing to chat (bug 3738, r=dvander) 2009-07-27 16:44:17 -07:00
psychonic 15fe086e7a Insurgency gamedata updates (bug 3511, r=dvander) 2009-07-27 16:31:08 -07:00
psychonic 26eae4e396 ZM gamedata updates (bug 3746, r=dvander) 2009-07-27 16:30:39 -07:00
psychonic 72eeebb59f Empires gamedata updates (bug 3500, r=dvander) 2009-07-27 16:30:10 -07:00
psychonic 1c5a684f1c ZPS gamedata updates (bug 3877, r=dvander) 2009-07-27 16:25:14 -07:00
psychonic 3f5cd0e0e7 AoC gamedata updates (bug 3891, r=dvander) 2009-07-27 16:23:08 -07:00
Matt Schubert 536ef2c019 Fixed RemovePlayerDisguise signature for TF2 (bug 3892). 2009-07-11 16:07:44 -07:00
David Anderson 9320d4b378 Bumped version, changed back to dev branch. 2009-05-31 01:14:33 -04:00
David Anderson 5b6970561e Added tag sourcemod-1.2.1 for changeset 3c30a59c2296 2009-05-31 01:13:15 -04:00
David Anderson 83f374561c Bumped versions again. 2009-05-30 23:49:31 -04:00
David Anderson d914a6b982 Fixed buildbot script bugs. 2009-05-30 23:49:10 -04:00
David Anderson 9b14101586 Bumped versions for release. 2009-05-30 22:57:53 -04:00
David Anderson 46c87f509b Changed branch from dev to rel. 2009-05-30 22:51:23 -04:00
David Anderson 4df1d19cf2 Updated changelog for 1.2.1 release. 2009-05-30 22:49:10 -04:00
David Anderson c1af9081c6 Build push. 2009-05-30 21:18:58 -04:00
David Anderson ae538916b6 Fixed build. 2009-05-30 19:57:59 -04:00
David Anderson 1efea1fd82 Fixed compiler asserting when returning a string literal (bug 3836, r+a12=fyren). 2009-05-30 19:43:02 -04:00
David Anderson ef255c9a3e Fixed compiler erroring when tagging functions for string return (bug 3837, r+a12=fyren). 2009-05-30 19:41:34 -04:00
David Anderson 0909a1ffae Fixed compiler not handling constant chained relational operators correctly (bug 3838, r+a12=fyren). 2009-05-30 19:40:13 -04:00
David Anderson d725178405 Fixed revote bug and inflexibilities in RedrawClientVoteMenu (bug 3834, r=fyren). 2009-05-30 19:32:43 -04:00
Fyren 148271c5ea Fix crash when unloading a plugin with live user message hooks (bug 3817, r+a12=dvander) 2009-05-25 18:13:28 -07:00
David Anderson 6252676e57 Fixed compiler using NDEBUG in debug builds (bug 3815, r=fyren, a12=NPOTB). 2009-05-24 12:08:00 -04:00
David Anderson d4709704ea Fixed Plugin_Handled acting like a Stop in usermsg hooks (bug 3685, r=fyren, a12=blocking). 2009-05-24 12:00:53 -04:00
Fyren e6d418c04e This is the do something button. 2009-05-21 20:51:31 -07:00
Fyren 752f7bdefc Preliminary TF2 gamedata changes 2009-05-21 20:39:03 -07:00
Fyren ced6add9ea Add L4D handling to GuessSDKVersion() (bug 3842, r+a12=dvander) 2009-05-13 16:05:37 -07:00
noob cannon lol e9834a33b1 Updated Zombie Panic Source offsets (bug 3632, r=dvander). 2009-05-12 20:28:04 -04:00
1054 changed files with 86872 additions and 384272 deletions
-13
View File
@@ -1,15 +1,11 @@
# Binaries # Binaries
\.dll$ \.dll$
\.dylib$
\.exe$ \.exe$
\.so$ \.so$
# Files generated by Visual Studio # Files generated by Visual Studio
\.aps$ \.aps$
\.ipch$
\.ncb$ \.ncb$
\.opensdf$
\.sdf$
\.suo$ \.suo$
\.user$ \.user$
@@ -17,12 +13,3 @@
/CrazyDebug.* /CrazyDebug.*
/Debug.* /Debug.*
/Release.* /Release.*
# Files generated by Mac OS X Finder
(^|/)\.DS_Store$
# Files generated by Windows Explorer
(^|/)[dD]esktop\.ini$
(^|/)[tT]humbs\.db$
syntax: glob
build/*
+2 -6
View File
@@ -3,9 +3,5 @@ e6ef5ecdf8d75740ca2685a709bf321f8873bc3b sourcemod-1.1.0
e877885fac80be71822641f7a9122cebc9812521 sourcemod-1.1.1 e877885fac80be71822641f7a9122cebc9812521 sourcemod-1.1.1
b3ffa8a4511c4eadaf533fc790aa6b14f7f0c6ea sourcemod-1.1.2 b3ffa8a4511c4eadaf533fc790aa6b14f7f0c6ea sourcemod-1.1.2
3a73bbf60f34befa9b66be03fa5974b394bb3411 sourcemod-1.2.0 3a73bbf60f34befa9b66be03fa5974b394bb3411 sourcemod-1.2.0
78a1f1b1c6fa86fd7691c70ebf48a9fb3dfb3c11 sourcemod-1.5.0 3c30a59c2296a13284a9f4eb42863b47db645adf sourcemod-1.2.1
5574bfe07731b7dba171c1300f6022319d2dbc89 sourcemod-1.5.1 f55c735efeefe68863b96713fcd55a7774d8ceab sourcemod-1.2.2
238c41726d73d9f0d65005ff43c1ab86adb0e163 sourcemod-1.5.2
27bf76b007d2360a9cfc7af9e14d1c9a6bddcc64 sourcemod-1.5.3
27bf76b007d2360a9cfc7af9e14d1c9a6bddcc64 sourcemod-1.5.3
0000000000000000000000000000000000000000 sourcemod-1.5.3
-490
View File
@@ -1,490 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys
class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir):
if dir == 'ep1':
folder = 'hl2sdk'
else:
folder = 'hl2sdk-' + dir
self.envvar = sdk
self.ext = ext
self.code = aDef
self.define = name
self.platform = platform
self.folder = folder # Default folder name.
self.name = dir
self.path = None # Actual path
WinOnly = ['windows']
WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac']
PossibleSDKs = {
'ep1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'ep1'),
'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'ob'),
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'),
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'),
'tf2': SDK('HL2SDKTF2', '2.tf2', '10', 'TF2', WinLinuxMac, 'tf2'),
'l4d': SDK('HL2SDKL4D', '2.l4d', '11', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
'nd': SDK('HL2SDKND', '2.nd', '12', 'NUCLEARDAWN', WinLinuxMac, 'nd'),
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '13', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
'swarm': SDK('HL2SDK-SWARM', '2.swarm', '14', 'ALIENSWARM', WinOnly, 'swarm'),
'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '18', 'CSGO', WinLinuxMac, 'csgo'),
'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '15', 'PORTAL2', [], 'portal2'),
# These engines are only supported on SourceMod 1.6.
# 'blade': SDK('HL2SDKBLADE', '2.blade', '16', 'BLADE', WinLinux, 'blade'),
# 'dota': SDK('HL2SDKDOTA', '2.dota', '19', 'DOTA', WinOnly, 'dota'),
# 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '17', 'INSURGENCY', WinLinuxMac, 'insurgency'),
# 'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, '2013'),
}
def ResolveEnvPath(env, folder):
if env in os.environ:
path = os.environ[env]
if os.path.isdir(path):
return path
else:
head = os.getcwd()
oldhead = None
while head != None and head != oldhead:
path = os.path.join(head, folder)
if os.path.isdir(path):
return path
oldhead = head
head, tail = os.path.split(head)
return None
class SMConfig(object):
def __init__(self):
self.sdks = {}
self.binaries = []
self.extensions = []
self.generated_headers = None
self.mms_root = None
self.mysql_root = None
self.spcomp = None
self.smx_files = {}
self.versionlib = None
def detectProductVersion(self):
builder.AddConfigureFile('product.version')
# For OS X dylib versioning
import re
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
productContents = fp.read()
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents)
if m == None:
self.productVersion = '1.0.0'
else:
major, minor, release = m.groups()
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
def detectSDKs(self):
sdk_list = builder.options.sdks.split(',')
use_all = sdk_list[0] == 'all'
use_present = sdk_list[0] == 'present'
for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name]
if builder.target_platform in sdk.platform:
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
if sdk_path is None:
if use_all or sdk_name in sdk_list:
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
continue
if use_all or use_present or sdk_name in sdk_list:
sdk.path = sdk_path
self.sdks[sdk_name] = sdk
if len(self.sdks) < 1:
raise Exception('At least one SDK must be available.')
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
if not self.mms_root:
raise Exception('Could not find a source copy of Metamod:Source')
if builder.options.hasMySql:
for i in range(7):
self.mysql_root = ResolveEnvPath('MYSQL5', 'mysql-5.' + str(i))
if self.mysql_root:
break
if not self.mysql_root:
raise Exception('Could not find a path to MySQL!')
def configure(self):
builder.AddConfigureFile('pushbuild.txt')
cfg = builder.DetectCompilers()
cxx = cfg.cxx
if cxx.behavior == 'gcc':
cfg.defines += [
'stricmp=strcasecmp',
'_stricmp=strcasecmp',
'_snprintf=snprintf',
'_vsnprintf=vsnprintf',
'HAVE_STDINT_H',
'GNUC',
]
cfg.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
'-Werror',
'-Wno-uninitialized',
'-Wno-unused',
'-Wno-switch',
'-msse',
'-m32',
]
have_gcc = cxx.name == 'gcc'
have_clang = cxx.name == 'clang'
if have_clang or (have_gcc and cxx.majorVersion >= 4):
cfg.cflags += ['-fvisibility=hidden']
cfg.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.minorVersion >= 6):
cfg.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.minorVersion >= 7) or (have_clang and cxx.majorVersion >= 3):
cfg.cxxflags += ['-Wno-delete-non-virtual-dtor']
if have_gcc:
cfg.cflags += ['-Wno-parentheses']
elif have_clang:
cfg.cflags += ['-Wno-logical-op-parentheses']
cfg.linkflags += ['-m32']
cfg.cxxflags += [
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
]
if have_gcc:
cfg.cflags += ['-mfpmath=sse']
elif cxx.name == 'msvc':
if builder.options.debug == '1':
cfg.cflags += ['/MTd']
cfg.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cfg.cflags += ['/MT']
cfg.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0',
]
cfg.cflags += [
'/W3',
]
cfg.cxxflags += [
'/EHsc',
'/GR-',
'/TP',
]
cfg.linkflags += [
'/MACHINE:X86',
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
'user32.lib',
'gdi32.lib',
'winspool.lib',
'comdlg32.lib',
'advapi32.lib',
'shell32.lib',
'ole32.lib',
'oleaut32.lib',
'uuid.lib',
'odbc32.lib',
'odbccp32.lib',
]
# Optimization
if builder.options.opt == '1':
cfg.defines += ['NDEBUG']
if cxx.behavior == 'gcc':
cfg.cflags += ['-O3']
elif cxx.behavior == 'msvc':
cfg.cflags += ['/Ox']
cfg.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging
if builder.options.debug == '1':
cfg.defines += ['DEBUG', '_DEBUG']
if cxx.behavior == 'msvc':
cfg.cflags += ['/Od', '/RTC1']
if int(cxx.version) >= 1600:
cfg.cflags += ['/d2Zi+']
# This needs to be after our optimization flags which could otherwise disable it.
if cxx.name == 'msvc':
# Don't omit the frame pointer.
cfg.cflags += ['/Oy-']
# Platform-specifics
if builder.target_platform == 'linux':
cfg.defines += ['_LINUX', 'POSIX']
if cxx.name == 'gcc':
cfg.linkflags += ['-static-libgcc']
elif cxx.name == 'clang':
cfg.linkflags += ['-lgcc_eh']
elif builder.target_platform == 'mac':
cfg.defines += ['OSX', '_OSX', 'POSIX']
cfg.cflags += ['-mmacosx-version-min=10.5']
cfg.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++',
'-stdlib=libstdc++',
]
cfg.cxxflags += ['-stdlib=libstdc++']
elif builder.target_platform == 'windows':
cfg.defines += ['WIN32', '_WINDOWS']
# Finish up.
cfg.defines += [
'SOURCEMOD_BUILD',
'SM_GENERATED_BUILD',
'SM_USE_VERSIONLIB',
]
cfg.includes += [os.path.join(builder.buildPath, 'includes')]
cfg.includes += [os.path.join(builder.sourcePath, 'versionlib')]
def LibraryBuilder(self, compiler, name):
binary = compiler.Library(name)
if builder.target_platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'SM_GENERATED_BUILD',
'RC_COMPILE',
]
elif builder.target_platform == 'mac':
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
]
binary.compiler.linkflags += [self.versionlib]
binary.compiler.sourcedeps += SM.generated_headers
return binary
def ProgramBuilder(self, compiler, name):
binary = compiler.Program(name)
if builder.target_platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'SM_GENERATED_BUILD',
'RC_COMPILE',
]
binary.compiler.linkflags += [self.versionlib]
binary.compiler.sourcedeps += SM.generated_headers
return binary
def Library(self, context, name):
compiler = context.compiler.clone()
return self.LibraryBuilder(compiler, name)
def Program(self, context, name):
compiler = context.compiler.clone()
return self.ProgramBuilder(compiler, name)
def ExtCompiler(self, context):
compiler = context.compiler.clone()
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'extensions'),
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
os.path.join(builder.sourcePath, 'public', 'amtl'),
]
return compiler
def HL2Compiler(self, context, sdk):
compiler = self.ExtCompiler(context)
if sdk.name == 'ep1':
mms_path = os.path.join(self.mms_root, 'core-legacy')
else:
mms_path = os.path.join(self.mms_root, 'core')
compiler.cxxincludes += [
os.path.join(mms_path),
os.path.join(mms_path, 'sourcehook'),
]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines
paths = [
['public'],
['public', 'engine'],
['public', 'mathlib'],
['public', 'vstdlib'],
['public', 'tier0'],
['public', 'tier1']
]
if sdk.name == 'ep1' or sdk.name == 'darkm':
paths.append(['public', 'dlls'])
paths.append(['game_shared'])
else:
paths.append(['public', 'game', 'server'])
paths.append(['public', 'toolframework'])
paths.append(['game', 'shared'])
paths.append(['common'])
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name == '2013' and compiler.cxx.behavior == 'gcc':
# The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp')
compiler.defines.remove('_snprintf=snprintf')
compiler.defines.remove('_vsnprintf=vsnprintf')
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
if compiler.cc.behavior == 'msvc':
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
else:
compiler.defines += ['COMPILER_GCC']
# For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes.
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.defines += ['NETWORK_VARS_ENABLED']
if sdk.name in ['css', 'hl2dm', 'dods', '2013', 'tf2', 'l4d2']:
if builder.target_platform in ['linux', 'mac']:
compiler.defines += ['NO_MALLOC_OVERRIDE']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
return compiler
def ExtLibrary(self, context, name):
compiler = self.ExtCompiler(context)
return self.LibraryBuilder(compiler, name)
def HL2Library(self, context, name, sdk):
compiler = self.HL2Compiler(context, sdk)
if builder.target_platform == 'linux':
if sdk.name == 'ep1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name == '2013':
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac':
if sdk.name == '2013':
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']:
if sdk.name == '2013':
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
]
else:
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
]
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
binary = self.LibraryBuilder(compiler, name)
dynamic_libs = []
if builder.target_platform == 'linux':
compiler.linkflags[0:0] = ['-lm']
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', '2013', 'l4d2']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif sdk.name in ['l4d', 'nd', 'blade', 'insurgency', 'csgo']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
binary.compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
binary.compiler.linkflags.append(binary.Dep(lib_path))
for library in dynamic_libs:
source_path = os.path.join(lib_folder, library)
output_path = os.path.join(binary.localFolder, library)
def make_linker(source_path, output_path):
def link(context, binary):
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
return output
return link
linker = make_linker(source_path, output_path)
binary.compiler.linkflags[0:0] = [binary.Dep(library, linker)]
return binary
SM = SMConfig()
SM.detectProductVersion()
SM.detectSDKs()
SM.configure()
SM.generated_headers = builder.RunScript(
'tools/buildbot/Versioning',
{ 'SM': SM }
)
SM.versionlib = builder.RunScript(
'versionlib/AMBuilder',
{ 'SM': SM }
)
builder.RunBuildScripts(
[
'loader/AMBuilder',
'core/AMBuilder',
'core/logic/AMBuilder',
'extensions/bintools/AMBuilder',
'extensions/clientprefs/AMBuilder',
'extensions/curl/AMBuilder',
'extensions/cstrike/AMBuilder',
'extensions/geoip/AMBuilder',
'extensions/mysql/AMBuilder',
'extensions/regex/AMBuilder',
'extensions/sdkhooks/AMBuilder',
'extensions/sdktools/AMBuilder',
'extensions/sqlite/AMBuilder',
'extensions/tf2/AMBuilder',
'extensions/topmenus/AMBuilder',
'extensions/updater/AMBuilder',
'sourcepawn/compiler/AMBuilder',
'sourcepawn/jit/AMBuilder',
'plugins/AMBuilder',
'tools/buildbot/PackageScript',
],
{
'SM': SM
}
)
if builder.options.breakpad_dump:
builder.RunScript('tools/buildbot/BreakpadSymbols', { 'SM': SM })
+1
View File
@@ -3,3 +3,4 @@ CONFIGURE YOUR IDENTITY FOR MERCURIAL!
IF YOU ARE A DEVELOPER WITH PUSH ACCESS, DO IT NOW KPLZTHX. IF YOU ARE A DEVELOPER WITH PUSH ACCESS, DO IT NOW KPLZTHX.
http://wiki.alliedmods.net/Mercurial_Tutorial#Identity http://wiki.alliedmods.net/Mercurial_Tutorial#Identity
-637
View File
@@ -1,642 +1,5 @@
SourceMod Changelog SourceMod Changelog
SourceMod 1.5.3 [2014-03-22]
URL: http://wiki.alliedmods.net/SourceMod_1.5.3_Release_Notes
User Changes:
- Updated support for CS:GO after multiple breaking game updates.
- Updated gamedata support for GoldenEye: Source (Peace-Maker).
- Fixed crash on SDKHooks extension load in Alien Swarm (bug 6059).
- Fixed memory leak from unmanaged forwards never being freed (bug 6025).
- Fixed possible crash when unloading the CStrike extension.
- Fixed crash in SDKHooks Reload post-hook (Peace-Maker).
- Fixed FakeClientCommandEx always leaking memory (bug 5678).
- Fixed extra entity networking occuring with SetEntProp natives on some games.
- Fixed being able to nominate same map multiple times (bug 5109).
- Fixed spurious FindEntityByClassname error being logged on some games and platforms.
- Fixed an Anti-Flood bypass exploit (bug 5394).
- Removed part of Addresses gamedata error handling which could cause false errors to be logged (bug 6044).
- Fixed mapchooser not resetting nominations count when clearing nominations list (bug 5359).
- Improved performances of client convar query handling (bug 6003).
Developer Changes:
- Added GiveAmmo native to SDKTools (bug 6039) (Peace-Maker).
- Added SQL_SetCharset native to (re)set charset even after reconnect (bug 5786) (Peace-Maker).
- Added support for entity references in SDKHooks natives (bug 6069).
- Added support for server passwords to DisplayAskConnectBox stock (bug 5984) (FlaminSarge).
- Renamed SortFunc2D parameters to match documentation (bug 6014) (Peace-Maker).
- Fixed param order in AddToTopMenu function doc (bug 6035) (Peace-Maker).
- Added |any| tag to WritePackCell and ReadPackCell native param/return values (bug 6001).
- Updated SDKHook_TakeDamage native for game updates.
- Added default infinite value for TF2_AddCondition duration.
- Added support for conditions >= 64 in TF2_OnConditionAdded/Removed (bug 5565, bug 5976) (FlaminSarge).
- Updated TFCond and TF customkill enum values (bug 6012) (FlaminSarge).
- Fixed regression causing incorrect return and inability to block in TF2_OnCalcIsAttackCritical forward.
- Fixed TE_* natives operating on incorrect data for some tempents (bug 6072).
- Fixed CS_AliasToWeaponID not returning a valid weaponID for cz75a.
- Fixed CS_GetWeaponPrice returning incorrect value for M4A1 in CS:GO (bug 6045).
- Increased max gamedata byte signature length.
- Ported SM build scripts to AMBuild2 (bug 5997).
----------------------------------------------------------
SourceMod 1.5.2 [2013-10-29]
URL: http://wiki.alliedmods.net/SourceMod_1.5.2_Release_Notes
User Changes:
- Updated gamedata support for TF2, CS:S, CS:GO, and HL2:DM.
- Fixed crash from regression in SDKTools SetClientListening hook refcounting (bug 5956) (KyleS).
- Fixed potential crash when having maps with format characters in name.
- Fixed some nextmap issues with long map names.
- SDKTools no longer requires gamedata for sm_dump_datamaps on TF2, CS:S, HL2:DM, and DoD:S (bug 5968).
Developer Changes:
- Updated TFCond and TF custom dmg enums.
- Updated TF2 critical hit detection logic in TF2_OnCalcIsAttackCritical to handle more cases, including when criticals are disabled (bug 5894).
- Fixed GetEngineVersion native returning a bad value when running on MM:S 1.9.x or earlier (bug 5697).
----------------------------------------------------------
SourceMod 1.5.1 [2013-09-10]
URL: http://wiki.alliedmods.net/SourceMod_1.5.1_Release_Notes
User Changes:
- Updated gamedata support for TF2.
- Added missing DispatchKeyValue gamedata for HL2 CTF (bug 5114) (peace-maker).
- Fixed translations not being loaded if identifier was not two or three characters (fixes Portuguese) (bug 5888).
- Fixed runoff voting occurring when receiving the exact number of required votes (bug 5890).
- Fixed reserve slot plugin hiding too many slots on Orangebox gamesif SourceTV and/or Replay are present (bug 5499).
- Fixed some crashes in TF2 and unexpected behavior in all games with SDKHook_TakeDamage due to uninitialized var.
- Fixed attempted triggers from gagged users displaying in chat (bug 5918).
- Fixed errors in Italian translation (Oktober).
- Added Norwegian translation (checkster).
Developer Changes:
- Added CS_UpdateClientModel native to CStrike extension for CS:S and CS:GO (bug 5905) (Drifter).
- Fixed setting weapon param in SDKHook_TakeDamage overwriting attacker instead of setting weapon (bug 5911) (KyleS)
----------------------------------------------------------
SourceMod 1.5.0 [2013-08-25]
URL: http://wiki.alliedmods.net/SourceMod_1.5.0_Release_Notes
User Changes:
- Added support for Counter-Strike: Global Offensive (bug 5299, bug 5579).
- Split CS:S, TF2, DoD:S, HL2:DM, and ND to separate binaries (bug 5370, bug 5813).
- Added support for runoff voting in mapchooser (bug 4218).
- Added option to require Steam validation before granting admin access (bug 4837) (VoiDeD).
- Added localization support for many more core and base plugin messages (bug 5120, bug 5146).
- Added the ability to override RegConsoleCommand-created commands (bug 5199).
- Added support for "fuzzy" (partial) map names in map-related natives and cmds for L4D and later (bug 5599).
- Updated Reserved Slots to use max humans as max count (bug 5444).
- Added support for custom maxitems on radio menus (bug 5371).
- Improved console config editing (bug 5470).
- Increased map name buffer sizes in mapchooser to better account for nested maps (bug 5609) (Peace-Maker).
- Fixed JIT conflicts with SELinux (bug 5581).
- Added logged error when PlayerRunCommand offset lookup fails (bug 5535) (GoD-Tony).
- Fixed double print when sending psay to self (bug 5649) (Peace-Maker).
- Fixed check against uninitialized string in extension loader (bug 5546) (KyleS).
- Fixed possible runtime errors in basetriggers for not-ingame clients (bug 5191) (Peace-Maker).
- Check all possible mapcycle paths on newer orangebox games (bug 5719).
- Fixed ReadMapList not seeing maps in all valve search paths (bug 5715) (VoiDeD).
- Fixed typo in too-many-params native error message (Peace-Maker).
- Fixed various issues in clientprefs (bug 5538) (KyleS).
- Removed debug printout from PerformGravity (bug 5679) (KyleS).
- Fixed broken translating in some plugins and natives (bug 5612) (KyleS).
- Fixed issues with COMMAND_FILTER_NO_BOTS and @bots multi-target.
- Fixed crash in SDKHooks when throwing bad ent type error on logical ent (KyleS).
Developer Changes:
- Added support for CS:GO to the CStrike extension (bug 5299) (Drifter).
- Added support for new protobuf usermessages used in newer games (bug 5579, bug 5588, bug 5590, bug 5633).
- Added latest SDKHooks version as first-party extension.
- Updated SQLite to version 3.7.15.1 (bug 5235).
- Added natives for changing team score and mvp stars on CSS/CSGO (bug 5295) (Drifter).
- Added global pre and post forwards for client chat (bug 5394) (KyleS).
- Added TF2_CanPlayerTeleport forward to the TF2 game extension (bug 5283) (VoiDeD).
- Added GetEntityAddress native (bug 5269) (ProdigySim).
- Added more parameters to PlayerRunCommand forward (bug 5346) (GoD-Tony).
- Added forwards to basecomm plugin (bug 5466) (Drifter).
- Added symbol lookup support to gamedata on Windows (bug 5511) (GoD-Tony).
- Exposed GetLanguageInfo in ITranslator interface (bug 5249) (VoiDeD).
- Increase maximum .sp line length to 4095 characters. (bug 5347) (theY4Kman).
- Improved netprop dump output (bug 5471).
- Added int64 typename to netprop dumps (bug 5655).
- Added GetMaxHumanPlayers native exposing IServerGameClients func (bug 5551).
- Added WeaponIDToAlias native to CStrike extension (bug 5460) (KyleS).
- Fixed OnLibraryAdded/Removed not being called in all plugins (bug 5431).
- Made thread worker processing limits configurable at runtime (bug 5326).
- Added support in TF2 ext for detection of player conds >= 64 (bug 5565).
- Updated button defines in entity_prop_stocks (bug 5564).
- Added GetPlayerResourceEntity to SDKTools to replace old, semi-broken TF2-only version (bug 5491).
- Exposed third parameter of TF2's AddCond in TF2_AddCondition (bug 5641) (FlaminSarge).
- Added GetSteamAccountID function to IPlayerHelpers and native for sp (bug 5548) (KyleS).
- Added ISDKHooks interface with entity listeners (bug 5602) (GoD-Tony).
- Added file upload support to webternet extension.
- Added more alternative names for TFClass_Heavy (bug 5338) (Afronanny).
- Throw error instead of crash when calling SetTeamScore between maps (bug 5718) (KyleS).
- Fixed clients not being marked as in kick queue in some cases (bug 5746) (SystematicMania).
- Made compile.sh set working dir to own dir (bug 5710) (KyleS).
- Added CS_IsValidWeaponID native and validity checks to other natives (bug 5566) (Drifter).
- Numerous code documentation fixups (bug 5720) (Tsunami).
- Fixed cmd listener callback return behavior to match func doc (bug 5882).
Internal Changes:
- Fixed handle misuse in clientprefs plugin (bug 5805) (KyleS).
- Removed call to getchar() in debug build of compiler (bug 5626) (KyleS).
- Fixed instability issues with cloned handles (bug 5245, bug 5240) (KyleS).
- Changed extension unload order to avoid exposing finalization window (bug 5556) (KyleS).
- Call OnPluginEnd before finalizer hooks have run (bug 4519).
- Fixed potential for reading out of library bounds in MemoryUtils::FindPattern.
- Fixed typo in TF2 ext asm.c causing accidental assignment instead of compare.
- Overhauled versioning information (bug 5453).
- Changed from RemoveEdict to using the Kill input for TF2_RemoveWeapon.
- Fixed accidental assignment in each of SDKTools and sp compiler (bug 5745) (KyleS).
- Fixed potential deadlock in HandleSystem::TryAndFreeSomeHandles (bug 5665) (KyleS).
----------------------------------------------------------
SourceMod 1.4.7 [2013-02-06]
URL: http://wiki.alliedmods.net/SourceMod_1.4.7_Release_Notes
User Changes:
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM).
- Updated gamedata for Left 4 Dead 2, Nuclear Dawn, No More Room in Hell, Zombie Panic Source, CSPromod, GoldenEye Source, Synergy, The Hidden, and PVKII.
- Added system to block malware or illegal plugins (bug 5289).
- Fixed a potential crash when a bad entity index is passed to certain functions (bug 5539) (KyleS).
- Added an error message for when auto plugin configs fail to be created due to write error (bug 5465) (Drifter).
- Fixed an issue where a malformed plugin could cause crashes (bug 5478).
Developer Changes:
- Added new values to the TFCond TF2 conditions enum (bug 5537) (FlaminSarge).
- Updated TFHoliday TF2 holidays enum (bug 5526) (Powerlord).
- Fixed regression in SourceMod 1.3.0 causing GetEntPropEnt, GetEntDataEnt2, and GameRules_GetPropEnt to possibly return stale (incorrect) entity indexes in place of -1.
- Added support for < 32-bit unsigned sign extension to GameRules_GetProp lookup (already in GetEntProp since SM 1.4.0).
- Fixed < 32-bit unsigned sign extension in GetEntProp not being applied for array prop elements (bug 5591).
- Fixed value size auto-detection in GetEntProp and GameRules_GetProp for ep2v's new SPROP_VARINT sendprops.
- Fixed Sort_Random sort type not including first value in array sorting functions (bug 4292) (Peace-Maker).
- Fixed GameRules_SetPropVector writing data to unexpected addresses instead of to the gamerules proxy entity (bug 5592) (ProdigySim).
- Fixed VoteMenuToAll stock adding bots to list (bug 5253 (VoiDeD).
----------------------------------------------------------
SourceMod 1.4.6 [2012-09-04]
URL: http://wiki.alliedmods.net/SourceMod_1.4.6_Release_Notes
User Changes:
- Fixed extraneous errors resulting from a bug in 1.4.5.
----------------------------------------------------------
SourceMod 1.4.5 [2012-09-03]
URL: http://wiki.alliedmods.net/SourceMod_1.4.5_Release_Notes
User Changes:
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Updated Nuclear Dawn, Dino D-Day, and Zombie Panic gamedata.
- Added compatibility for running on Metamod:Source 1.9.0.
- Fixed very minor memory leaks in CStrike extension (bug 5456) (KyleS).
- Fixed crash from plugins accessing netprops too early (bug 5297) (KyleS).
- Fixed crash from plugins trying to access nested datadesc members (bug 5446).
Developer Changes:
- Added new TF2 weapon and custom dmg defines.
- Added new TF2 TFHoliday value (bug 5436) (Powerlord).
- Fixed IClientListener::InterceptClientConnect not being able to properly block connections (bug 5461) (PimpinJuice).
- Fixed PrepSDKCall_SetSignature native not working with symbol names on L4D2 linux (bug 5440).
- Fixed resolution of GetProfilerTime native on non-Windows platforms.
-----------------------------
SourceMod 1.4.4 [2012-07-03]
URL: http://wiki.alliedmods.net/SourceMod_1.4.4_Release_Notes
User Changes:
- Updated support for latest Source 2009 engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Updated Nuclear Dawn gamedata.
- Fixed a crash that could occur when selecting an option on a clientprefs prefab menu (bug 5374).
Developer Changes:
- Added new TF2 weapon and custom dmg defines.
- Added new TF2 TFHoliday value (bug 5364) (Powerlord).
- Updated sample extension to properly fill ninvoke with INativeInvoker ptr (bug 5340) (Afronanny).
-----------------------------
SourceMod 1.4.3 [2012-06-09]
URL: http://wiki.alliedmods.net/SourceMod_1.4.3_Release_Notes
User Changes:
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Made clientprefs attempt to reconnect to the database on map change (bug 4745).
- Log functions now respect sv_logecho (bug 5135).
- Fixed client console vote output (bug 5290, bug 5205) (FlaminSarge).
- Fixed error when reloading dependant plugins using aliased natives (bug 5302).
- Fixed intermittent crash when looking for an invalid signature (bug 5301).
- Fixed possible crash when reloading a plugin with an invalid binary (bug 5288).
- Exposed extensions list to clients (bug 5221) (VoiDeD).
- Fixed intermittent crashes in clientprefs (bug 4660).
- Fixed crash when passing an invalid entity reference to ReferenceToEntity (bug 5330).
- Fixed cstrike extension crash on shutdown (bug 5328).
- Lowered threading API think time to 20ms, making threaded MySQL queries complete faster (bug 4733).
Developer Changes:
- Fixed client serials not being unique on Windows (bug 5285).
- Fixed broken SourceTV detection on L4D1 (bug 5216).
- Fixed Float negation operator (bug 5292).
- Updated TF2 condition defines (bug 5259) (FlaminSarge).
- Adding missing SetMenuNoVoteButton native declaration (bug 4522) (GoD-Tony).
- Fixed erroneous const-qualification of name param of GetAdminUsername (bug 5267).
- Added GetGameTickCount native (bug 5209) (GoD-Tony).
-----------------------------
SourceMod 1.4.2 [2011-04-13]
URL: http://wiki.alliedmods.net/SourceMod_1.4.2_Release_Notes
User Changes:
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Fixed regression in SourceMod 1.4.0 causing SM to cause load errors on The Ship (bug 5216).
- Fixed toggling and player lag issues with sm_drug command (bugs 5217, 5218) (FlaminSarge).
Developer Changes:
- Updated TF2-specific defines and enums (bug 5194).
- Fixed StoreToAddress always writing 32 bits and throwing an error (bug 5248) (ProdigySim).
- Fixed crash with StoreToAddress if memory wasn't writable (bug 5252) (Dr!fter).
- Fixed return value of VoteMenuToAll (bug 5254) (VoiDeD).
- Fixed bug in command lower-casing API guarantee
-----------------------------
SourceMod 1.4.1 [2011-12-07]
URL: http://wiki.alliedmods.net/SourceMod_1.4.1_Release_Notes
User Changes:
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Added gamedata for Adrenaline Gamer 2 and No More Room in Hell.
- Fixed "not connected" error in reserve slots plugin (bug 5158) (ostrel).
- Fixed ff trigger output printing to all in triggerer's language (rather than viewer's language) (bug 5161).
- Fixed typo in one of basebans ban reasons (bug 5188).
- Fixed formatting error in Swedish "Vote Count" phrase (bug 5174).
Developer Changes:
- Fixed sp MaxClients not being updated on map changes after load (bug 5160).
- Removed GLIBC_2.7 dependency from spcomp.
- Increased buffer for sm_rcon command to fit larger responses (bug 5169).
- BaseComm now properly registers a library allowing it to be required by other plugins (bug 5156).
- Fixed TFHoliday enum values (bug 5155).
- Updated TF2_OnIsHolidayActive ret behavior to match doc (bug 5155).
- Added new TF2 deathflag and dmg custom defines (bug 5157).
-----------------------------
SourceMod 1.4.0 [2011-10-28]
URL: http://wiki.alliedmods.net/SourceMod_1.4.0_Release_Notes
User Changes:
- Added support for Max OS X (bug 4392).
- Added support for Bloody Good Time (bug 4780).
- Added support for E.Y.E Divine Cybermancy (bug 5035).
- Added gamedata for Nuclear Dawn.
- Added gamedata for International Online Soccer: Source (bug 5019).
- Added gamedata for Half-Life 2 Capture the Flag (bug 5114).
- Updated mapchooser and other base plugins with Nuclear Dawn specific fixes (bug 5117).
- Fixed ServerLang value not being read properly on startup (bug 4675).
- Added support for aliases in languages.cfg (bug 4858).
- Added output display to sm_rcon command (bug 5018).
- Flood protection bypass access can now be overridden with command name sm_flood_access (bug 4584).
- Added a reset argument to sm cvars command to revset cvar values to default (bug 5043).
- Fixed incorrect language identifiers for Chinese (both Trad. and Simplified) and Brazilian Portuguese not matching cl_language values (bug 5067).
- Added translation support for Bulgarian (bg).
- Fixed incorrect number of slots being hidden for reserve with sm_hideslots on Source 2009 with SourceTV or replay (bug 5094).
- sm_hideslots changes now take effect immediately instead of waiting until a client joins or leaves (bug 5094).
- Fixed sv_visiblemaxplayers getting stuck at previous max clients in some cases with reserves and SourceTV or replay (bug 5094).
- Removed error logging if an optional extension is not found (bug 5112).
- Fixed bots with semicolon in name being unkickable (bug 5120).
- Changed strings in ice-related funcommands to be translatable (bug 4540).
- Changed Bintools extension to use a single build for every engine (bug 4548).
Developer Changes:
- Provided native interface for basecomm (bug 2594).
- Client language detection is too late. (bug 3714) (Tony A. "GoD-Tony").
- Added ServerCommandEx native to execute server command and retrieve output (bug 3873).
- Added ability to update clientprefs cookies values on clients not currently connected (bug 3882) (databomb).
- Added library "matchmaking_ds" support to gamedata lookups (bug 4158).
- Rooted menu handles to callbacks (bug 4353).
- Fixed corner cases with ExplodeString (bug 4629). (Michael "LumiStance").
- Fixed return omission with else-after-return (bug 4852).
- Added OnConditionAdded and OnConditionRemoved forwards to TF2 extension (bug 4851).
- Added new natives and forward to the cstrike extension (bug 4732, bug 4985) (Dr!fter).
- Added WaitingForPlayers forwards to the TF2 extension (bug 4704) (CrimsonGT).
- Updated and added more TF2 condition, weapon, and damagecustom defines (multiple bug#s).
- Fixed TF2_RemoveCondition not always removing conditions (bug 4981).
- Fixed MaxClients not being updated correctly in some places with SourceTV or replay active (bug 4986).
- Fixed some vars not being marked for init on first compile pass (bug 4643).
- Increased symbol name limit to 63 characters (bug 4564) (javalia).
- Fixed crash when dynamic arrays run out of memory (bug 4632).
- Fixed a crash that could happen from looking up out-of-bounds edict or entity indexes (bug 5080).
- Fixed client serials not getting cleared on disconnect (bug 5121).
- Added error on declaring arrays that the compiler is too buggy to handle (bug 4977).
- Removed reliance on gamedata for multiple SDKTools functions in ep2 and later (bug 4899).
- Added InvalidateClient and ReconnectClient natives to SDKTools (bug 4931) (Brian "Afronanny" Simon).
- Added ability to lookup and set values on the gamerules class (bug 4983.
- BaseComm now uses AddCommandListener for chat hooks (bug 4991).
- Fixed shutdown bug in SDKTools (bug 5063).
- Fixed MM-enabled extensions continuing to load after failing MM attach (bug 5042).
- Added GetDistGainFromSoundLevel native to SDKTools (bug 5066) (javalia).
- Added CheckAccess native to check an AdminId's command access (bug 5083).
- Fixed GetEntProp not sign-extending unsigned values less than 32 bits (bug 5105).
- Fixed crashing when calling CreateEntityByName or CreateFakeClient when no map is running (now errors) (bug 5119).
- Fixed erring in kick function (e. bad translation) causing client to become unkickable until disconnect (bug 5120).
- Fixed KickClientEx not immediately kicking client if client was in kick queue (bug 5120).
- Added IsClientSourceTV and IsClientReplay natives (bug 5124).
- Added support for getting and setting individual array elements with Get/Set EntProp functions (bug 4160).
- Added support for threaded query handles to SQL_GetInsertId and SQL_GetAffectedRows (bug 4699) (Nephyrin).
- Added a GetGameRules function to ISDKTools for extensions to easily get the GameRules class pointer (bug 4707).
- Added GetMessageName to IUserMessages (bug 4573) (Zach "theY4Kman" Kanzler)
- Added HintTextMsg to IGameHelpers (bug 4950).
- Added ProcessTargetString simple filter API (bug 4404).
- Moved much functionality from core bins to logic bin (bug 4406, bug 4402).
- Fixed bogus asserts in sp compiler (bug 4486, bug 4487).
- Greatly improved sp compiler performance (~5x overall speedup) (bug 3820, bug 4493, bug 4495).
- Changed entity output detours to use CDetour (bug 4416).
- Enhanced nominations API (bug 4677) (CrimsonGT).
- Added Linux support for profiling natives (bug 4927).
- Added a new ValveCallType that allows for arbitrary |this| parameters, as well as associated features in gamedata and for reading/writing memory (bug 3520) (Downtown1).
- Updated TF2 extension to handle Valve's changes to the "holiday" system (bug 5150).
-----------------------------
SourceMod 1.3.8 [2011-06-23]
URL: http://wiki.alliedmods.net/SourceMod_1.3.8_Release_Notes
User Changes:
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Updated support for various games, including Garry's Mod, Zombie Panic, and Dino D-Day.
- Added gamedata for Eternal Silence.
- Fixed libgcc_s.so.1 load error present on some systems (bug 4876).
- Handle leak notices now print to error log (in addition fatal log) (bug 4929).
- Translator now properly falls back on bad server language (bug 4861).
- Fixed invalid client errors from bad MaxClients value when SourceTV is late-loaded (bug 4881).
- Fixed crash on plugin unload when two commands exist with same name, different casing (bug 4698).
Developer Changes:
- Updated TF2 condition defines (bug 4916).
- Fixed var names and docs for TF2_MakeBleed native (bug 4928).
- Removed compiler double include check (bug 4863).
- Fixed plugin compile errors when using GetEntityClassname (bug 4798).
---------------------------
SourceMod 1.3.7 [2011-04-15]
URL: http://wiki.alliedmods.net/SourceMod_1.3.7_Release_Notes
User Changes:
- Updated support for latest OrangeBox engine changes (CS:S, DoD:S, TF2, HL2DM, GMod).
- Updated support for various games, including Zombie Panic, CS ProMod, Empires, and GoldenEye: Source.
- Added gamedata for Dino D-Day.
- Fix precedence of voice mute flag versus specific client overrides (bug 4826).
- Fix mistaken unhooking of voice hooks (bug 4804).
- Fixed graphical glitches with funcommands effects in L4D1 (bug 3486).
- Fixed bug in nominations that could cause "Unknown command" error (bug 4797).
- Removed tv_enable hook to fix rare max client count issue (bug 4791).
- Added missing unhooking of ClientConnect in PlayerManager (bug 4749).
- Fixed sm_rtv printing "unknown command" (bug 4730).
- Fixed voting crash when client console, chat, and SourceTV are enabled (bug 4676).
- Fixed CDetour crash in TF2 extension when last plugin using forward is unloaded (bug 4713).
Developer Changes:
- SetEntProp now marks edict state as changed (bug 4855).
- Added GetEntityClassname stock (bug 4798).
- Fix compiler hanging when #including a directory (bug 4822).
- Added GetEntityFlags and SetEntityFlags natives for better cross-engine compatibility. (bug 4809).
- Fixed ClientPrefs natives not being marked optional when REQUIRE_EXTENSIONS not defined (bug 4839).
- Changed some instances of LogMessage to LogAction (bug 4649).
- Added some new language natives (bug 4613).
- Fixed SetTeamScore not updating score on client (bug 2736).
- Raised MAXPLAYERS from 64 to 65 (bug 4490).
- Added and updated many TF2-specific defines in tf2.inc and tf2_stocks.inc.
- Fixed TF2_GetPlayerConditionFlags no longer necessarily returning all set flags (bug 4726).
- Fixed profiler flush not clearing, added 'report' and 'clear' (bug 4674).
- Fixed GetPlayerDecalFile crash on L4D and L4D2 (bug 4729).
- Fixed TF2_OnGetHoliday detour no longer firing under all circumstances (bug 4700).
- Added TF2_IsPlayerInDuel native to TF2 extension (bug 4695).
----------------------------
SourceMod 1.3.6 [2010-10-31]
URL: http://wiki.alliedmods.net/SourceMod_1.3.6_Release_Notes
User Changes:
- Updated support for latest Left 4 Dead 1 (bug 4681).
Developer Changes:
- Updated TF2 custom kill defines (bug 4682).
----------------------------
SourceMod 1.3.5 [2010-10-17]
URL: http://wiki.alliedmods.net/SourceMod_1.3.5_Release_Notes
User Changes:
- Updated support for CS:S, Garry's Mod, DoD:S, TF2, HL2DM.
- Added support for Firearms: Source (bug 4537).
- Added support for Fistful of Frags (bug 3883).
- Added support for Alien Swarm (bug 4530).
- Fixed living players hearing dead players if alltalk is disabled while deadtalk is on (bug 4533, thanks Zach Callear).
- Fixed timeleft not getting reset on Game_Commencing in CS:S (bug 4557).
- Fixed PlayerRunCmd being hooked when not used (bug 3990).
- Fixed errors and missing effects caused by missing sprites on L4D2 (bug 4512).
- Fixed 'sm plugins' public command skipping plugins in recommended listing (bug 4501).
- Fixed corruption with large database.cfg files (bug 4286).
Developer Changes:
- Added TF2 object stocks (bug 4536).
- Added TF2_MakeBleed native to TF2 ext (bug 4542).
- Added support for logical entities in Synergy (bug 4534).
- Updated TF2 conditions enum and defines (bug 4526).
- Fixed potential crash with IMemUtils::FindPattern on Linux (bug 4554).
----------------------------
SourceMod 1.3.4 [2010-07-18]
URL: http://wiki.alliedmods.net/SourceMod_1.3.4_Release_Notes
User Changes:
- Support for latest TF update (bug 4506).
- Support for latest L4D2 update (bug 4509).
Developer Changes:
- Added FindFlagChar native (bug 3776).
- Added GetConVarDefault native (bug 4502).
- Added forward for TF's GetHoliday function (bug 4462).
----------------------------
SourceMod 1.3.3 [2010-06-23]
URL: http://wiki.alliedmods.net/SourceMod_1.3.3_Release_Notes
User Changes:
- Added support for CS:S on Orange Box
- Added gamedata for Resistance and Liberation (bug 4418).
- Updated gamedata for SourceForts, Empires, Obsidian Conflict, Zombie Master.
- Fixed memory corruption and leaks with some voice functionality (bug 4415).
- Fixed UI bug in sm_motd (bug 4460).
Developer Changes:
- Added new player condition (TFCond_CritCola, bug 4447).
- Fixed clientprefs deleting cookies twice in rare cases (bug 4412).
- Fixed OnClientConnected forward not firing for bots (bug 4443).
- Fixed sm_dump_datamaps crash (bug 4424).
- Fixed switch case comparisons failing with large numbers (bug 4457).
- Fixed rare crash in output hooks (bug 4422).
- Fixed bug with dynamically sized arrays being sliced (bug 4428).
- Fixed SendConVarValue() on TF2, DOD:S, L4D, and L4D2 (bug 4273).
- Fixed TF2 natives not being marked optional (bug 4389).
----------------------------
SourceMod 1.3.2 [2010-05-02]
URL: http://wiki.alliedmods.net/SourceMod_1.3.2_Release_Notes
User Changes:
- Support for recent TF, DoD, and L4D2 updates (bug 4356, bug 4361, bug 4371, bug 4374, bug 4375).
- Fixed rare crash when replicating cvars to clients (bug 4315).
- Lots of extra game support for Insurgency, ZPS, CSProMod, PVKII, and FortressForever (thanks
Nicholas "psychonic" hastings).
Developer Changes:
- Added TF functions for stunning, conditions, regeneration, and power play (bug 4166, bug 4331).
----------------------------
SourceMod 1.3.1 [2010-02-09]
URL: http://wiki.alliedmods.net/SourceMod_1.3.1_Release_Notes
User Changes:
- Added extended support for CSProMod (bug 4255).
- Fixed client disconnect crash on many third party games (bug 4231).
- Improved support for Battlegrounds 2 (bug 4146).
- Improved support for Insurgency (bug 4180).
- Improved support for Garry's Mod (bug 4230, bug 4268).
- Improved support for Synergy (bug 4235).
- Updated Day of Defeat support for 20010123 update (bug 4262).
- Fixed Webternet extension not loading on Windows 2000 (bug 4234).
Developer Changes:
- Fixed compiler complaints when using |any| tag on array arguments (bug 4274).
- Fixed GetClientCookieTime not being exported (bug 4237).
- Fixed potential crash in entity handling code (bug 4249).
----------------------------
SourceMod 1.3.0 [2010-01-15]
URL: http://wiki.alliedmods.net/SourceMod_1.3.0_Release_Notes
Major Features:
* Left 4 Dead 2 support
* Non-networked entity support
User Changes:
- Added Left 4 Dead 2 support (bug 4075).
- Added much richer voting progress feedback (bug 1997).
- Improved support for various third-party games (Nicholas "psychonic" Hastings).
- Added @spec target (bug 2718).
- Added sm_resetcvar command (bug 3636).
- Added "motd" chat trigger (bug 2694).
- Updated GeoIP to OCT-2009.
- Fixed rare map vote error (bug 3905).
- Fixed small leak in the nominations plugin (bug 4104).
- Fixed last client being excluded from some command effects (bug 3984).
- Fixed crashes in plugin [|un|re]loading (bug 4034, bug 4038, bug 4044, bug 4153).
- Special target "@me" is now filtered for certain statuses properly (bug 4000).
- Improved non-admin to admin chat (bug 3844).
- Removed "auto.*" extension folders (bug 3949).
Developer Changes:
- Added non-networked entity support (bug 2459).
- Added improved random number generator (bug 3831).
- Added GetClientCookieTime native (bug 3736).
- Added AskPluginLoad2 callback (bug 3716).
- Added PlayerRunCmd callback (bug 3289).
- Added PointOutsideWorld native (bug 3906).
- Added API for "blanket" command hooks (bug 4015).
- Added ability to test for SourceMod features (bug 4021).
- Added ability to change broadcast status on hooked events (bug 3886).
- OnClientCommand no longer receives unconnected clients (bug 3732).
- Fixed various bugs in client listening API (bug 3818).
- Fixed crash in BanClient (bug 3912).
- Fixed various crashes in self-removing callbacks (bug 4059).
- Fixed rare HUD text crash on TF (bug 4016).
- Fixed OnConfigsExecuted not running on EP1 games with large configs (bug 3828).
- Fixed entity output hooks not working (bug 3988).
- Gamedata folder matches are now case-insensitive (bug 3913).
- Blocked plugins from hooking "sm" command (bug 4013).
----------------------------
SourceMod 1.2.4 [2009-10-03]
URL: http://wiki.alliedmods.net/SourceMod_1.2.4_Release_Notes
- Updated for L4D changes (bugs 4032, 4033, 4035).
- Updated GeoLite Country database for GeoIP extension.
- Fixed crash when block-loading more than eight plugins (bug 4034).
- Fixed rare crash in hudtext code on TF (bug 4016).
- Fixed crash when reloading a blocked plugin failed (bug 4038).
- Fixed Huntsman not firing critical callback on TF (bug 3927).
- Registering the "sm" command no longer has any effect (bug 4013).
- Fixed translation bug in extension API (bug 4010).
---------------------------- ----------------------------
SourceMod 1.2.3 [2009-08-28] SourceMod 1.2.3 [2009-08-28]
-1
View File
@@ -1,7 +1,6 @@
//This file unloads all plugins, re-loads a few "safe" ones, and then prevents //This file unloads all plugins, re-loads a few "safe" ones, and then prevents
//any more plugins from being loaded. //any more plugins from being loaded.
sm plugins unload_all sm plugins unload_all
sm plugins load_unlock
sm plugins load basebans.smx sm plugins load basebans.smx
sm plugins load basecommands.smx sm plugins load basecommands.smx
sm plugins load admin-flatfile.smx sm plugins load admin-flatfile.smx
+3 -28
View File
@@ -80,21 +80,21 @@ sm_reserve_type 0
sm_reserved_slots 0 sm_reserved_slots 0
// Specifies whether or not reserved slots will be hidden (subtracted from max // Specifies whether or not reserved slots will be hidden (subtracted from max
// slot count). Valid values are 0 (Visible) or 1 (Hidden). // slot count). Valid values are 0 (visible) or 1 (hidden).
// -- // --
// Requires: reservedslots.smx // Requires: reservedslots.smx
// Default: 0 // Default: 0
sm_hide_slots 0 sm_hide_slots 0
// Specifies whether or not non-admins can send messages to admins using // Specifies whether or not non-admins can send messages to admins using
// say_team @<message>. Valid values are 0 (Disabled) or 1 (Enabled) // say_team @<message>. Valid values are 0 (disabled) or 1 (enabled)
// -- // --
// Requires: basechat.smx // Requires: basechat.smx
// Default: 1 // Default: 1
sm_chat_mode 1 sm_chat_mode 1
// Specifies whether or not "timeleft" will automaticly be triggered every // Specifies whether or not "timeleft" will automaticly be triggered every
// x seconds. Valid values are 0 (Disabled) to 1800 seconds. // x seconds. Valid values are 0 (disabled) to 1800 seconds.
// -- // --
// Requires: basetriggers.smx // Requires: basetriggers.smx
// Default: 0 // Default: 0
@@ -107,28 +107,3 @@ sm_timeleft_interval 0
// Requires: basetriggers.smx // Requires: basetriggers.smx
// Default: 1 // Default: 1
sm_trigger_show 1 sm_trigger_show 1
// Specifies whether or not to display vote progress to clients in the
// "hint" box (near the bottom of the screen in most games).
// Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_hintbox 0
// Specifies whether or not to display vote progress to clients in the
// chat area. Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_chat 0
// Specifies whether or not to display vote progress in the server console.
// Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_console 0
// Specifies whether or not to display vote progress to clients in the
// client console. Valid values are 0 (Disabled) or 1 (Enabled).
// --
// Default: 0
sm_vote_progress_client_console 0
-18
View File
@@ -107,22 +107,4 @@
* Currently this will log details about the gamedata updating process. * Currently this will log details about the gamedata updating process.
*/ */
"DebugSpew" "no" "DebugSpew" "no"
/**
* If set to yes, SourceMod will validate steamid auth strings with the Steam backend before giving out admin access.
* This can prevent malicious users from impersonating admins with stolen Steam apptickets.
* If Steam is down, admins will not be authenticated until Steam comes back up.
* This option increases the security of your server, but is still experimental.
*/
"SteamAuthstringValidation" "no"
/**
* Enables or disables whether SourceMod blocks known or potentially malicious plugins from loading.
* It is STRONGLY advised that this is left enabled, there have been cases in the past with plugins that
* allow anyone to delete files on the server, gain full rcon control, etc.
*
* "yes" - Block malware or illegal plugins from loading (default)
* "no" - Warn about malware or illegal plugins loading
*/
"BlockBadPlugins" "yes"
} }
-2
View File
@@ -2,8 +2,6 @@
{ {
"driver_default" "mysql" "driver_default" "mysql"
// When specifying "host", you may use an IP address, a hostname, or a socket file path
"default" "default"
{ {
"driver" "default" "driver" "default"
Binary file not shown.
-28
View File
@@ -1,28 +0,0 @@
# vim: set ts=2 sw=2 tw=99 noet:
import sys
try:
from ambuild2 import run
except:
try:
import ambuild
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
except:
sys.stderr.write('AMBuild must be installed to build this project.\n')
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
sys.exit(1)
run = run.PrepareBuild(sourcePath=sys.path[0])
run.default_build_folder = 'obj-' + run.target_platform
run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols')
run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization')
run.options.add_option('--no-mysql', action='store_false', default=True, dest='hasMySql',
help='Disable building MySQL extension')
run.options.add_option('-s', '--sdks', default='all', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or '
'comma-delimited list of engine names (default: %default)')
run.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump',
default=False, help='Dump and upload breakpad symbols')
run.Configure()
-124
View File
@@ -1,124 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name]
binary_name = 'sourcemod.' + sdk.ext
binary = SM.HL2Library(builder, binary_name, sdk)
compiler = binary.compiler
if sdk.name == 'csgo':
# Protobuf 2.3 headers have some signed/unsigned compares. I believe that it's fixed in later versions, but Valve.
if compiler.cxx.behavior == 'gcc':
compiler.cflags += ['-Wno-sign-compare']
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.3.0', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
]
elif sdk.name == 'dota':
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.4.1', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf')
]
if builder.target_platform == 'linux':
compiler.postlink += ['-lpthread', '-lrt']
if sdk.name == 'csgo' or sdk.name == 'dota':
if builder.target_platform == 'linux':
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
elif builder.target_platform == 'mac':
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif builder.target_platform == 'windows':
if 'DEBUG' in compiler.defines:
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs2010', 'libprotobuf.lib')
else:
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs2010', 'libprotobuf.lib')
compiler.linkflags.insert(0, binary.Dep(lib_path))
binary.sources += [
'AdminCache.cpp',
'MenuStyle_Valve.cpp',
'logic_bridge.cpp',
'smn_entities.cpp',
'sm_stringutil.cpp',
'MenuVoting.cpp',
'smn_events.cpp',
'smn_menus.cpp',
'sm_trie.cpp',
'CDataPack.cpp',
'frame_hooks.cpp',
'smn_nextmap.cpp',
'sourcemm_api.cpp',
'ChatTriggers.cpp',
'smn_player.cpp',
'sourcemod.cpp',
'concmd_cleaner.cpp',
'HalfLife2.cpp',
'NextMap.cpp',
'ConCmdManager.cpp',
'ConVarManager.cpp',
'LibrarySys.cpp',
'PlayerManager.cpp',
'TimerSys.cpp',
'CoreConfig.cpp',
'Logger.cpp',
'smn_halflife.cpp',
'smn_console.cpp',
'UserMessages.cpp',
'MenuManager.cpp',
'smn_core.cpp',
'smn_hudtext.cpp',
'smn_usermsgs.cpp',
'MenuStyle_Base.cpp',
'smn_keyvalues.cpp',
'smn_vector.cpp',
'EventManager.cpp',
'MenuStyle_Radio.cpp',
'sm_autonatives.cpp',
'sm_srvcmds.cpp',
'ConsoleDetours.cpp',
'NativeInvoker.cpp',
'smn_database.cpp',
'ForwardSys.cpp',
'Database.cpp',
'DebugReporter.cpp',
'ShareSys.cpp',
'PluginSys.cpp',
'HandleSys.cpp',
'NativeOwner.cpp',
'ExtensionSys.cpp',
'smn_fakenatives.cpp',
'smn_filesystem.cpp',
'ADTFactory.cpp',
'PluginInfoDatabase.cpp',
]
if sdk.name in ['csgo', 'dota']:
binary.sources += ['smn_protobuf.cpp']
else:
binary.sources += ['smn_bitbuffer.cpp']
if sdk.name == 'csgo':
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
]
elif sdk.name == 'dota':
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'networkbasetypes.pb.cc'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'ai_activity.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'protobuf', 'usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_commonmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'dota', 'protobuf', 'dota_usermessage_helpers.cpp'),
]
SM.binaries += [builder.Add(binary)]
+2 -2
View File
@@ -1719,7 +1719,7 @@ bool AdminCache::CanAdminUseCommand(int client, const char *cmd)
} }
} }
return g_ConCmds.CheckClientCommandAccess(client, cmd, bits); return g_ConCmds.CheckCommandAccess(client, cmd, bits);
} }
unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level) unsigned int AdminCache::SetGroupImmunityLevel(GroupId gid, unsigned int level)
@@ -1794,7 +1794,7 @@ bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool o
GetCommandOverride(cmd, Override_Command, &bits); GetCommandOverride(cmd, Override_Command, &bits);
} }
return g_ConCmds.CheckClientCommandAccess(client, cmd, bits) ? 1 : 0; return g_ConCmds.CheckCommandAccess(client, cmd, bits) ? 1 : 0;
} }
void iterator_glob_basic_override(Trie *pTrie, const char *key, void **value, void *data) void iterator_glob_basic_override(Trie *pTrie, const char *key, void **value, void *data)
@@ -29,9 +29,6 @@
* Version: $Id$ * Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_CELLARRAY_H_
#define _INCLUDE_SOURCEMOD_CELLARRAY_H_
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -207,6 +204,3 @@ private:
size_t m_AllocSize; size_t m_AllocSize;
size_t m_Size; size_t m_Size;
}; };
#endif /* _INCLUDE_SOURCEMOD_CELLARRAY_H_ */
+61 -132
View File
@@ -34,8 +34,8 @@
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "ConCmdManager.h" #include "ConCmdManager.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "Translator.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "logic_bridge.h"
/* :HACKHACK: We can't SH_DECL here because ConCmdManager.cpp does. /* :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 * While the OB build only runs on MM:S 1.6.0+ (SH 5+), the older one
@@ -59,17 +59,13 @@ ChatTriggers g_ChatTriggers;
bool g_bSupressSilentFails = false; bool g_bSupressSilentFails = false;
ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false), ChatTriggers::ChatTriggers() : m_pSayCmd(NULL), m_bWillProcessInPost(false),
m_ReplyTo(SM_REPLY_CONSOLE) m_bTriggerWasSilent(false), m_ReplyTo(SM_REPLY_CONSOLE)
{ {
m_PubTrigger = sm_strdup("!"); m_PubTrigger = sm_strdup("!");
m_PrivTrigger = sm_strdup("/"); m_PrivTrigger = sm_strdup("/");
m_PubTriggerSize = 1; m_PubTriggerSize = 1;
m_PrivTriggerSize = 1; m_PrivTriggerSize = 1;
m_bIsChatTrigger = false; m_bIsChatTrigger = false;
m_bPluginIgnored = false;
#if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = false;
#endif
} }
ChatTriggers::~ChatTriggers() ChatTriggers::~ChatTriggers()
@@ -113,13 +109,11 @@ void ChatTriggers::OnSourceModAllInitialized()
{ {
m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell); m_pShouldFloodBlock = g_Forwards.CreateForward("OnClientFloodCheck", ET_Event, 1, NULL, Param_Cell);
m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell); m_pDidFloodBlock = g_Forwards.CreateForward("OnClientFloodResult", ET_Event, 2, NULL, Param_Cell, Param_Cell);
m_pOnClientSayCmd = g_Forwards.CreateForward("OnClientSayCommand", ET_Event, 3, NULL, Param_Cell, Param_String, Param_String);
m_pOnClientSayCmd_Post = g_Forwards.CreateForward("OnClientSayCommand_Post", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_String);
} }
void ChatTriggers::OnSourceModAllInitialized_Post() void ChatTriggers::OnSourceModAllInitialized_Post()
{ {
logicore.AddCorePhraseFile("antiflood.phrases"); g_pCorePhrases->AddPhraseFile("antiflood.phrases");
} }
void ChatTriggers::OnSourceModGameInitialized() void ChatTriggers::OnSourceModGameInitialized()
@@ -137,62 +131,23 @@ void ChatTriggers::OnSourceModGameInitialized()
SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Pre, false); 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); SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayTeamCmd, this, &ChatTriggers::OnSayCommand_Post, true);
} }
#if SOURCE_ENGINE == SE_EPISODEONE
m_bIsINS = (strcmp(g_SourceMod.GetGameFolderName(), "insurgency") == 0);
if (m_bIsINS)
{
m_pSay2Cmd = FindCommand("say2");
if (m_pSay2Cmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
m_pSaySquadCmd = FindCommand("say_squad");
if (m_pSaySquadCmd)
{
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_ADD_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#endif
} }
void ChatTriggers::OnSourceModShutdown() 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) 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_Post, true);
SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false); SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pSayCmd, this, &ChatTriggers::OnSayCommand_Pre, false);
} }
if (m_pSayTeamCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSayTeamCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
}
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS && m_pSay2Cmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSay2Cmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
if (m_pSaySquadCmd)
{
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Pre), false);
SH_REMOVE_HOOK(ConCommand, Dispatch, m_pSaySquadCmd, SH_MEMBER(this, &ChatTriggers::OnSayCommand_Post), true);
}
#endif
g_Forwards.ReleaseForward(m_pShouldFloodBlock); g_Forwards.ReleaseForward(m_pShouldFloodBlock);
g_Forwards.ReleaseForward(m_pDidFloodBlock); g_Forwards.ReleaseForward(m_pDidFloodBlock);
g_Forwards.ReleaseForward(m_pOnClientSayCmd);
g_Forwards.ReleaseForward(m_pOnClientSayCmd_Post);
} }
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
@@ -203,10 +158,24 @@ void ChatTriggers::OnSayCommand_Pre()
{ {
CCommand command; CCommand command;
#endif #endif
int client = g_ConCmds.GetCommandClient(); int client;
CPlayer *pPlayer;
client = g_ConCmds.GetCommandClient();
m_bIsChatTrigger = false; m_bIsChatTrigger = false;
m_bWasFloodedMessage = false; m_bWasFloodedMessage = false;
m_bPluginIgnored = false;
/* The server console cannot do this */
if (client == 0 || (pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
{
RETURN_META(MRES_IGNORED);
}
/* We guarantee the client is connected */
if (!pPlayer->IsConnected())
{
RETURN_META(MRES_IGNORED);
}
const char *args = command.ArgS(); const char *args = command.ArgS();
@@ -215,38 +184,22 @@ void ChatTriggers::OnSayCommand_Pre()
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
/* Save these off for post hook as the command data returned from the engine in older engine versions
* can be NULL, despite the data still being there and valid. */
m_Arg0Backup = command.Arg(0);
m_ArgSBackup = command.ArgS();
/* The server console cannot do this */
if (client == 0)
{
cell_t res = CallOnClientSayCommand(client);
if (res >= Pl_Handled)
{
m_bPluginIgnored = (res >= Pl_Stop);
RETURN_META(MRES_SUPERCEDE);
}
RETURN_META(MRES_IGNORED);
}
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
/* We guarantee the client is connected */
if (!pPlayer || !pPlayer->IsConnected())
{
RETURN_META(MRES_IGNORED);
}
/* Check if we need to block this message from being sent */ /* Check if we need to block this message from being sent */
if (ClientIsFlooding(client)) if (ClientIsFlooding(client))
{ {
char buffer[128]; char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "Flooding the server", &client)) if (!CoreTranslate(
buffer,
sizeof(buffer),
"%T",
2,
NULL,
"Flooding the server",
&client))
{
UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!"); UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
}
/* :TODO: we should probably kick people who spam too much. */ /* :TODO: we should probably kick people who spam too much. */
@@ -267,13 +220,6 @@ void ChatTriggers::OnSayCommand_Pre()
is_quoted = true; is_quoted = true;
} }
#if SOURCE_ENGINE == SE_EPISODEONE
if (m_bIsINS && strcmp(m_Arg0Backup, "say2") == 0 && strlen(args) >= 4)
{
args += 4;
}
#endif
bool is_trigger = false; bool is_trigger = false;
bool is_silent = false; bool is_silent = false;
@@ -290,28 +236,38 @@ void ChatTriggers::OnSayCommand_Pre()
args = &args[m_PrivTriggerSize]; args = &args[m_PrivTriggerSize];
} }
if (!is_trigger)
{
RETURN_META(MRES_IGNORED);
}
/** /**
* Test if this is actually a command! * Test if this is actually a command!
*/ */
if (is_trigger && PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted)) if (!PreProcessTrigger(PEntityOfEntIndex(client), args, is_quoted))
{ {
m_bIsChatTrigger = true; CPlayer *pPlayer;
if (is_silent
/** && g_bSupressSilentFails
* We'll execute it in post. && client != 0
*/ && (pPlayer = g_Players.GetPlayerByIndex(client)) != NULL
m_bWillProcessInPost = true; && pPlayer->GetAdminId() != INVALID_ADMIN_ID)
{
RETURN_META(MRES_SUPERCEDE);
}
RETURN_META(MRES_IGNORED);
} }
cell_t res = CallOnClientSayCommand(client); m_bIsChatTrigger = true;
if (res >= Pl_Handled) /**
{ * We'll execute it in post.
m_bPluginIgnored = (res >= Pl_Stop); */
RETURN_META(MRES_SUPERCEDE); m_bWillProcessInPost = true;
} m_bTriggerWasSilent = is_silent;
if (is_silent && (m_bIsChatTrigger || (g_bSupressSilentFails && pPlayer->GetAdminId() != INVALID_ADMIN_ID))) /* If we're silent, block */
if (is_silent)
{ {
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
@@ -326,33 +282,19 @@ void ChatTriggers::OnSayCommand_Post(const CCommand &command)
void ChatTriggers::OnSayCommand_Post() void ChatTriggers::OnSayCommand_Post()
#endif #endif
{ {
int client = g_ConCmds.GetCommandClient(); m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
if (m_bWillProcessInPost) if (m_bWillProcessInPost)
{ {
/* Reset this for re-entrancy */ /* Reset this for re-entrancy */
m_bWillProcessInPost = false; m_bWillProcessInPost = false;
/* Execute the cached command */ /* Execute the cached command */
int client = g_ConCmds.GetCommandClient();
unsigned int old = SetReplyTo(SM_REPLY_CHAT); unsigned int old = SetReplyTo(SM_REPLY_CHAT);
serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute); serverpluginhelpers->ClientCommand(PEntityOfEntIndex(client), m_ToExecute);
SetReplyTo(old); SetReplyTo(old);
} }
if (m_bPluginIgnored)
{
m_bPluginIgnored = false;
}
else if (!m_bWasFloodedMessage && !m_bIsChatTrigger && m_pOnClientSayCmd_Post->GetFunctionCount() != 0)
{
m_pOnClientSayCmd_Post->PushCell(client);
m_pOnClientSayCmd_Post->PushString(m_Arg0Backup);
m_pOnClientSayCmd_Post->PushString(m_ArgSBackup);
m_pOnClientSayCmd_Post->Execute(NULL);
}
m_bIsChatTrigger = false;
m_bWasFloodedMessage = false;
} }
bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted) bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted)
@@ -429,19 +371,6 @@ bool ChatTriggers::PreProcessTrigger(edict_t *pEdict, const char *args, bool is_
return true; return true;
} }
cell_t ChatTriggers::CallOnClientSayCommand(int client)
{
cell_t res = Pl_Continue;
if (!m_bIsChatTrigger && m_pOnClientSayCmd->GetFunctionCount() != 0)
{
m_pOnClientSayCmd->PushCell(client);
m_pOnClientSayCmd->PushString(m_Arg0Backup);
m_pOnClientSayCmd->PushString(m_ArgSBackup);
m_pOnClientSayCmd->Execute(&res);
}
return res;
}
unsigned int ChatTriggers::SetReplyTo(unsigned int reply) unsigned int ChatTriggers::SetReplyTo(unsigned int reply)
{ {
unsigned int old = m_ReplyTo; unsigned int old = m_ReplyTo;
+1 -14
View File
@@ -69,34 +69,21 @@ public:
private: private:
bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted); bool PreProcessTrigger(edict_t *pEdict, const char *args, bool is_quoted);
bool ClientIsFlooding(int client); bool ClientIsFlooding(int client);
cell_t CallOnClientSayCommand(int client);
private: private:
ConCommand *m_pSayCmd; ConCommand *m_pSayCmd;
ConCommand *m_pSayTeamCmd; ConCommand *m_pSayTeamCmd;
#if SOURCE_ENGINE == SE_EPISODEONE
ConCommand *m_pSay2Cmd;
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
ConCommand *m_pSaySquadCmd;
#endif
char *m_PubTrigger; char *m_PubTrigger;
size_t m_PubTriggerSize; size_t m_PubTriggerSize;
char *m_PrivTrigger; char *m_PrivTrigger;
size_t m_PrivTriggerSize; size_t m_PrivTriggerSize;
bool m_bWillProcessInPost; bool m_bWillProcessInPost;
bool m_bTriggerWasSilent;
bool m_bIsChatTrigger; bool m_bIsChatTrigger;
bool m_bWasFloodedMessage; bool m_bWasFloodedMessage;
bool m_bPluginIgnored;
unsigned int m_ReplyTo; unsigned int m_ReplyTo;
char m_ToExecute[300]; char m_ToExecute[300];
const char *m_Arg0Backup;
const char *m_ArgSBackup;
IForward *m_pShouldFloodBlock; IForward *m_pShouldFloodBlock;
IForward *m_pDidFloodBlock; IForward *m_pDidFloodBlock;
IForward *m_pOnClientSayCmd;
IForward *m_pOnClientSayCmd_Post;
#if SOURCE_ENGINE == SE_EPISODEONE
bool m_bIsINS;
#endif
}; };
extern ChatTriggers g_ChatTriggers; extern ChatTriggers g_ChatTriggers;
+92 -47
View File
@@ -34,9 +34,9 @@
#include "AdminCache.h" #include "AdminCache.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "Translator.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include "ChatTriggers.h" #include "ChatTriggers.h"
#include "logic_bridge.h"
ConCmdManager g_ConCmds; ConCmdManager g_ConCmds;
@@ -226,38 +226,30 @@ void ConCmdManager::SetCommandClient(int client)
m_CmdClient = client + 1; m_CmdClient = client + 1;
} }
ConCmdInfo *ConCmdManager::FindInTrie(const char *name)
{
ConCmdInfo *pInfo;
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
return NULL;
return pInfo;
}
ConCmdList::iterator ConCmdManager::FindInList(const char *cmd)
{
List<ConCmdInfo *>::iterator iter = m_CmdList.begin();
while (iter != m_CmdList.end())
{
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
break;
iter++;
}
return iter;
}
ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int args, ResultType type) ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int args, ResultType type)
{ {
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
if ((pInfo = FindInTrie(cmd)) == NULL) if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
{ {
ConCmdList::iterator item = FindInList(cmd); List<ConCmdInfo *>::iterator iter;
if (item == m_CmdList.end())
pInfo = NULL;
iter = m_CmdList.begin();
while (iter != m_CmdList.end())
{
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
{
pInfo = (*iter);
break;
}
iter++;
}
if (pInfo == NULL)
{
return type; return type;
pInfo = *item; }
} }
cell_t result = type; cell_t result = type;
@@ -322,20 +314,35 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
*/ */
const char *cmd = g_HL2.CurrentCommandName(); const char *cmd = g_HL2.CurrentCommandName();
ConCmdInfo *pInfo = FindInTrie(cmd); ConCmdInfo *pInfo;
if (pInfo == NULL) if (!sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
{ {
/* Unfortunately, we now have to do a slow lookup because Valve made client commands /* Unfortunately, we now have to do a slow lookup because Valve made client commands
* case-insensitive. We can't even use our sortedness. * case-insensitive. We can't even use our sortedness.
*/ */
if (client == 0 && !engine->IsDedicatedServer()) if (client == 0 && !engine->IsDedicatedServer())
{
return; return;
}
ConCmdList::iterator item = FindInList(cmd); List<ConCmdInfo *>::iterator iter;
if (item == m_CmdList.end())
return;
pInfo = *item; pInfo = NULL;
iter = m_CmdList.begin();
while (iter != m_CmdList.end())
{
if (strcasecmp((*iter)->pCmd->GetName(), cmd) == 0)
{
pInfo = (*iter);
break;
}
iter++;
}
if (pInfo == NULL)
{
return;
}
} }
/* This is a hack to prevent say triggers from firing on messages that were /* This is a hack to prevent say triggers from firing on messages that were
@@ -450,7 +457,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
} }
} }
bool ConCmdManager::CheckClientCommandAccess(int client, const char *cmd, FlagBits cmdflags) bool ConCmdManager::CheckCommandAccess(int client, const char *cmd, FlagBits cmdflags)
{ {
if (cmdflags == 0 || client == 0) if (cmdflags == 0 || client == 0)
{ {
@@ -471,11 +478,7 @@ bool ConCmdManager::CheckClientCommandAccess(int client, const char *cmd, FlagBi
return false; return false;
} }
return CheckAdminCommandAccess(player->GetAdminId(), cmd, cmdflags); AdminId adm = player->GetAdminId();
}
bool ConCmdManager::CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits cmdflags)
{
if (adm != INVALID_ADMIN_ID) if (adm != INVALID_ADMIN_ID)
{ {
FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective); FlagBits bits = g_Admins.GetAdminFlags(adm, Access_Effective);
@@ -528,7 +531,7 @@ bool ConCmdManager::CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBi
bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin) bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin)
{ {
if (CheckClientCommandAccess(client, cmd, pAdmin->eflags)) if (CheckCommandAccess(client, cmd, pAdmin->eflags))
{ {
return true; return true;
} }
@@ -537,7 +540,7 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
/* If we got here, the command failed... */ /* If we got here, the command failed... */
char buffer[128]; char buffer[128];
if (!logicore.CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client)) if (!CoreTranslate(buffer, sizeof(buffer), "%T", 2, NULL, "No Access", &client))
{ {
UTIL_Format(buffer, sizeof(buffer), "You do not have access to this command"); UTIL_Format(buffer, sizeof(buffer), "You do not have access to this command");
} }
@@ -559,6 +562,44 @@ bool ConCmdManager::CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmi
return false; return false;
} }
bool ConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
const char *name,
const char *description,
int flags)
{
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo)
{
return false;
}
CmdHook *pHook = new CmdHook();
pHook->pf = pFunction;
if (description && description[0])
{
pHook->helptext.assign(description);
}
pInfo->conhooks.push_back(pHook);
/* Add to the plugin */
CmdList *pList;
IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new CmdList();
pPlugin->SetProperty("CommandList", pList);
}
PlCmdInfo info;
info.pInfo = pInfo;
info.type = Cmd_Console;
info.pHook = pHook;
AddToPlCmdList(pList, info);
return true;
}
bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction, bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
const char *name, const char *name,
const char *group, const char *group,
@@ -620,6 +661,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
/* Finally, add the hook */ /* Finally, add the hook */
pInfo->conhooks.push_back(pHook); pInfo->conhooks.push_back(pHook);
pInfo->admin = *(pHook->pAdmin); pInfo->admin = *(pHook->pAdmin);
pInfo->is_admin_set = true;
/* Now add to the plugin */ /* Now add to the plugin */
CmdList *pList; CmdList *pList;
@@ -764,6 +806,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
pInfo->admin = *(pHook->pAdmin); pInfo->admin = *(pHook->pAdmin);
} }
} }
pInfo->is_admin_set = true;
} }
else if (type == Override_CommandGroup) else if (type == Override_CommandGroup)
{ {
@@ -797,6 +840,7 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
} }
} }
} }
pInfo->is_admin_set = true;
} }
} }
@@ -864,7 +908,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
*pFlags = pInfo->admin.eflags; *pFlags = pInfo->admin.eflags;
return true; return pInfo->is_admin_set;
} }
ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags) ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
@@ -872,10 +916,6 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo)) if (!sm_trie_retrieve(m_pCmds, name, (void **)&pInfo))
{ {
ConCmdList::iterator item = FindInList(name);
if (item != m_CmdList.end())
return *item;
pInfo = new ConCmdInfo(); pInfo = new ConCmdInfo();
/* Find the commandopan */ /* Find the commandopan */
ConCommand *pCmd = FindCommand(name); ConCommand *pCmd = FindCommand(name);
@@ -901,6 +941,7 @@ ConCmdInfo *ConCmdManager::AddOrFindCommand(const char *name, const char *descri
} }
pInfo->pCmd = pCmd; pInfo->pCmd = pCmd;
pInfo->is_admin_set = false;
sm_trie_insert(m_pCmds, name, pInfo); sm_trie_insert(m_pCmds, name, pInfo);
AddToCmdList(pInfo); AddToCmdList(pInfo);
@@ -953,9 +994,13 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
{ {
type = "server"; type = "server";
} }
else if (cmd.type == Cmd_Console)
{
type = "console";
}
else if (cmd.type == Cmd_Admin) else if (cmd.type == Cmd_Admin)
{ {
type = (cmd.pInfo->admin.eflags == 0)?"console":"admin"; type = "admin";
} }
name = cmd.pInfo->pCmd->GetName(); name = cmd.pInfo->pCmd->GetName();
if (cmd.pHook->helptext.size()) if (cmd.pHook->helptext.size())
+5 -12
View File
@@ -48,6 +48,7 @@ using namespace SourceHook;
enum CmdType enum CmdType
{ {
Cmd_Server, Cmd_Server,
Cmd_Console,
Cmd_Admin, Cmd_Admin,
}; };
@@ -88,10 +89,9 @@ struct ConCmdInfo
List<CmdHook *> srvhooks; /**< Hooks as a server command */ List<CmdHook *> srvhooks; /**< Hooks as a server command */
List<CmdHook *> conhooks; /**< Hooks as a console command */ List<CmdHook *> conhooks; /**< Hooks as a console command */
AdminCmdInfo admin; /**< Admin info, if any */ AdminCmdInfo admin; /**< Admin info, if any */
bool is_admin_set; /**< Whether or not admin info is set */
}; };
typedef List<ConCmdInfo *> ConCmdList;
class ConCmdManager : class ConCmdManager :
public SMGlobalClass, public SMGlobalClass,
public IRootConsoleCommand, public IRootConsoleCommand,
@@ -117,6 +117,7 @@ public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe); void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
public: public:
bool AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags); 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, bool AddAdminCommand(IPluginFunction *pFunction,
const char *name, const char *name,
const char *group, const char *group,
@@ -127,8 +128,7 @@ public:
void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove); void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove);
bool LookForSourceModCommand(const char *cmd); bool LookForSourceModCommand(const char *cmd);
bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags); bool LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags);
bool CheckClientCommandAccess(int client, const char *cmd, FlagBits flags); bool CheckCommandAccess(int client, const char *cmd, FlagBits flags);
bool CheckAdminCommandAccess(AdminId adm, const char *cmd, FlagBits flags);
private: private:
void InternalDispatch(const CCommand &command); void InternalDispatch(const CCommand &command);
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
@@ -139,12 +139,6 @@ private:
void RemoveConCmds(List<CmdHook *> &cmdlist); void RemoveConCmds(List<CmdHook *> &cmdlist);
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext); void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
// Case insensitive
ConCmdList::iterator FindInList(const char *name);
// Case sensitive
ConCmdInfo *FindInTrie(const char *name);
public: public:
inline int GetCommandClient() inline int GetCommandClient()
{ {
@@ -157,7 +151,7 @@ public:
private: private:
Trie *m_pCmds; /* command lookup */ Trie *m_pCmds; /* command lookup */
Trie *m_pCmdGrps; /* command group lookup */ Trie *m_pCmdGrps; /* command group lookup */
ConCmdList m_CmdList; /* command list */ List<ConCmdInfo *> m_CmdList; /* command list */
int m_CmdClient; /* current client */ int m_CmdClient; /* current client */
BaseStringTable m_Strings; /* string table */ BaseStringTable m_Strings; /* string table */
}; };
@@ -165,4 +159,3 @@ private:
extern ConCmdManager g_ConCmds; extern ConCmdManager g_ConCmds;
#endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_ #endif // _INCLUDE_SOURCEMOD_CONCMDMANAGER_H_
-89
View File
@@ -1,89 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2010 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_CON_COMMAND_BASE_ITERATOR_H_
#define _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_
#if SOURCE_ENGINE >= SE_LEFT4DEAD
class ConCommandBaseIterator
{
public:
inline ConCommandBaseIterator() : iter(icvar)
{
iter.SetFirst();
}
inline bool IsValid()
{
return iter.IsValid();
}
inline void Next()
{
iter.Next();
}
inline ConCommandBase *Get()
{
return iter.Get();
}
private:
ICvar::Iterator iter;
};
#else
class ConCommandBaseIterator
{
public:
inline ConCommandBaseIterator()
{
iter = icvar->GetCommands();
}
inline bool IsValid()
{
return iter != NULL;
}
inline void Next()
{
iter = const_cast<ConCommandBase *>(iter->GetNext());
}
inline ConCommandBase *Get()
{
return iter;
}
private:
ConCommandBase *iter;
};
#endif
#endif /* _INCLUDE_SOURCEMOD_CON_COMMAND_BASE_ITERATOR_H_ */
+14 -104
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -25,6 +25,8 @@
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/ */
#include "ConVarManager.h" #include "ConVarManager.h"
@@ -58,40 +60,6 @@ const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String}
typedef List<const ConVar *> ConVarList; typedef List<const ConVar *> ConVarList;
KTrie<ConVarInfo *> convar_cache; KTrie<ConVarInfo *> convar_cache;
class ConVarReentrancyGuard
{
ConVar *cvar;
ConVarReentrancyGuard *up;
public:
static ConVarReentrancyGuard *chain;
ConVarReentrancyGuard(ConVar *cvar)
: cvar(cvar), up(chain)
{
chain = this;
}
~ConVarReentrancyGuard()
{
assert(chain == this);
chain = up;
}
static bool IsCvarInChain(ConVar *cvar)
{
ConVarReentrancyGuard *guard = chain;
while (guard != NULL)
{
if (guard->cvar == cvar)
return true;
guard = guard->up;
}
return false;
}
};
ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false) ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
{ {
} }
@@ -126,12 +94,8 @@ void ConVarManager::OnSourceModAllInitialized()
} }
#endif #endif
g_Players.AddClientListener(this);
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false); SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
g_PluginSys.AddPluginsListener(this);
/* Add the 'convars' option to the 'sm' console command */ /* Add the 'convars' option to the 'sm' console command */
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this); g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
} }
@@ -193,15 +157,11 @@ void ConVarManager::OnSourceModShutdown()
} }
#endif #endif
g_Players.RemoveClientListener(this);
SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false); SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
/* Remove the 'convars' option from the 'sm' console command */ /* Remove the 'convars' option from the 'sm' console command */
g_RootMenu.RemoveRootConsoleCommand("cvars", this); g_RootMenu.RemoveRootConsoleCommand("cvars", this);
g_PluginSys.RemovePluginsListener(this);
/* Remove the 'ConVar' handle type */ /* Remove the 'ConVar' handle type */
g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent); g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
} }
@@ -220,7 +180,7 @@ void ConVarManager::OnSourceModVSPReceived()
} }
/* For later MM:S versions, use the updated API, since it's cleaner. */ /* For later MM:S versions, use the updated API, since it's cleaner. */
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 #if defined METAMOD_PLAPI_VERSION
int engine = g_SMAPI->GetSourceEngineBuild(); int engine = g_SMAPI->GetSourceEngineBuild();
if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2) if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
{ {
@@ -292,39 +252,12 @@ void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
void ConVarManager::OnPluginUnloaded(IPlugin *plugin) void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
{ {
ConVarList *pConVarList; ConVarList *pConVarList;
List<ConVarQuery>::iterator iter;
/* If plugin has a convar list, free its memory */ /* If plugin has a convar list, free its memory */
if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true)) if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
{ {
delete pConVarList; delete pConVarList;
} }
/* Remove convar queries for this plugin that haven't returned results yet */
for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
{
ConVarQuery &query = (*iter);
if (query.pCallback->GetParentRuntime() == plugin->GetRuntime())
{
m_ConVarQueries.erase(iter);
}
}
}
void ConVarManager::OnClientDisconnected(int client)
{
/* Remove convar queries for this client that haven't returned results yet */
for (List<ConVarQuery>::iterator iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end();)
{
ConVarQuery &query = (*iter);
if (query.client == client)
{
iter = m_ConVarQueries.erase(iter);
continue;
}
++iter;
}
} }
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object) void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
@@ -342,15 +275,8 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
int argcount = command.ArgC(); int argcount = command.ArgC();
if (argcount >= 3) if (argcount >= 3)
{ {
bool wantReset = false;
/* Get plugin index that was passed */ /* Get plugin index that was passed */
const char *arg = command.Arg(2); const char *arg = command.Arg(2);
if (argcount >= 4 && strcmp(arg, "reset") == 0)
{
wantReset = true;
arg = command.Arg(3);
}
/* Get plugin object */ /* Get plugin object */
CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg); CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
@@ -375,34 +301,21 @@ void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
return; return;
} }
if (!wantReset) g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
{ g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
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 */
}
/* Iterate convar list and display/reset each one */
for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++) for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
{ {
/*const */ConVar *pConVar = const_cast<ConVar *>(*iter); const ConVar *pConVar = (*iter);
if (!wantReset) g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
{
g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
} else {
pConVar->Revert();
}
}
if (wantReset)
{
g_RootMenu.ConsolePrint("[SM] Reset %d convars for: %s", pConVarList->size(), plname);
} }
return; return;
} }
/* Display usage of subcommand */ /* Display usage of subcommand */
g_RootMenu.ConsolePrint("[SM] Usage: sm cvars [reset] <plugin #>"); 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) 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)
@@ -610,8 +523,7 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
} }
/* If the forward now has 0 functions in it... */ /* If the forward now has 0 functions in it... */
if (pForward->GetFunctionCount() == 0 && if (pForward->GetFunctionCount() == 0)
!ConVarReentrancyGuard::IsCvarInChain(pConVar))
{ {
/* Free this forward */ /* Free this forward */
g_Forwards.ReleaseForward(pForward); g_Forwards.ReleaseForward(pForward);
@@ -639,7 +551,7 @@ QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char
return InvalidQueryCvarCookie; return InvalidQueryCvarCookie;
} }
ConVarQuery query = {cookie, pCallback, (cell_t)hndl, IndexOfEdict(pPlayer)}; ConVarQuery query = {cookie, pCallback, hndl};
m_ConVarQueries.push_back(query); m_ConVarQueries.push_back(query);
#endif #endif
@@ -722,8 +634,6 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
if (pForward != NULL) if (pForward != NULL)
{ {
ConVarReentrancyGuard guard(pConVar);
/* Now call forwards in plugins that have hooked this */ /* Now call forwards in plugins that have hooked this */
pForward->PushCell(pInfo->handle); pForward->PushCell(pInfo->handle);
pForward->PushString(oldValue); pForward->PushString(oldValue);
+1 -7
View File
@@ -39,10 +39,8 @@
#include <IForwardSys.h> #include <IForwardSys.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#include <IPlayerHelpers.h>
#include <compat_wrappers.h> #include <compat_wrappers.h>
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include "PlayerManager.h"
#if SOURCE_ENGINE == SE_DARKMESSIAH #if SOURCE_ENGINE == SE_DARKMESSIAH
class EQueryCvarValueStatus; class EQueryCvarValueStatus;
@@ -77,7 +75,6 @@ struct ConVarQuery
QueryCvarCookie_t cookie; /**< Cookie that identifies query */ QueryCvarCookie_t cookie; /**< Cookie that identifies query */
IPluginFunction *pCallback; /**< Function that will be called when query is finished */ IPluginFunction *pCallback; /**< Function that will be called when query is finished */
cell_t value; /**< Optional value passed to query function */ cell_t value; /**< Optional value passed to query function */
cell_t client; /**< Only used for cleaning up on client disconnection */
}; };
class ConVarManager : class ConVarManager :
@@ -85,8 +82,7 @@ class ConVarManager :
public IHandleTypeDispatch, public IHandleTypeDispatch,
public IPluginsListener, public IPluginsListener,
public IRootConsoleCommand, public IRootConsoleCommand,
public IConCommandTracker, public IConCommandTracker
public IClientListener
{ {
public: public:
ConVarManager(); ConVarManager();
@@ -105,8 +101,6 @@ public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command); void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
public: //IConCommandTracker public: //IConCommandTracker
void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe); void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
public: //IClientListener
void OnClientDisconnected(int client);
public: public:
/** /**
* Create a convar and return a handle to it. * Create a convar and return a handle to it.
-747
View File
@@ -1,747 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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$
*/
/**
* On SourceHook v4.3 or lower, there are no DVP hooks. Very sad, right?
* Only do this on newer versions. For the older code, we'll do an incredibly
* hacky detour.
*
* The idea of the "non-hacky" (yeah... no) code is that every unique
* ConCommand vtable gets its own DVP hook. We watch for unloading and
* loading commands to remove stale hooks from SH.
*/
#include "sourcemod.h"
#include "sourcemm_api.h"
#include "Logger.h"
#include "compat_wrappers.h"
#include "ConsoleDetours.h"
#include <IGameConfigs.h>
#include "sm_stringutil.h"
#include "ConCmdManager.h"
#include "HalfLife2.h"
#include "ConCommandBaseIterator.h"
#include "ShareSys.h"
#if defined PLATFORM_POSIX
# include <dlfcn.h>
# include <sys/mman.h>
# include <stdint.h>
# include <unistd.h>
#endif
#if SH_IMPL_VERSION >= 5
# if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &);
# else
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
# endif
#else
# if SH_IMPL_VERSION >= 4
extern int __SourceHook_FHVPAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>,bool);
extern int __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *, bool, class fastdelegate::FastDelegate0<void>);
#endif
#if SH_IMPL_VERSION >= 4
class GenericCommandHooker : public IConCommandLinkListener
{
struct HackInfo
{
void **vtable;
int hook;
unsigned int refcount;
};
CVector<HackInfo> vtables;
bool enabled;
SourceHook::MemFuncInfo dispatch;
inline void **GetVirtualTable(ConCommandBase *pBase)
{
return *reinterpret_cast<void***>(reinterpret_cast<char*>(pBase) +
dispatch.thisptroffs +
dispatch.vtbloffs);
}
inline bool FindVtable(void **ptr, size_t& index)
{
for (size_t i = 0; i < vtables.size(); i++)
{
if (vtables[i].vtable == ptr)
{
index = i;
return true;
}
}
return false;
}
void MakeHookable(ConCommandBase *pBase)
{
if (!pBase->IsCommand())
return;
ConCommand *cmd = (ConCommand*)pBase;
void **vtable = GetVirtualTable(cmd);
size_t index;
if (!FindVtable(vtable, index))
{
HackInfo hack;
hack.vtable = vtable;
hack.hook = SH_ADD_VPHOOK(ConCommand, Dispatch, cmd, SH_MEMBER(this, &GenericCommandHooker::Dispatch), false);
hack.refcount = 1;
vtables.push_back(hack);
}
else
{
vtables[index].refcount++;
}
}
# if SOURCE_ENGINE >= SE_ORANGEBOX
void Dispatch(const CCommand& args)
# else
void Dispatch()
# endif
{
cell_t res = ConsoleDetours::Dispatch(META_IFACEPTR(ConCommand)
# if SOURCE_ENGINE >= SE_ORANGEBOX
, args
# endif
);
if (res >= Pl_Handled)
RETURN_META(MRES_SUPERCEDE);
}
void ReparseCommandList()
{
for (size_t i = 0; i < vtables.size(); i++)
vtables[i].refcount = 0;
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
MakeHookable(iter.Get());
CVector<HackInfo>::iterator iter = vtables.begin();
while (iter != vtables.end())
{
if ((*iter).refcount)
{
iter++;
continue;
}
/* Damn it. This event happens AFTER the plugin has unloaded!
* There's two options. Remove the hook now and hope SH's memory
* protection will prevent a crash. Otherwise, we can wait until
* the server shuts down and more likely crash then.
*
* This situation only arises if:
* 1) Someone has used AddCommandFilter()
* 2) ... on a Dark Messiah server (mm:s new api)
* 3) ... and another MM:S plugin that uses ConCommands has unloaded.
*
* Even though the impact is really small, we'll wait until the
* server shuts down, so normal operation isn't interrupted.
*
* See bug 4018.
*/
iter = vtables.erase(iter);
}
}
void UnhookCommand(ConCommandBase *pBase)
{
if (!pBase->IsCommand())
return;
ConCommand *cmd = (ConCommand*)pBase;
void **vtable = GetVirtualTable(cmd);
size_t index;
if (!FindVtable(vtable, index))
{
g_Logger.LogError("Console detour tried to unhook command \"%s\" but it wasn't found", pBase->GetName());
return;
}
assert(vtables[index].refcount > 0);
vtables[index].refcount--;
if (vtables[index].refcount == 0)
{
SH_REMOVE_HOOK_ID(vtables[index].hook);
vtables.erase(vtables.iterAt(index));
}
}
public:
GenericCommandHooker() : enabled(false)
{
}
bool Enable()
{
SourceHook::GetFuncInfo(&ConCommand::Dispatch, dispatch);
if (dispatch.thisptroffs < 0)
{
g_Logger.LogError("Command filter could not determine ConCommand layout");
return false;
}
for (ConCommandBaseIterator iter; iter.IsValid(); iter.Next())
MakeHookable(iter.Get());
if (!vtables.size())
{
g_Logger.LogError("Command filter could not find any cvars!");
return false;
}
enabled = true;
return true;
}
void Disable()
{
for (size_t i = 0; i < vtables.size(); i++)
SH_REMOVE_HOOK_ID(vtables[i].hook);
vtables.clear();
}
virtual void OnLinkConCommand(ConCommandBase *pBase)
{
if (!enabled)
return;
MakeHookable(pBase);
}
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
{
if (!enabled)
return;
if (pBase == NULL)
ReparseCommandList();
else
UnhookCommand(pBase);
}
};
/**
* END DVP HOOK VERSION
*/
#else /* SH_IMPL_VERSION >= 4 */
/**
* BEGIN ENGINE DETOUR VERSION
*/
# include <jit/jit_helpers.h>
# include <jit/x86/x86_macros.h>
class GenericCommandHooker
{
struct Patch
{
Patch() : applied(false)
{
}
bool applied;
void *base;
unsigned char search[16];
size_t search_len;
size_t offset;
size_t saveat;
int regparam;
void *detour;
};
Patch ces;
Patch cgc;
public:
static void DelayedActivation(void *inparam)
{
GenericCommandHooker *cdtrs = reinterpret_cast<GenericCommandHooker*>(inparam);
/* Safe to re-enter because the frame queue is lock+swapped. */
if ((!cdtrs->ces.applied || !cdtrs->cgc.applied) &&
g_HL2.PeekCommandStack() != NULL)
{
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, cdtrs);
return;
}
if (!cdtrs->ces.applied)
cdtrs->ApplyPatch(&cdtrs->ces);
if (!cdtrs->cgc.applied)
cdtrs->ApplyPatch(&cdtrs->cgc);
}
bool Enable()
{
const char *platform = NULL;
# if defined(PLATFORM_WINDOWS)
platform = "Windows";
# else
void *addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
Dl_info info;
if (!dladdr(addrInBase, &info))
{
g_Logger.LogError("Command filter could not find engine name");
return false;
}
if (strstr(info.dli_fname, "engine_i486"))
{
platform = "Linux_486";
}
else if (strstr(info.dli_fname, "engine_i686"))
{
platform = "Linux_686";
}
else if (strstr(info.dli_fname, "engine_amd"))
{
platform = "Linux_AMD";
}
else
{
g_Logger.LogError("Command filter could not determine engine (%s)", info.dli_fname);
return false;
}
# endif
if (!PrepPatch("Cmd_ExecuteString", "CES", platform, &ces))
return false;
if (!PrepPatch("CGameClient::ExecuteString", "CGC", platform, &cgc))
return false;
if (g_HL2.PeekCommandStack() != NULL)
{
g_SourceMod.AddFrameAction(GenericCommandHooker::DelayedActivation, this);
return true;
}
ApplyPatch(&ces);
ApplyPatch(&cgc);
return true;
}
void Disable()
{
UndoPatch(&ces);
UndoPatch(&cgc);
}
private:
# if !defined PLATFORM_WINDOWS
# define PAGE_READWRITE PROT_READ|PROT_WRITE
# define PAGE_EXECUTE_READ PROT_READ|PROT_EXEC
static inline uintptr_t AddrToPage(uintptr_t address)
{
return (address & ~(uintptr_t(sysconf(_SC_PAGE_SIZE) - 1)));
}
# endif
void Protect(void *addr, size_t length, int prot)
{
# if defined PLATFORM_WINDOWS
DWORD ignore;
VirtualProtect(addr, length, prot, &ignore);
# else
uintptr_t startPage = AddrToPage(uintptr_t(addr));
length += (uintptr_t(addr) - startPage);
mprotect((void*)startPage, length, prot);
# endif
}
void UndoPatch(Patch *patch)
{
if (!patch->applied || patch->detour == NULL)
return;
g_pSourcePawn->FreePageMemory(patch->detour);
unsigned char *source = (unsigned char *)patch->base + patch->offset;
Protect(source, patch->search_len, PAGE_READWRITE);
for (size_t i = 0; i < patch->search_len; i++)
source[i] = patch->search[i];
Protect(source, patch->search_len, PAGE_EXECUTE_READ);
}
void ApplyPatch(Patch *patch)
{
assert(!patch->applied);
size_t length = 0;
void *callback = (void*)&ConsoleDetours::Dispatch;
/* Bogus assignment to make compiler is doing the right thing. */
patch->detour = callback;
/* Assemgle the detour. */
JitWriter writer;
writer.outbase = NULL;
writer.outptr = NULL;
do
{
/* Need a specific register, or value on stack? */
if (patch->regparam != -1)
IA32_Push_Reg(&writer, patch->regparam);
/* Call real function. */
IA32_Write_Jump32_Abs(&writer, IA32_Call_Imm32(&writer, 0), callback);
/* Restore stack. */
if (patch->regparam != -1)
IA32_Pop_Reg(&writer, patch->regparam);
/* Copy any saved bytes */
if (patch->saveat)
{
for (size_t i = patch->saveat; i < patch->search_len; i++)
{
writer.write_ubyte(patch->search[i]);
}
}
/* Jump back to the caller. */
unsigned char *target = (unsigned char *)patch->base + patch->offset + patch->search_len;
IA32_Jump_Imm32_Abs(&writer, target);
/* Assemble, if we can. */
if (writer.outbase == NULL)
{
length = writer.outptr - writer.outbase;
patch->detour = g_pSourcePawn->AllocatePageMemory(length);
if (patch->detour == NULL)
{
g_Logger.LogError("Ran out of memory!");
return;
}
g_pSourcePawn->SetReadWrite(patch->detour);
writer.outbase = (jitcode_t)patch->detour;
writer.outptr = writer.outbase;
}
else
{
break;
}
} while (true);
g_pSourcePawn->SetReadExecute(patch->detour);
unsigned char *source = (unsigned char *)patch->base + patch->offset;
Protect(source, 6, PAGE_READWRITE);
source[0] = 0xFF;
source[1] = 0x25;
*(void **)&source[2] = &patch->detour;
Protect(source, 6, PAGE_EXECUTE_READ);
patch->applied = true;
}
bool PrepPatch(const char *signature, const char *name, const char *platform, Patch *patch)
{
/* Get the base address of the function. */
if (!g_pGameConf->GetMemSig(signature, &patch->base) || patch->base == NULL)
{
g_Logger.LogError("Command filter could not find signature: %s", signature);
return false;
}
const char *value;
char keyname[255];
/* Get the verification bytes that will be written over. */
UTIL_Format(keyname, sizeof(keyname), "%s_Patch_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
{
g_Logger.LogError("Command filter could not find key: %s", keyname);
return false;
}
patch->search_len = UTIL_DecodeHexString(patch->search, sizeof(patch->search), value);
if (patch->search_len < 6)
{
g_Logger.LogError("Error decoding %s value, or not long enough", keyname);
return false;
}
/* Get the offset into the function. */
UTIL_Format(keyname, sizeof(keyname), "%s_Offset_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) == NULL)
{
g_Logger.LogError("Command filter could not find key: %s", keyname);
return false;
}
patch->offset = atoi(value);
if (patch->offset > 20000)
{
g_Logger.LogError("Command filter %s value is bogus", keyname);
return false;
}
/* Get the number of bytes to save from what was written over. */
patch->saveat = 0;
UTIL_Format(keyname, sizeof(keyname), "%s_Save_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
{
patch->saveat = atoi(value);
if (patch->saveat >= patch->search_len)
{
g_Logger.LogError("Command filter %s value is too large", keyname);
return false;
}
}
/* Get register for parameter, if any. */
patch->regparam = -1;
UTIL_Format(keyname, sizeof(keyname), "%s_Reg_%s", name, platform);
if ((value = g_pGameConf->GetKeyValue(keyname)) != NULL)
{
patch->regparam = atoi(value);
}
/* Everything loaded from gamedata, make sure the patch will succeed. */
unsigned char *address = (unsigned char *)patch->base + patch->offset;
for (size_t i = 0; i < patch->search_len; i++)
{
if (address[i] != patch->search[i])
{
g_Logger.LogError("Command filter %s has changed (byte %x is not %x sub-offset %d)",
name, address[i], patch->search[i], i);
return false;
}
}
return true;
}
};
static bool dummy_hook_set = false;
void DummyHook()
{
if (dummy_hook_set)
{
dummy_hook_set = false;
RETURN_META(MRES_SUPERCEDE);
}
}
#endif
/**
* BEGIN THE ACTUALLY GENERIC CODE.
*/
#define FEATURECAP_COMMANDLISTENER "command listener"
static GenericCommandHooker s_GenericHooker;
ConsoleDetours g_ConsoleDetours;
ConsoleDetours::ConsoleDetours() : status(FeatureStatus_Unknown)
{
}
void ConsoleDetours::OnSourceModAllInitialized()
{
m_pForward = g_Forwards.CreateForwardEx("OnAnyCommand", ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
g_ShareSys.AddCapabilityProvider(NULL, this, FEATURECAP_COMMANDLISTENER);
}
void ConsoleDetours::OnSourceModShutdown()
{
List<Listener*>::iterator iter = m_Listeners.begin();
while (iter != m_Listeners.end())
{
Listener *listener = (*iter);
g_Forwards.ReleaseForward(listener->forward);
delete listener;
iter = m_Listeners.erase(iter);
}
g_Forwards.ReleaseForward(m_pForward);
s_GenericHooker.Disable();
}
FeatureStatus ConsoleDetours::GetFeatureStatus(FeatureType type, const char *name)
{
return GetStatus();
}
FeatureStatus ConsoleDetours::GetStatus()
{
if (status == FeatureStatus_Unknown)
{
status = s_GenericHooker.Enable() ? FeatureStatus_Available : FeatureStatus_Unavailable;
}
return status;
}
bool ConsoleDetours::AddListener(IPluginFunction *fun, const char *command)
{
if (GetStatus() != FeatureStatus_Available)
return false;
if (command == NULL)
{
m_pForward->AddFunction(fun);
}
else
{
const char *str = UTIL_ToLowerCase(command);
Listener *listener;
Listener **plistener = m_CmdLookup.retrieve(str);
if (plistener == NULL)
{
listener = new Listener;
listener->forward = g_Forwards.CreateForwardEx(NULL, ET_Hook, 3, NULL, Param_Cell,
Param_String, Param_Cell);
m_CmdLookup.insert(str, listener);
}
else
{
listener = *plistener;
}
listener->forward->AddFunction(fun);
delete [] str;
}
return true;
}
bool ConsoleDetours::RemoveListener(IPluginFunction *fun, const char *command)
{
if (command == NULL)
{
return m_pForward->RemoveFunction(fun);
}
else
{
const char *str = UTIL_ToLowerCase(command);
Listener *listener;
Listener **plistener = m_CmdLookup.retrieve(str);
delete [] str;
if (plistener == NULL)
return false;
listener = *plistener;
return listener->forward->RemoveFunction(fun);
}
}
cell_t ConsoleDetours::InternalDispatch(int client, const CCommand& args)
{
char name[255];
const char *realname = args.Arg(0);
size_t len = strlen(realname);
// Disallow command strings that are too long, for now.
if (len >= sizeof(name) - 1)
return Pl_Continue;
for (size_t i = 0; i < len; i++)
{
if (realname[i] >= 'A' && realname[i] <= 'Z')
name[i] = tolower(realname[i]);
else
name[i] = realname[i];
}
name[len] = '\0';
cell_t result = Pl_Continue;
m_pForward->PushCell(client);
m_pForward->PushString(name);
m_pForward->PushCell(args.ArgC() - 1);
m_pForward->Execute(&result, NULL);
/* Don't let plugins block this. */
if (strcmp(name, "sm") == 0)
result = Pl_Continue;
if (result >= Pl_Handled)
return result;
Listener **plistener = m_CmdLookup.retrieve(name);
if (plistener == NULL)
return result;
Listener *listener = *plistener;
if (listener->forward->GetFunctionCount() == 0)
return result;
cell_t result2 = Pl_Continue;
listener->forward->PushCell(client);
listener->forward->PushString(name);
listener->forward->PushCell(args.ArgC() - 1);
listener->forward->Execute(&result2, NULL);
if (result2 > result)
result = result2;
/* "sm" should not have flown through the above. */
assert(strcmp(name, "sm") != 0 || result == Pl_Continue);
return result;
}
#if SOURCE_ENGINE >= SE_ORANGEBOX
cell_t ConsoleDetours::Dispatch(ConCommand *pBase, const CCommand& args)
{
#else
cell_t ConsoleDetours::Dispatch(ConCommand *pBase)
{
CCommand args;
#endif
g_HL2.PushCommandStack(&args);
cell_t res = g_ConsoleDetours.InternalDispatch(g_ConCmds.GetCommandClient(), args);
g_HL2.PopCommandStack();
#if SH_IMPL_VERSION < 4
if (res >= Pl_Handled)
{
/* See bug 4020 - we can't optimize this because looking at the vtable
* is probably more expensive, since there's no SH_GET_ORIG_VFNPTR_ENTRY.
*/
SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
dummy_hook_set = true;
pBase->Dispatch();
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, pBase, DummyHook, false);
}
else
{
/* Make sure the command gets invoked. See bug 4019 on making this better. */
pBase->Dispatch();
}
#endif
return res;
}
-83
View File
@@ -1,83 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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_CONSOLE_DETOURS_H_
#define _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_
#include "sm_globals.h"
#include "sourcemm_api.h"
#include "ForwardSys.h"
#include <sm_trie_tpl.h>
class ConsoleDetours :
public SMGlobalClass,
public IFeatureProvider
{
friend class PlayerManager;
friend class GenericCommandHooker;
struct Listener
{
IChangeableForward *forward;
};
public:
ConsoleDetours();
public: //SMGlobalClass
void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: //IFeatureProvider
FeatureStatus GetFeatureStatus(FeatureType type, const char *name);
public:
bool AddListener(IPluginFunction *fun, const char *command);
bool RemoveListener(IPluginFunction *fun, const char *command);
private:
cell_t InternalDispatch(int client, const CCommand& args);
#if SOURCE_ENGINE >= SE_ORANGEBOX
static cell_t Dispatch(ConCommand *pBase, const CCommand& args);
#else
static cell_t Dispatch(ConCommand *pBase);
#endif
public:
FeatureStatus GetStatus();
bool IsEnabled()
{
return status == FeatureStatus_Available;
}
private:
FeatureStatus status;
IChangeableForward *m_pForward;
KTrie<Listener*> m_CmdLookup;
List<Listener*> m_Listeners;
};
extern ConsoleDetours g_ConsoleDetours;
#endif /* _INCLUDE_SOURCEMOD_CONSOLE_DETOURS_H_ */
+15 -47
View File
@@ -34,7 +34,7 @@
#include "sourcemod.h" #include "sourcemod.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include <sourcemod_version.h> #include "sm_version.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "LibrarySys.h" #include "LibrarySys.h"
#include "Logger.h" #include "Logger.h"
@@ -68,11 +68,7 @@ void Hook_ExecDispatchPre(const CCommand &cmd)
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
void Hook_ExecDispatchPre() void Hook_ExecDispatchPre()
#else #else
# if SH_IMPL_VERSION >= 4 extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
void Hook_ExecDispatchPre() void Hook_ExecDispatchPre()
#endif #endif
@@ -107,7 +103,11 @@ void CheckAndFinalizeConfigs()
{ {
if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart) if ((g_bServerExecd || g_ServerCfgFile == NULL) && g_bGotServerStart)
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX
g_PendingInternalPush = true; g_PendingInternalPush = true;
#else
SM_InternalCmdTrigger();
#endif
} }
} }
@@ -193,30 +193,17 @@ void CoreConfig::OnRootConsoleCommand(const char *cmdname, const CCommand &comma
if (res == ConfigResult_Reject) if (res == ConfigResult_Reject)
{ {
g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\". (%s)", option, value, error); g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\" (%s)", option, value, error);
} else if (res == ConfigResult_Ignore) { } else if (res == ConfigResult_Ignore) {
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option); g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
} else { } else {
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" successfully set to \"%s\".", option, value); g_RootMenu.ConsolePrint("Config option \"%s\" successfully set to \"%s.\"", option, value);
} }
return;
} else if (argcount >= 3) {
const char *option = command.Arg(2);
const char *value = GetCoreConfigValue(option);
if (value == NULL)
{
g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
} else {
g_RootMenu.ConsolePrint("[SM] Config option \"%s\" is set to \"%s\".", option, value);
}
return; return;
} }
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> [value]"); g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
} }
void CoreConfig::Initialize() void CoreConfig::Initialize()
@@ -227,28 +214,14 @@ void CoreConfig::Initialize()
/* Try to get command line value of core config convar */ /* Try to get command line value of core config convar */
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile"); const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
/* If sm_corecfgfile is on the command line, use that /* If sm_corecfgfile not specified on command line, use default value */
* If sm_corecfgfile isn't there, check sm_basepath on the command line and build the path off that if (!corecfg)
* If sm_basepath isn't there, just use the default path for the cfg
*/
if (corecfg)
{ {
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg); corecfg = sm_corecfgfile.GetDefault();
} }
else
{
const char *basepath = icvar->GetCommandLineValue("sm_basepath");
/* Format path to config file */ /* Format path to config file */
if (basepath) g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
{
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s/%s", g_SourceMod.GetGamePath(), basepath, "configs/core.cfg");
}
else
{
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), sm_corecfgfile.GetDefault());
}
}
/* Reset cached key values */ /* Reset cached key values */
m_KeyValues.clear(); m_KeyValues.clear();
@@ -408,7 +381,7 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
FILE *fp = fopen(file, "wt"); FILE *fp = fopen(file, "wt");
if (fp) if (fp)
{ {
fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SOURCEMOD_VERSION); 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, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
fprintf(fp, "\n\n"); fprintf(fp, "\n\n");
@@ -465,11 +438,6 @@ bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
can_create = false; can_create = false;
fclose(fp); fclose(fp);
} }
else
{
g_Logger.LogError("Failed to auto generate config for %s, make sure the directory has write permission.", pl->GetFilename());
return can_create;
}
} }
} }
+32 -41
View File
@@ -37,7 +37,7 @@
#include "Logger.h" #include "Logger.h"
#include "ExtensionSys.h" #include "ExtensionSys.h"
#include <stdlib.h> #include <stdlib.h>
#include <IThreader.h> #include "ThreadSupport.h"
#define DBPARSE_LEVEL_NONE 0 #define DBPARSE_LEVEL_NONE 0
#define DBPARSE_LEVEL_MAIN 1 #define DBPARSE_LEVEL_MAIN 1
@@ -47,7 +47,7 @@ DBManager g_DBMan;
static bool s_OneTimeThreaderErrorMsg = false; static bool s_OneTimeThreaderErrorMsg = false;
DBManager::DBManager() DBManager::DBManager()
: m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL) : m_StrTab(512), m_ParseLevel(0), m_ParseState(0), m_pDefault(NULL)
{ {
} }
@@ -104,7 +104,6 @@ void DBManager::OnSourceModShutdown()
m_pQueueLock->DestroyThis(); m_pQueueLock->DestroyThis();
g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent); g_HandleSys.RemoveType(m_DatabaseType, g_pCoreIdent);
g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent); g_HandleSys.RemoveType(m_DriverType, g_pCoreIdent);
ClearConfigs();
} }
unsigned int DBManager::GetInterfaceVersion() unsigned int DBManager::GetInterfaceVersion()
@@ -134,20 +133,13 @@ void DBManager::OnHandleDestroy(HandleType_t type, void *object)
void DBManager::ReadSMC_ParseStart() void DBManager::ReadSMC_ParseStart()
{ {
ClearConfigs(); m_confs.clear();
m_ParseLevel = 0; m_ParseLevel = 0;
m_ParseState = DBPARSE_LEVEL_NONE; m_ParseState = DBPARSE_LEVEL_NONE;
m_StrTab.Reset();
m_DefDriver.clear(); m_DefDriver.clear();
} }
void DBManager::ClearConfigs()
{
List<ConfDbInfo *>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
delete (*iter);
m_confs.clear();
}
ConfDbInfo s_CurInfo; ConfDbInfo s_CurInfo;
SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name) SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *name)
{ {
@@ -167,7 +159,7 @@ SMCResult DBManager::ReadSMC_NewSection(const SMCStates *states, const char *nam
} }
} else if (m_ParseState == DBPARSE_LEVEL_MAIN) { } else if (m_ParseState == DBPARSE_LEVEL_MAIN) {
s_CurInfo = ConfDbInfo(); s_CurInfo = ConfDbInfo();
s_CurInfo.name = name; s_CurInfo.name = m_StrTab.AddString(name);
m_ParseState = DBPARSE_LEVEL_DATABASE; m_ParseState = DBPARSE_LEVEL_DATABASE;
} else if (m_ParseState == DBPARSE_LEVEL_DATABASE) { } else if (m_ParseState == DBPARSE_LEVEL_DATABASE) {
m_ParseLevel++; m_ParseLevel++;
@@ -194,16 +186,16 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
{ {
if (strcmp(value, "default") != 0) if (strcmp(value, "default") != 0)
{ {
s_CurInfo.driver = value; s_CurInfo.driver = m_StrTab.AddString(value);
} }
} else if (strcmp(key, "database") == 0) { } else if (strcmp(key, "database") == 0) {
s_CurInfo.database = value; s_CurInfo.database = m_StrTab.AddString(value);
} else if (strcmp(key, "host") == 0) { } else if (strcmp(key, "host") == 0) {
s_CurInfo.host = value; s_CurInfo.host = m_StrTab.AddString(value);
} else if (strcmp(key, "user") == 0) { } else if (strcmp(key, "user") == 0) {
s_CurInfo.user = value; s_CurInfo.user = m_StrTab.AddString(value);
} else if (strcmp(key, "pass") == 0) { } else if (strcmp(key, "pass") == 0) {
s_CurInfo.pass = value; s_CurInfo.pass = m_StrTab.AddString(value);
} else if (strcmp(key, "timeout") == 0) { } else if (strcmp(key, "timeout") == 0) {
s_CurInfo.info.maxTimeout = atoi(value); s_CurInfo.info.maxTimeout = atoi(value);
} else if (strcmp(key, "port") == 0) { } else if (strcmp(key, "port") == 0) {
@@ -214,6 +206,13 @@ SMCResult DBManager::ReadSMC_KeyValue(const SMCStates *states, const char *key,
return SMCResult_Continue; 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) SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
{ {
if (m_ParseLevel) if (m_ParseLevel)
@@ -224,26 +223,17 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
if (m_ParseState == DBPARSE_LEVEL_DATABASE) if (m_ParseState == DBPARSE_LEVEL_DATABASE)
{ {
ConfDbInfo *cdb = new ConfDbInfo(); /* Set all of the info members to either a blank string
* or the string pointer from the string table.
cdb->name = s_CurInfo.name; */
cdb->driver = s_CurInfo.driver; ASSIGN_VAR(driver);
cdb->host = s_CurInfo.host; ASSIGN_VAR(database);
cdb->user = s_CurInfo.user; ASSIGN_VAR(host);
cdb->pass = s_CurInfo.pass; ASSIGN_VAR(user);
cdb->database = s_CurInfo.database; ASSIGN_VAR(pass);
cdb->realDriver = s_CurInfo.realDriver;
cdb->info.maxTimeout = s_CurInfo.info.maxTimeout;
cdb->info.port = s_CurInfo.info.port;
cdb->info.driver = cdb->driver.c_str();
cdb->info.database = cdb->database.c_str();
cdb->info.host = cdb->host.c_str();
cdb->info.user = cdb->user.c_str();
cdb->info.pass = cdb->pass.c_str();
/* Save it.. */ /* Save it.. */
m_confs.push_back(cdb); m_confs.push_back(s_CurInfo);
/* Go up one level */ /* Go up one level */
m_ParseState = DBPARSE_LEVEL_MAIN; m_ParseState = DBPARSE_LEVEL_MAIN;
@@ -254,6 +244,7 @@ SMCResult DBManager::ReadSMC_LeavingSection(const SMCStates *states)
return SMCResult_Continue; return SMCResult_Continue;
} }
#undef ASSIGN_VAR
void DBManager::ReadSMC_ParseEnd(bool halted, bool failed) void DBManager::ReadSMC_ParseEnd(bool halted, bool failed)
{ {
@@ -342,10 +333,10 @@ void DBManager::RemoveDriver(IDBDriver *pDriver)
} }
/* Make sure NOTHING references this! */ /* Make sure NOTHING references this! */
List<ConfDbInfo *>::iterator iter; List<ConfDbInfo>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++) for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
{ {
ConfDbInfo &db = *(*iter); ConfDbInfo &db = (*iter);
if (db.realDriver == pDriver) if (db.realDriver == pDriver)
{ {
db.realDriver = NULL; db.realDriver = NULL;
@@ -457,12 +448,12 @@ const DatabaseInfo *DBManager::FindDatabaseConf(const char *name)
ConfDbInfo *DBManager::GetDatabaseConf(const char *name) ConfDbInfo *DBManager::GetDatabaseConf(const char *name)
{ {
List<ConfDbInfo *>::iterator iter; List<ConfDbInfo>::iterator iter;
for (iter=m_confs.begin(); iter!=m_confs.end(); iter++) for (iter=m_confs.begin(); iter!=m_confs.end(); iter++)
{ {
ConfDbInfo &conf = *(*iter); ConfDbInfo &conf = (*iter);
if (conf.name == name) if (strcmp(m_StrTab.GetString(conf.name), name) == 0)
{ {
return &conf; return &conf;
} }
+10 -9
View File
@@ -47,15 +47,16 @@ using namespace SourceHook;
struct ConfDbInfo struct ConfDbInfo
{ {
ConfDbInfo() : realDriver(NULL) ConfDbInfo() : name(-1), driver(-1), host(-1), user(-1), pass(-1),
database(-1), realDriver(NULL)
{ {
} }
String name; int name;
String driver; int driver;
String host; int host;
String user; int user;
String pass; int pass;
String database; int database;
IDBDriver *realDriver; IDBDriver *realDriver;
DatabaseInfo info; DatabaseInfo info;
}; };
@@ -120,7 +121,6 @@ public:
return m_DatabaseType; return m_DatabaseType;
} }
private: private:
void ClearConfigs();
void KillWorkerThread(); void KillWorkerThread();
private: private:
CVector<IDBDriver *> m_drivers; CVector<IDBDriver *> m_drivers;
@@ -134,10 +134,11 @@ private:
IMutex *m_pQueueLock; /* Queue safety lock */ IMutex *m_pQueueLock; /* Queue safety lock */
IMutex *m_pThinkLock; /* Think-queue lock */ IMutex *m_pThinkLock; /* Think-queue lock */
List<ConfDbInfo *> m_confs; List<ConfDbInfo> m_confs;
HandleType_t m_DriverType; HandleType_t m_DriverType;
HandleType_t m_DatabaseType; HandleType_t m_DatabaseType;
String m_DefDriver; String m_DefDriver;
BaseStringTable m_StrTab;
char m_Filename[PLATFORM_MAX_PATH]; char m_Filename[PLATFORM_MAX_PATH];
unsigned int m_ParseLevel; unsigned int m_ParseLevel;
unsigned int m_ParseState; unsigned int m_ParseState;
+2 -7
View File
@@ -56,16 +56,11 @@ void DebugReport::OnDebugSpew(const char *msg, ...)
void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...) void DebugReport::GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...)
{ {
va_list ap; va_list ap;
char buffer[512];
va_start(ap, message); va_start(ap, message);
GenerateErrorVA(ctx, func_idx, err, message, ap);
va_end(ap);
}
void DebugReport::GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap)
{
char buffer[512];
UTIL_FormatArgs(buffer, sizeof(buffer), message, ap); UTIL_FormatArgs(buffer, sizeof(buffer), message, ap);
va_end(ap);
const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename(); const char *plname = g_PluginSys.FindPluginByContext(ctx->GetContext())->GetFilename();
const char *error = g_pSourcePawn2->GetErrorString(err); const char *error = g_pSourcePawn2->GetErrorString(err);
-1
View File
@@ -46,7 +46,6 @@ public: // IDebugListener
void OnDebugSpew(const char *msg, ...); void OnDebugSpew(const char *msg, ...);
public: public:
void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...); void GenerateError(IPluginContext *ctx, cell_t func_idx, int err, const char *message, ...);
void GenerateErrorVA(IPluginContext *ctx, cell_t func_idx, int err, const char *message, va_list ap);
void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...); void GenerateCodeError(IPluginContext *ctx, uint32_t code_addr, int err, const char *message, ...);
private: private:
int _GetPluginIndex(IPluginContext *ctx); int _GetPluginIndex(IPluginContext *ctx);
+3 -36
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -42,20 +42,6 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell}; const ParamType GAMEEVENT_PARAMS[] = {Param_Cell, Param_String, Param_Cell};
typedef List<EventHook *> EventHookList; typedef List<EventHook *> EventHookList;
class EventForwardFilter : public IForwardFilter
{
EventInfo *pEventInfo;
public:
EventForwardFilter(EventInfo *pEventInfo) : pEventInfo(pEventInfo)
{
}
void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
{
params[2].val = pEventInfo->bDontBroadcast ? 1 : 0;
}
};
EventManager::EventManager() : m_EventType(0) EventManager::EventManager() : m_EventType(0)
{ {
/* Create an event lookup trie */ /* Create an event lookup trie */
@@ -161,13 +147,6 @@ void EventManager::FireGameEvent(IGameEvent *pEvent)
Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */ Just need to add ourselves as a listener to make our hook on IGameEventManager2::FireEvent work */
} }
#if SOURCE_ENGINE >= SE_LEFT4DEAD
int EventManager::GetEventDebugID()
{
return EVENT_DEBUG_ID_INIT;
}
#endif
EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode) EventHookError EventManager::HookEvent(const char *name, IPluginFunction *pFunction, EventHookMode mode)
{ {
EventHook *pHook; EventHook *pHook;
@@ -348,7 +327,6 @@ EventInfo *EventManager::CreateEvent(IPluginContext *pContext, const char *name,
pInfo->pEvent = pEvent; pInfo->pEvent = pEvent;
pInfo->pOwner = pContext->GetIdentity(); pInfo->pOwner = pContext->GetIdentity();
pInfo->bDontBroadcast = false;
return pInfo; return pInfo;
} }
@@ -387,7 +365,6 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
IChangeableForward *pForward; IChangeableForward *pForward;
const char *name; const char *name;
cell_t res = Pl_Continue; cell_t res = Pl_Continue;
bool broadcast = bDontBroadcast;
/* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
if (!pEvent) if (!pEvent)
@@ -413,16 +390,10 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
HandleSecurity sec(NULL, g_pCoreIdent); HandleSecurity sec(NULL, g_pCoreIdent);
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
info.bDontBroadcast = bDontBroadcast;
EventForwardFilter filter(&info);
pForward->PushCell(hndl); pForward->PushCell(hndl);
pForward->PushString(name); pForward->PushString(name);
pForward->PushCell(bDontBroadcast); pForward->PushCell(bDontBroadcast);
pForward->Execute(&res, &filter); pForward->Execute(&res, NULL);
broadcast = info.bDontBroadcast;
g_HandleSys.FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
} }
@@ -443,9 +414,6 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
m_EventStack.push(NULL); m_EventStack.push(NULL);
} }
if (broadcast != bDontBroadcast)
RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, true, &IGameEventManager2::FireEvent, (pEvent, broadcast));
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
@@ -473,7 +441,6 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{ {
if (pHook->postCopy) if (pHook->postCopy)
{ {
info.bDontBroadcast = bDontBroadcast;
info.pEvent = m_EventCopies.front(); info.pEvent = m_EventCopies.front();
info.pOwner = NULL; info.pOwner = NULL;
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
+1 -5
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -53,7 +53,6 @@ struct EventInfo
} }
IGameEvent *pEvent; IGameEvent *pEvent;
IdentityToken_t *pOwner; IdentityToken_t *pOwner;
bool bDontBroadcast;
}; };
struct EventHook struct EventHook
@@ -105,9 +104,6 @@ public: // IPluginsListener
void OnPluginUnloaded(IPlugin *plugin); void OnPluginUnloaded(IPlugin *plugin);
public: // IGameEventListener2 public: // IGameEventListener2
void FireGameEvent(IGameEvent *pEvent); void FireGameEvent(IGameEvent *pEvent);
#if SOURCE_ENGINE >= SE_LEFT4DEAD
int GetEventDebugID();
#endif
public: public:
/** /**
* Get the 'GameEvent' handle type ID. * Get the 'GameEvent' handle type ID.
+19 -191
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 sw=4 tw=99 noet :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -37,7 +37,6 @@
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "PlayerManager.h"
CExtensionManager g_Extensions; CExtensionManager g_Extensions;
IdentityType_t g_ExtType; IdentityType_t g_ExtType;
@@ -64,35 +63,15 @@ CRemoteExtension::CRemoteExtension(IExtensionInterface *pAPI, const char *filena
#if defined METAMOD_PLAPI_VERSION #if defined METAMOD_PLAPI_VERSION
#if SOURCE_ENGINE == SE_LEFT4DEAD #if SOURCE_ENGINE == SE_LEFT4DEAD
#define GAMEFIX "2.l4d" #define GAMEFIX "2.l4d"
#elif SOURCE_ENGINE == SE_LEFT4DEAD2
#define GAMEFIX "2.l4d2"
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
#define GAMEFIX "2.nd"
#elif SOURCE_ENGINE == SE_ALIENSWARM
#define GAMEFIX "2.swarm"
#elif SOURCE_ENGINE == SE_ORANGEBOX #elif SOURCE_ENGINE == SE_ORANGEBOX
#define GAMEFIX "2.ep2" #define GAMEFIX "2.ep2"
#elif SOURCE_ENGINE == SE_BLOODYGOODTIME #elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
#define GAMEFIX "2.bgt" #define GAMEFIX "2.ep2v"
#elif SOURCE_ENGINE == SE_EYE
#define GAMEFIX "2.eye"
#elif SOURCE_ENGINE == SE_CSS
#define GAMEFIX "2.css"
#elif SOURCE_ENGINE == SE_HL2DM
#define GAMEFIX "2.hl2dm"
#elif SOURCE_ENGINE == SE_DODS
#define GAMEFIX "2.dods"
#elif SOURCE_ENGINE == SE_TF2
#define GAMEFIX "2.tf2"
#elif SOURCE_ENGINE == SE_DARKMESSIAH #elif SOURCE_ENGINE == SE_DARKMESSIAH
#define GAMEFIX "2.darkm" #define GAMEFIX "2.darkm"
#elif SOURCE_ENGINE == SE_PORTAL2
#define GAMEFIX "2.portal2"
#elif SOURCE_ENGINE == SE_CSGO
#define GAMEFIX "2.csgo"
#else #else
#define GAMEFIX "2.ep1" #define GAMEFIX "2.ep1"
#endif //(SOURCE_ENGINE == SE_LEFT4DEAD) || (SOURCE_ENGINE == SE_LEFT4DEAD2) #endif //SOURCE_ENGINE == SE_LEFT4DEAD
#else //METAMOD_PLAPI_VERSION #else //METAMOD_PLAPI_VERSION
#define GAMEFIX "1.ep1" #define GAMEFIX "1.ep1"
#endif //METAMOD_PLAPI_VERSION #endif //METAMOD_PLAPI_VERSION
@@ -104,12 +83,6 @@ CLocalExtension::CLocalExtension(const char *filename)
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
/* Special case for new bintools binary */
if (strcmp(filename, "bintools.ext") == 0)
{
goto normal;
}
/* Zeroth, see if there is an engine specific build in the new place. */ /* Zeroth, see if there is an engine specific build in the new place. */
g_SourceMod.BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
@@ -122,31 +95,6 @@ CLocalExtension::CLocalExtension(const char *filename)
goto found; goto found;
} }
#if SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.ep2v." PLATFORM_LIB_EXT,
filename);
if (g_LibSys.IsPathFile(path))
{
goto found;
}
#elif SOURCE_ENGINE == SE_NUCLEARDAWN
g_SourceMod.BuildPath(Path_SM,
path,
PLATFORM_MAX_PATH,
"extensions/%s.2.l4d2." PLATFORM_LIB_EXT,
filename);
if (g_LibSys.IsPathFile(path))
{
goto found;
}
#endif
/* First see if there is an engine specific build! */ /* First see if there is an engine specific build! */
g_SourceMod.BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
@@ -157,7 +105,6 @@ CLocalExtension::CLocalExtension(const char *filename)
/* Try the "normal" version */ /* Try the "normal" version */
if (!g_LibSys.IsPathFile(path)) if (!g_LibSys.IsPathFile(path))
{ {
normal:
g_SourceMod.BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
PLATFORM_MAX_PATH, PLATFORM_MAX_PATH,
@@ -222,28 +169,6 @@ bool CLocalExtension::Load(char *error, size_t maxlength)
{ {
bool already; bool already;
m_PlId = g_pMMPlugins->Load(m_Path.c_str(), g_PLID, already, error, maxlength); m_PlId = g_pMMPlugins->Load(m_Path.c_str(), g_PLID, already, error, maxlength);
// Check the plugin didn't refuse load
Pl_Status status;
#ifndef METAMOD_PLAPI_VERSION
const char *file;
PluginId source;
#endif
if (!m_PlId || (
#ifndef METAMOD_PLAPI_VERSION
g_pMMPlugins->Query(m_PlId, file, status, source)
#else
g_pMMPlugins->Query(m_PlId, NULL, &status, NULL)
#endif
&& status < Pl_Paused))
{
m_pLib->CloseLibrary();
m_pLib = NULL;
m_pAPI = NULL;
return false;
}
} }
if (!CExtension::Load(error, maxlength)) if (!CExtension::Load(error, maxlength))
@@ -410,11 +335,6 @@ const char *CExtension::GetFilename()
return m_RealFile.c_str(); return m_RealFile.c_str();
} }
const char *CExtension::GetPath() const
{
return m_Path.c_str();
}
IdentityToken_t *CExtension::GetIdentity() IdentityToken_t *CExtension::GetIdentity()
{ {
return m_pIdentToken; return m_pIdentToken;
@@ -623,7 +543,7 @@ void CExtensionManager::TryAutoload()
} }
} }
IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOnMissing) IExtension *CExtensionManager::LoadAutoExtension(const char *path)
{ {
/* Remove platform extension if it's there. Compat hack. */ /* Remove platform extension if it's there. Compat hack. */
const char *ext = g_LibSys.GetFileExtension(path); const char *ext = g_LibSys.GetFileExtension(path);
@@ -632,7 +552,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
char path2[PLATFORM_MAX_PATH]; char path2[PLATFORM_MAX_PATH];
UTIL_Format(path2, sizeof(path2), "%s", path); UTIL_Format(path2, sizeof(path2), "%s", path);
path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0'; path2[strlen(path) - strlen(PLATFORM_LIB_EXT) - 1] = '\0';
return LoadAutoExtension(path2, bErrorOnMissing); return LoadAutoExtension(path2);
} }
IExtension *pAlready; IExtension *pAlready;
@@ -651,11 +571,7 @@ IExtension *CExtensionManager::LoadAutoExtension(const char *path, bool bErrorOn
if (!p->Load(error, sizeof(error)) || !p->IsLoaded()) if (!p->Load(error, sizeof(error)) || !p->IsLoaded())
{ {
if (bErrorOnMissing || g_LibSys.IsPathFile(p->GetPath())) g_Logger.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
{
g_Logger.LogError("[SM] Unable to load extension \"%s\": %s", path, error);
}
p->SetError(error); p->SetError(error);
} }
@@ -836,13 +752,6 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
return false; return false;
} }
/* Tell it to unload */
if (pExt->IsLoaded())
{
IExtensionInterface *pAPI = pExt->GetAPI();
pAPI->OnExtensionUnload();
}
/* First remove us from internal lists */ /* First remove us from internal lists */
g_ShareSys.RemoveInterfaces(_pExt); g_ShareSys.RemoveInterfaces(_pExt);
m_Libs.remove(pExt); m_Libs.remove(pExt);
@@ -866,7 +775,7 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
s_iter != pExt->m_Libraries.end(); s_iter != pExt->m_Libraries.end();
s_iter++) s_iter++)
{ {
g_PluginSys.OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed); g_PluginSys.OnLibraryAction((*s_iter).c_str(), false, true);
} }
/* Notify and/or unload all dependencies */ /* Notify and/or unload all dependencies */
@@ -937,6 +846,13 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
} }
} }
/* Tell it to unload */
if (pExt->IsLoaded())
{
IExtensionInterface *pAPI = pExt->GetAPI();
pAPI->OnExtensionUnload();
}
pExt->Unload(); pExt->Unload();
delete pExt; delete pExt;
@@ -1070,7 +986,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{ {
if (argcount < 4) if (argcount < 4)
{ {
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>"); g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>");
return; return;
} }
@@ -1078,7 +994,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
unsigned int id = atoi(sId); unsigned int id = atoi(sId);
if (id <= 0) if (id <= 0)
{ {
g_RootMenu.ConsolePrint("[SM] Usage: sm exts info <#>"); g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>");
return; return;
} }
@@ -1155,7 +1071,7 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
{ {
if (argcount < 4) if (argcount < 4)
{ {
g_RootMenu.ConsolePrint("[SM] Usage: sm exts unload <#> [code]"); g_RootMenu.ConsolePrint("[SM] Usage: sm unload <#> [code]");
return; return;
} }
@@ -1322,94 +1238,6 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmdname, const CCommand
g_RootMenu.DrawGenericOption("unload", "Unload an extension"); g_RootMenu.DrawGenericOption("unload", "Unload an extension");
} }
void CExtensionManager::ListExtensionsToClient(CPlayer *player, const CCommand &args)
{
char buffer[256];
int numExtensions = m_Libs.size();
edict_t *edict = player->GetEdict();
unsigned int id = 0;
unsigned int start = 0;
if (!numExtensions)
{
ClientConsolePrint(edict, "[SM] No extensions found.");
return;
}
if (args.ArgC() > 2)
{
start = atoi(args.Arg(2));
}
CExtension *ext;
SourceHook::List<CExtension *>::iterator iter;
for (iter = m_Libs.begin();
iter != m_Libs.end();
iter++)
{
ext = (*iter);
char error[255];
if (!ext->IsRunning(error, sizeof(error)))
{
continue;
}
id++;
if (id < start)
{
continue;
}
if (id - start > 10)
{
break;
}
IExtensionInterface *api = ext->GetAPI();
const char *name = api->GetExtensionName();
const char *version = api->GetExtensionVerString();
const char *author = api->GetExtensionAuthor();
const char *description = api->GetExtensionDescription();
size_t len = UTIL_Format(buffer, sizeof(buffer), " \"%s\"", name);
if (version != NULL && IS_STR_FILLED(version))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", version);
}
if (author != NULL && IS_STR_FILLED(author))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", author);
}
if (description != NULL && IS_STR_FILLED(description))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, ": %s", description);
}
ClientConsolePrint(edict, "%s", buffer);
}
while (iter != m_Libs.end())
{
char error[255];
if ((*iter)->IsRunning(error, sizeof(error)))
{
break;
}
}
if (iter != m_Libs.end())
{
ClientConsolePrint(edict, "To see more, type \"sm exts %d\"", id);
}
}
CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr) CExtension *CExtensionManager::GetExtensionFromIdent(IdentityToken_t *ptr)
{ {
if (ptr->type == g_ExtType) if (ptr->type == g_ExtType)
@@ -1432,7 +1260,7 @@ void CExtensionManager::AddLibrary(IExtension *pSource, const char *library)
{ {
CExtension *pExt = (CExtension *)pSource; CExtension *pExt = (CExtension *)pSource;
pExt->AddLibrary(library); pExt->AddLibrary(library);
g_PluginSys.OnLibraryAction(library, LibraryAction_Added); g_PluginSys.OnLibraryAction(library, false, false);
} }
bool CExtensionManager::LibraryExists(const char *library) bool CExtensionManager::LibraryExists(const char *library)
+1 -6
View File
@@ -45,8 +45,6 @@
#include "PluginSys.h" #include "PluginSys.h"
#include "NativeOwner.h" #include "NativeOwner.h"
class CPlayer;
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook; using namespace SourceHook;
@@ -68,7 +66,6 @@ public:
public: //IExtension public: //IExtension
IExtensionInterface *GetAPI(); IExtensionInterface *GetAPI();
const char *GetFilename(); const char *GetFilename();
const char *GetPath() const;
IdentityToken_t *GetIdentity(); IdentityToken_t *GetIdentity();
ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface); ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface); bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
@@ -166,7 +163,7 @@ public: //IPluginsListener
public: //IRootConsoleCommand public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *cmdname, const CCommand &command); void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
public: public:
IExtension *LoadAutoExtension(const char *path, bool bErrorOnMissing=true); IExtension *LoadAutoExtension(const char *path);
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo); void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
void AddInterface(IExtension *pOwner, SMInterface *pInterface); void AddInterface(IExtension *pOwner, SMInterface *pInterface);
void BindChildPlugin(IExtension *pParent, CPlugin *pPlugin); void BindChildPlugin(IExtension *pParent, CPlugin *pPlugin);
@@ -177,8 +174,6 @@ public:
bool LibraryExists(const char *library); bool LibraryExists(const char *library);
void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax); void CallOnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax);
void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface); void AddRawDependency(IExtension *ext, IdentityToken_t *other, void *iface);
public:
void ListExtensionsToClient(CPlayer *player, const CCommand &args);
public: public:
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr); CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
void Shutdown(); void Shutdown();
+8 -15
View File
@@ -1,5 +1,5 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
@@ -193,7 +193,6 @@ void CForwardManager::ForwardFree(CForward *fwd)
m_FreeForwards.push(fwd); m_FreeForwards.push(fwd);
m_managed.remove(fwd); m_managed.remove(fwd);
m_unmanaged.remove(fwd);
} }
CForward *CForwardManager::ForwardMake() CForward *CForwardManager::ForwardMake()
@@ -256,7 +255,6 @@ CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int nu
} }
CForward *pForward = g_Forwards.ForwardMake(); CForward *pForward = g_Forwards.ForwardMake();
pForward->m_IterGuard = NULL;
pForward->m_curparam = 0; pForward->m_curparam = 0;
pForward->m_ExecType = et; pForward->m_ExecType = et;
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : ""); snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
@@ -296,7 +294,7 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
cell_t high_result = 0; cell_t high_result = 0;
cell_t low_result = 0; cell_t low_result = 0;
int err; int err;
unsigned int success=0; unsigned int failed=0, success=0;
unsigned int num_params = m_curparam; unsigned int num_params = m_curparam;
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS]; FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
FwdParamInfo *param; FwdParamInfo *param;
@@ -306,15 +304,10 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
memcpy(temp_info, m_params, sizeof(m_params)); memcpy(temp_info, m_params, sizeof(m_params));
m_curparam = 0; m_curparam = 0;
FuncIteratorGuard guard(&m_IterGuard, &iter); for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
while (iter != m_functions.end())
{ {
func = (*iter); func = (*iter);
if (filter)
filter->Preprocess(func, temp_info);
for (unsigned int i=0; i<num_params; i++) for (unsigned int i=0; i<num_params; i++)
{ {
int err = SP_ERROR_PARAM; int err = SP_ERROR_PARAM;
@@ -366,7 +359,11 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
} }
/* Call the function and deal with the return value. */ /* Call the function and deal with the return value. */
if ((err=func->Execute(&cur_result)) == SP_ERROR_NONE) if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
{
failed++;
}
else
{ {
success++; success++;
switch (m_ExecType) switch (m_ExecType)
@@ -406,9 +403,6 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter)
} }
} }
} }
if (!guard.Triggered())
iter++;
} }
done: done:
@@ -688,7 +682,6 @@ bool CForward::RemoveFunction(IPluginFunction *func)
{ {
if ((*iter) == func) if ((*iter) == func)
{ {
m_IterGuard->FixIteratorChain(iter);
found = true; found = true;
lst->erase(iter); lst->erase(iter);
break; break;
-53
View File
@@ -61,58 +61,6 @@ struct FwdParamInfo
ParamType pushedas; ParamType pushedas;
}; };
class SourceMod::IForwardFilter
{
public:
virtual void Preprocess(IPluginFunction *fun, FwdParamInfo *params)
{
}
};
class FuncIteratorGuard
{
bool triggered;
FuncIteratorGuard **pprev;
FuncIter *iter;
FuncIteratorGuard *next;
public:
FuncIteratorGuard(FuncIteratorGuard **pprev, FuncIter *iter)
: triggered(false), pprev(pprev), iter(iter), next(*pprev)
{
*pprev = this;
}
~FuncIteratorGuard()
{
*pprev = next;
}
inline bool Triggered()
{
bool t = triggered;
triggered = false;
return t;
}
/**
* This should not read from |this| before the NULL check, because FwdSys
* can call (NULL)->FixIteratorChain().
*/
void FixIteratorChain(FuncIter &other)
{
FuncIteratorGuard *guard = this;
while (guard != NULL)
{
if (*guard->iter == other)
{
*(guard->iter) = ++(*(guard->iter));
guard->triggered = true;
}
guard = guard->next;
}
}
};
class CForward : public IChangeableForward class CForward : public IChangeableForward
{ {
public: //ICallable public: //ICallable
@@ -155,7 +103,6 @@ protected:
*/ */
mutable List<IPluginFunction *> m_functions; mutable List<IPluginFunction *> m_functions;
mutable List<IPluginFunction *> m_paused; mutable List<IPluginFunction *> m_paused;
FuncIteratorGuard *m_IterGuard;
/* Type and name information */ /* Type and name information */
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS]; FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
@@ -32,20 +32,26 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "GameConfigs.h" #include "GameConfigs.h"
//#include "sm_stringutil.h" #include "sm_stringutil.h"
//#include "sourcemod.h" #include "sourcemod.h"
//#include "sourcemm_api.h" #include "sourcemm_api.h"
//#include "HalfLife2.h" #include "HalfLife2.h"
//#include "Logger.h" #include "Logger.h"
//#include "ShareSys.h" #include "ShareSys.h"
//#include "MemoryUtils.h" #include "MemoryUtils.h"
//#include "LibrarySys.h" #include "LibrarySys.h"
//#include "HandleSys.h" #include "HandleSys.h"
//#include "sm_crc32.h" #include "sm_crc32.h"
//#if defined PLATFORM_LINUX #if defined PLATFORM_LINUX
//#include <dlfcn.h> #include <dlfcn.h>
//#endif #endif
GameConfigManager g_GameConfigs;
IGameConfig *g_pGameConf = NULL;
static char g_Game[256];
static char g_GameDesc[256] = {'!', '\0'};
static char g_GameName[256] = {'$', '\0'};
#define PSTATE_NONE 0 #define PSTATE_NONE 0
#define PSTATE_GAMES 1 #define PSTATE_GAMES 1
@@ -60,42 +66,70 @@
#define PSTATE_GAMEDEFS_CRC_BINARY 10 #define PSTATE_GAMEDEFS_CRC_BINARY 10
#define PSTATE_GAMEDEFS_CUSTOM 11 #define PSTATE_GAMEDEFS_CUSTOM 11
#define WIN 0 #if defined PLATFORM_WINDOWS
#define LIN 1 #define PLATFORM_NAME "windows"
#define PLATFORM_SERVER_BINARY "server.dll"
#elif defined PLATFORM_LINUX
#define PLATFORM_NAME "linux" #define PLATFORM_NAME "linux"
#define PLATFORM_SERVER_BINARY "server_i486.so" #define PLATFORM_SERVER_BINARY "server_i486.so"
#elif defined PLATFORM_APPLE
#define PLATFORM_NAME "undef"
#define PLATFORM_SERVER_BINARY "undef.dylib"
#endif
Offset *tempOffset; struct TempSigInfo
Sig *tempSig; {
void Reset()
{
library[0] = '\0';
sig[0] = '\0';
}
char sig[512];
char library[64];
} s_TempSig;
unsigned int s_ServerBinCRC; unsigned int s_ServerBinCRC;
bool s_ServerBinCRC_Ok = false; bool s_ServerBinCRC_Ok = false;
bool /*CGameConfig::*/DoesGameMatch(const char *value) static bool DoesGameMatch(const char *value)
{ {
if (strcmp(value, /*m_gdcG*/game) == 0) if (strcmp(value, g_Game) == 0 ||
strcmp(value, g_GameDesc) == 0 ||
strcmp(value, g_GameName) == 0)
{ {
return true; return true;
} }
return false; return false;
} }
bool /*CGameConfig::*/DoesEngineMatch(const char *value) static bool DoesEngineMatch(const char *value)
{ {
if (strcmp(value, /*m_gdcE*/engine) == 0) #if SOURCE_ENGINE == SE_EPISODEONE
if (strcmp(value, "original") == 0)
#elif SOURCE_ENGINE == SE_DARKMESSIAH
if (strcmp(value, "darkmessiah") == 0)
#elif SOURCE_ENGINE == SE_ORANGEBOX
if (strcmp(value, "orangebox") == 0)
#elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
if (strcmp(value, "orangebox_valve") == 0)
#elif SOURCE_ENGINE == SE_LEFT4DEAD
if (strcmp(value, "left4dead") == 0)
#else
#error "Unknown engine type"
#endif
{ {
return true; return true;
} }
return false; return false;
} }
CGameConfig::CGameConfig()//const char *file)//, const char *game, const char *engine) CGameConfig::CGameConfig(const char *file)
{ {
// strncopy(m_File, file, sizeof(m_File)); strncopy(m_File, file, sizeof(m_File));
// strncopy(m_gdcGame, game, sizeof(m_gdcGame)); m_pOffsets = sm_trie_create();
// strncopy(m_gdcEngine, engine, sizeof(m_gdcEngine)); m_pProps = sm_trie_create();
//m_pStrings = new BaseStringTable(512); m_pKeys = sm_trie_create();
m_pSigs = sm_trie_create();
m_pStrings = new BaseStringTable(512);
m_RefCount = 0; m_RefCount = 0;
m_CustomLevel = 0; m_CustomLevel = 0;
@@ -104,7 +138,11 @@ CGameConfig::CGameConfig()//const char *file)//, const char *game, const char *e
CGameConfig::~CGameConfig() CGameConfig::~CGameConfig()
{ {
// delete m_pStrings; sm_trie_destroy(m_pOffsets);
sm_trie_destroy(m_pProps);
sm_trie_destroy(m_pKeys);
sm_trie_destroy(m_pSigs);
delete m_pStrings;
} }
SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name) SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *name)
@@ -167,14 +205,11 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
} }
else if (strcmp(name, "CRC") == 0) else if (strcmp(name, "CRC") == 0)
{ {
#if 0
m_ParseState = PSTATE_GAMEDEFS_CRC; m_ParseState = PSTATE_GAMEDEFS_CRC;
bShouldBeReadingDefault = false; bShouldBeReadingDefault = false;
#endif
} }
else else
{ {
#if 0
ITextListener_SMC **pListen = g_GameConfigs.m_customHandlers.retrieve(name); ITextListener_SMC **pListen = g_GameConfigs.m_customHandlers.retrieve(name);
if (pListen != NULL) if (pListen != NULL)
@@ -185,7 +220,8 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
m_CustomHandler->ReadSMC_ParseStart(); m_CustomHandler->ReadSMC_ParseStart();
break; break;
} }
#endif
m_IgnoreLevel++;
} }
break; break;
} }
@@ -193,19 +229,17 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
{ {
m_Prop[0] = '\0'; m_Prop[0] = '\0';
m_Class[0] = '\0'; m_Class[0] = '\0';
tempOffset = new Offset(); strncopy(m_offset, name, sizeof(m_offset));
tempOffset->setName(name);
m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET; m_ParseState = PSTATE_GAMEDEFS_OFFSETS_OFFSET;
break; break;
} }
case PSTATE_GAMEDEFS_SIGNATURES: case PSTATE_GAMEDEFS_SIGNATURES:
{ {
tempSig = new Sig(); strncopy(m_offset, name, sizeof(m_offset));
tempSig->setName(name); s_TempSig.Reset();
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG; m_ParseState = PSTATE_GAMEDEFS_SIGNATURES_SIG;
break; break;
} }
#if 0
case PSTATE_GAMEDEFS_CRC: case PSTATE_GAMEDEFS_CRC:
{ {
char error[255]; char error[255];
@@ -255,7 +289,6 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
return m_CustomHandler->ReadSMC_NewSection(states, name); return m_CustomHandler->ReadSMC_NewSection(states, name);
break; break;
} }
#endif
/* No sub-sections allowed: /* No sub-sections allowed:
case PSTATE_GAMEDEFS_OFFSETS_OFFSET: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
case PSTATE_GAMEDEFS_KEYS: case PSTATE_GAMEDEFS_KEYS:
@@ -288,17 +321,13 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
strncopy(m_Class, value, sizeof(m_Class)); strncopy(m_Class, value, sizeof(m_Class));
} else if (strcmp(key, "prop") == 0) { } else if (strcmp(key, "prop") == 0) {
strncopy(m_Prop, value, sizeof(m_Prop)); strncopy(m_Prop, value, sizeof(m_Prop));
} else /*if (strcmp(key, PLATFORM_NAME) == 0) */ { } else if (strcmp(key, PLATFORM_NAME) == 0) {
int val = atoi(value); int val = atoi(value);
// sm_trie_replace(m_pOffsets, m_offset, (void *)val); sm_trie_replace(m_pOffsets, m_offset, (void *)val);
if (strcmp(key, "windows") == 0) tempOffset->setWin(val);
else if (strcmp(key, "linux") == 0) tempOffset->setLin(val);
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) { } else if (m_ParseState == PSTATE_GAMEDEFS_KEYS) {
m_Keys[key] = value; int id = m_pStrings->AddString(value);
// printf("Inserting %s - %s\n", key, value); sm_trie_replace(m_pKeys, key, (void *)id);
// int id = m_pStrings->AddString(value);
// sm_trie_replace(m_pKeys, key, (void *)id);
} else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) { } else if (m_ParseState == PSTATE_GAMEDEFS_SUPPORTED) {
if (strcmp(key, "game") == 0) if (strcmp(key, "game") == 0)
{ {
@@ -325,9 +354,12 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
} }
} }
} else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) { } else if (m_ParseState == PSTATE_GAMEDEFS_SIGNATURES_SIG) {
if (strcmp(key, "windows") == 0) tempSig->setWin(value); if (strcmp(key, PLATFORM_NAME) == 0)
else if (strcmp(key, "linux") == 0) tempSig->setLin(value); {
else if (strcmp(key, "library") == 0) tempSig->setLib(value); 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) { } else if (m_ParseState == PSTATE_GAMEDEFS_CRC_BINARY) {
if (strcmp(key, PLATFORM_NAME) == 0 if (strcmp(key, PLATFORM_NAME) == 0
&& s_ServerBinCRC_Ok && s_ServerBinCRC_Ok
@@ -388,8 +420,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
} }
case PSTATE_GAMEDEFS_OFFSETS_OFFSET: case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
{ {
m_Offsets.push_back(*tempOffset);
#if 0
/* Parse the offset... */ /* Parse the offset... */
if (m_Class[0] != '\0' if (m_Class[0] != '\0'
&& m_Prop[0] != '\0') && m_Prop[0] != '\0')
@@ -413,7 +443,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
} }
} }
} }
#endif
m_ParseState = PSTATE_GAMEDEFS_OFFSETS; m_ParseState = PSTATE_GAMEDEFS_OFFSETS;
break; break;
} }
@@ -442,8 +471,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
} }
case PSTATE_GAMEDEFS_SIGNATURES_SIG: case PSTATE_GAMEDEFS_SIGNATURES_SIG:
{ {
m_Sigs.push_back(*tempSig);
#if 0
if (s_TempSig.library[0] == '\0') if (s_TempSig.library[0] == '\0')
{ {
/* assume server */ /* assume server */
@@ -538,7 +565,6 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
skip_find: skip_find:
#endif #endif
sm_trie_replace(m_pSigs, m_offset, final_addr); sm_trie_replace(m_pSigs, m_offset, final_addr);
#endif
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES; m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
break; break;
@@ -663,7 +689,7 @@ public:
return SMCResult_Continue; return SMCResult_Continue;
} }
public: public:
list<char*> *fileList; List<String> *fileList;
unsigned int state; unsigned int state;
unsigned int ignoreLevel; unsigned int ignoreLevel;
char cur_file[PLATFORM_MAX_PATH]; char cur_file[PLATFORM_MAX_PATH];
@@ -678,21 +704,26 @@ static MasterReader master_reader;
bool CGameConfig::Reparse(char *error, size_t maxlength) bool CGameConfig::Reparse(char *error, size_t maxlength)
{ {
/* Reset cached data */ /* Reset cached data */
// m_pStrings->Reset(); m_pStrings->Reset();
m_Offsets.clear(); sm_trie_clear(m_pOffsets);
m_Sigs.clear(); sm_trie_clear(m_pProps);
sm_trie_clear(m_pKeys);
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
/* See if we can use the extended gamedata format. */ /* See if we can use the extended gamedata format. */
//TODO pass in path to gamedata somehow g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/master.games.txt", m_File);
// g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/master.games.txt", m_File); if (!g_LibSys.PathExists(path))
{
/* Nope, use the old mechanism. */
UTIL_Format(path, sizeof(path), "%s.txt", m_File);
return EnterFile(path, error, maxlength);
}
/* Otherwise, it's time to parse the master. */ /* Otherwise, it's time to parse the master. */
SMCError err; SMCError err;
SMCStates state = {0, 0}; SMCStates state = {0, 0};
list<char*> fileList; List<String> fileList;
master_reader.fileList = &fileList; master_reader.fileList = &fileList;
err = textparsers->ParseSMCFile(path, &master_reader, &state, error, maxlength); err = textparsers->ParseSMCFile(path, &master_reader, &state, error, maxlength);
@@ -700,26 +731,64 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
{ {
const char *msg = textparsers->GetSMCErrorString(err); const char *msg = textparsers->GetSMCErrorString(err);
printf("[SM] Error parsing master gameconf file \"%s\":", path); g_Logger.LogError("[SM] Error parsing master gameconf file \"%s\":", path);
printf("[SM] Error %d on line %d, col %d: %s", g_Logger.LogError("[SM] Error %d on line %d, col %d: %s",
err, err,
state.line, state.line,
state.col, state.col,
msg ? msg : "Unknown error"); msg ? msg : "Unknown error");
exit(PARSE_ERROR); return false;
} }
/* Go through each file we found and parse it. */ /* Go through each file we found and parse it. */
list<char*>::iterator iter; List<String>::iterator iter;
for (iter = fileList.begin(); iter != fileList.end(); iter++) for (iter = fileList.begin(); iter != fileList.end(); iter++)
{ {
UTIL_Format(path, sizeof(path), "%s/%s", m_File, *iter); UTIL_Format(path, sizeof(path), "%s/%s", m_File, (*iter).c_str());
if (!EnterFile(path, error, maxlength)) if (!EnterFile(path, error, maxlength))
{ {
return false; return false;
} }
} }
/* Parse the contents of the 'custom' directory */
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "gamedata/%s/custom", m_File);
IDirectory *customDir = g_LibSys.OpenDirectory(path);
if (!customDir)
{
return true;
}
while (customDir->MoreFiles())
{
if (!customDir->IsEntryFile())
{
customDir->NextEntry();
continue;
}
const char *curFile = customDir->GetEntryName();
/* Only allow .txt files */
int len = strlen(curFile);
if (len > 4 && strcmp(&curFile[len-4], ".txt") != 0)
{
customDir->NextEntry();
continue;
}
UTIL_Format(path, sizeof(path), "%s/custom/%s", m_File, curFile);
if (!EnterFile(path, error, maxlength))
{
g_LibSys.CloseDirectory(customDir);
return false;
}
customDir->NextEntry();
}
g_LibSys.CloseDirectory(customDir);
return true; return true;
} }
@@ -728,20 +797,22 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
SMCError err; SMCError err;
SMCStates state = {0, 0}; SMCStates state = {0, 0};
g_SourceMod.BuildPath(Path_SM, m_CurFile, sizeof(m_CurFile), "gamedata/%s", file);
/* Initialize parse states */ /* Initialize parse states */
m_IgnoreLevel = 0; m_IgnoreLevel = 0;
bShouldBeReadingDefault = true; bShouldBeReadingDefault = true;
m_ParseState = PSTATE_NONE; m_ParseState = PSTATE_NONE;
if ((err=textparsers->ParseSMCFile(file, this, &state, error, maxlength)) if ((err=textparsers->ParseSMCFile(m_CurFile, this, &state, error, maxlength))
!= SMCError_Okay) != SMCError_Okay)
{ {
const char *msg; const char *msg;
msg = textparsers->GetSMCErrorString(err); msg = textparsers->GetSMCErrorString(err);
printf("[SM] Error parsing gameconfig file \"%s\":\n", file); g_Logger.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile);
printf("[SM] Error %d on line %d, col %d: %s\n", g_Logger.LogError("[SM] Error %d on line %d, col %d: %s",
err, err,
state.line, state.line,
state.col, state.col,
@@ -755,13 +826,12 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength)
m_CustomLevel = 0; m_CustomLevel = 0;
} }
exit(PARSE_ERROR); return false;
} }
return true; return true;
} }
#if 0
bool CGameConfig::GetOffset(const char *key, int *value) bool CGameConfig::GetOffset(const char *key, int *value)
{ {
void *obj; void *obj;
@@ -813,16 +883,149 @@ unsigned int CGameConfig::DecRefCount()
m_RefCount--; m_RefCount--;
return m_RefCount; return m_RefCount;
} }
#endif
const char *CGameConfig::GetKeyValue(const char *key) GameConfigManager::GameConfigManager()
{ {
map<const char*,const char*,cmp_str>::iterator it = m_Keys.find(key); m_pLookup = sm_trie_create();
if (it == m_Keys.end()) return NULL;
return it->second;
} }
list<Offset> CGameConfig::GetOffsets() { return m_Offsets; } GameConfigManager::~GameConfigManager()
list<Sig> CGameConfig::GetSigs() { return m_Sigs; } {
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);
KeyValues *pGameInfo = new KeyValues("GameInfo");
if (g_HL2.KVLoadFromFile(pGameInfo, basefilesystem, "gameinfo.txt"))
{
const char *str;
if ((str = pGameInfo->GetString("game", NULL)) != NULL)
{
strncopy(g_GameName + 1, str, sizeof(g_GameName) - 1);
}
}
pGameInfo->deleteThis();
}
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)
{
#if 0
/* A crash was detected during last load - We block the gamedata loading so it hopefully won't happen again */
if (g_blockGameDataLoad)
{
UTIL_Format(error, maxlength, "GameData loaded blocked due to detected crash");
return false;
}
#endif
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_File);
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;
}
void GameConfigManager::AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener)
{
m_customHandlers.insert(sectionname, listener);
}
void GameConfigManager::RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener)
{
ITextListener_SMC **pListener = m_customHandlers.retrieve(sectionname);
if (pListener == NULL)
{
return;
}
if (*pListener != listener)
{
return;
}
m_customHandlers.remove(sectionname);
return;
}
void GameConfigManager::AcquireLock()
{
}
void GameConfigManager::ReleaseLock()
{
}
+10 -31
View File
@@ -32,12 +32,14 @@
#ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_ #ifndef _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
#define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_ #define _INCLUDE_SOURCEMOD_CGAMECONFIGS_H_
#include "common_logic.h"
#include <IGameConfigs.h> #include <IGameConfigs.h>
#include <ITextParsers.h> #include <ITextParsers.h>
#include <sh_list.h> #include <sh_list.h>
#include "sm_trie.h"
#include "sm_globals.h"
#include "sm_memtable.h" #include "sm_memtable.h"
#include <sm_trie_tpl.h> #include "sm_trie_tpl.h"
#include "ThreadSupport.h"
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook; using namespace SourceHook;
@@ -50,13 +52,11 @@ class CGameConfig :
{ {
friend class GameConfigManager; friend class GameConfigManager;
public: public:
CGameConfig(const char *file, const char *engine = NULL); CGameConfig(const char *file);
~CGameConfig(); ~CGameConfig();
public: public:
bool Reparse(char *error, size_t maxlength); bool Reparse(char *error, size_t maxlength);
bool EnterFile(const char *file, char *error, size_t maxlength); bool EnterFile(const char *file, char *error, size_t maxlength);
void SetBaseEngine(const char *engine);
void SetParseEngine(const char *engine);
public: //ITextListener_SMC public: //ITextListener_SMC
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
@@ -66,7 +66,6 @@ public: //IGameConfig
bool GetOffset(const char *key, int *value); bool GetOffset(const char *key, int *value);
SendProp *GetSendProp(const char *key); SendProp *GetSendProp(const char *key);
bool GetMemSig(const char *key, void **addr); bool GetMemSig(const char *key, void **addr);
bool GetAddress(const char *key, void **addr);
public: public:
void IncRefCount(); void IncRefCount();
unsigned int DecRefCount(); unsigned int DecRefCount();
@@ -74,10 +73,10 @@ private:
BaseStringTable *m_pStrings; BaseStringTable *m_pStrings;
char m_File[PLATFORM_MAX_PATH]; char m_File[PLATFORM_MAX_PATH];
char m_CurFile[PLATFORM_MAX_PATH]; char m_CurFile[PLATFORM_MAX_PATH];
KTrie<int> m_Offsets; Trie *m_pOffsets;
KTrie<SendProp *> m_Props; Trie *m_pProps;
KTrie<int> m_Keys; Trie *m_pKeys;
KTrie<void *> m_Sigs; Trie *m_pSigs;
unsigned int m_RefCount; unsigned int m_RefCount;
/* Parse states */ /* Parse states */
int m_ParseState; int m_ParseState;
@@ -95,26 +94,6 @@ private:
/* Custom Sections */ /* Custom Sections */
unsigned int m_CustomLevel; unsigned int m_CustomLevel;
ITextListener_SMC *m_CustomHandler; ITextListener_SMC *m_CustomHandler;
/* Support for reading Addresses */
struct AddressConf
{
char signatureName[64];
int readCount;
int read[8];
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
AddressConf() {}
};
char m_Address[64];
char m_AddressSignature[64];
int m_AddressReadCount;
int m_AddressRead[8];
KTrie<AddressConf> *m_pAddresses;
const char *m_pEngine;
const char *m_pBaseEngine;
}; };
class GameConfigManager : class GameConfigManager :
@@ -140,7 +119,7 @@ public: //SMGlobalClass
void OnSourceModAllShutdown(); void OnSourceModAllShutdown();
private: private:
List<CGameConfig *> m_cfgs; List<CGameConfig *> m_cfgs;
KTrie<CGameConfig *> m_Lookup; Trie *m_pLookup;
public: public:
KTrie<ITextListener_SMC *> m_customHandlers; KTrie<ITextListener_SMC *> m_customHandlers;
}; };
+16 -594
View File
@@ -35,60 +35,12 @@
#include "UserMessages.h" #include "UserMessages.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include <IGameConfigs.h> #include "GameConfigs.h"
#include <compat_wrappers.h> #include <compat_wrappers.h>
#include <Logger.h>
#include "LibrarySys.h"
#include "logic_bridge.h"
#include <tier0/mem.h>
#if SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessages.pb.h>
#endif
typedef ICommandLine *(*FakeGetCommandLine)();
#if defined _WIN32
#define TIER0_NAME "tier0.dll"
#define VSTDLIB_NAME "vstdlib.dll"
#elif defined __APPLE__
#define TIER0_NAME "libtier0.dylib"
#define VSTDLIB_NAME "libvstdlib.dylib"
#elif defined __linux__
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_LEFT4DEAD2
#define TIER0_NAME "libtier0_srv.so"
#define VSTDLIB_NAME "libvstdlib_srv.so"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#define TIER0_NAME "libtier0.so"
#define VSTDLIB_NAME "libvstdlib.so"
#else
#define TIER0_NAME "tier0_i486.so"
#define VSTDLIB_NAME "vstdlib_i486.so"
#endif
#endif
CHalfLife2 g_HL2; CHalfLife2 g_HL2;
ConVar *sv_lan = NULL; ConVar *sv_lan = NULL;
static void *g_EntList = NULL;
static void **g_pEntInfoList = NULL;
static int entInfoOffset = -1;
static CEntInfo *EntInfoArray()
{
if (g_EntList != NULL)
{
return (CEntInfo *)((intp)g_EntList + entInfoOffset);
}
else if (g_pEntInfoList)
{
return *(CEntInfo **)g_pEntInfoList;
}
return NULL;
}
namespace SourceHook namespace SourceHook
{ {
template<> template<>
@@ -140,16 +92,14 @@ CHalfLife2::~CHalfLife2()
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL; CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
#endif #endif
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
bool is_original_engine = false; bool is_original_engine = false;
#endif
void CHalfLife2::OnSourceModStartup(bool late) void CHalfLife2::OnSourceModStartup(bool late)
{ {
#if SOURCE_ENGINE != SE_DARKMESSIAH #if SOURCE_ENGINE != SE_DARKMESSIAH
/* The Ship currently is the only known game to use an older version of the engine */ /* The Ship currently is the only known game to use an older version of the engine */
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 #if defined METAMOD_PLAPI_VERSION
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL) if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
#else #else
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0) if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
@@ -173,136 +123,7 @@ void CHalfLife2::OnSourceModAllInitialized()
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
void CHalfLife2::OnSourceModAllInitialized_Post() #if !defined METAMOD_PLAPI_VERSION
{
InitLogicalEntData();
InitCommandLine();
}
void CHalfLife2::InitLogicalEntData()
{
char *addr = NULL;
/*
* gEntList and/or g_pEntityList
*
* First try to lookup pointer directly for platforms with symbols.
* If symbols aren't present (Windows or stripped Linux/Mac),
* attempt find via LevelShutdown + offset
*/
if (g_pGameConf->GetMemSig("gEntList", (void **)&addr))
{
#if !defined PLATFORM_WINDOWS
if (!addr)
{
// Key exists so notify if lookup fails, but try other method.
g_Logger.LogError("Failed lookup of gEntList directly - Reverting to lookup via LevelShutdown");
}
else
{
#endif
g_EntList = reinterpret_cast<void *>(addr);
#if !defined PLATFORM_WINDOWS
}
#endif
}
if (!g_EntList)
{
if (g_pGameConf->GetMemSig("LevelShutdown", (void **) &addr) && addr)
{
int offset;
if (!g_pGameConf->GetOffset("gEntList", &offset))
{
g_Logger.LogError("Logical Entities not supported by this mod (gEntList) - Reverting to networkable entities only");
return;
}
g_EntList = *reinterpret_cast<void **>(addr + offset);
}
}
// If we have g_EntList from either of the above methods, make sure we can get the offset from it to EntInfo as well
if (g_EntList && !g_pGameConf->GetOffset("EntInfo", &entInfoOffset))
{
g_Logger.LogError("Logical Entities not supported by this mod (EntInfo) - Reverting to networkable entities only");
g_EntList = NULL;
return;
}
// If we don't have g_EntList or have it but don't know where EntInfo is on it, use fallback.
if (!g_EntList || entInfoOffset == -1)
{
g_pGameConf->GetAddress("EntInfosPtr", (void **)&g_pEntInfoList);
}
if (!g_EntList && !g_pEntInfoList)
{
g_Logger.LogError("Failed lookup of gEntList - Reverting to networkable entities only");
return;
}
}
void CHalfLife2::InitCommandLine()
{
char path[PLATFORM_MAX_PATH];
char error[256];
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "../bin/" TIER0_NAME);
if (!g_LibSys.IsPathFile(path))
{
g_Logger.LogError("Could not find path for: " TIER0_NAME);
return;
}
ILibrary *lib = g_LibSys.OpenLibrary(path, error, sizeof(error));
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine_Tier0");
/* '_Tier0' dropped on Alien Swarm version */
if (m_pGetCommandLine == NULL)
{
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
}
if (m_pGetCommandLine == NULL)
{
/* We probably have a Ship engine. */
lib->CloseLibrary();
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "../bin/" VSTDLIB_NAME);
if (!g_LibSys.IsPathFile(path))
{
g_Logger.LogError("Could not find path for: " VSTDLIB_NAME);
return;
}
if ((lib = g_LibSys.OpenLibrary(path, error, sizeof(error))) == NULL)
{
g_Logger.LogError("Could not load %s: %s", path, error);
return;
}
m_pGetCommandLine = lib->GetSymbolAddress("CommandLine");
if (m_pGetCommandLine == NULL)
{
g_Logger.LogError("Could not locate any command line functionality");
}
lib->CloseLibrary();
}
}
ICommandLine *CHalfLife2::GetValveCommandLine()
{
if (!m_pGetCommandLine)
return NULL;
return ((FakeGetCommandLine)((FakeGetCommandLine *)m_pGetCommandLine))();
}
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11
bool CHalfLife2::IsOriginalEngine() bool CHalfLife2::IsOriginalEngine()
{ {
return is_original_engine; return is_original_engine;
@@ -351,13 +172,8 @@ bool UTIL_FindInSendTable(SendTable *pTable,
return false; return false;
} }
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name, bool *isNested) typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
{ {
if (isNested)
{
*isNested = false;
}
while (pMap) while (pMap)
{ {
for (int i=0; i<pMap->dataNumFields; i++) for (int i=0; i<pMap->dataNumFields; i++)
@@ -372,21 +188,10 @@ typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name, bool *i
} }
if (pMap->dataDesc[i].td) if (pMap->dataDesc[i].td)
{ {
if (isNested) typedescription_t *_td;
if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
{ {
*isNested = (UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL) != NULL); return _td;
if (*isNested)
{
return NULL;
} else {
continue;
}
} else { // Use the old behaviour, we dont want to spring this on extensions - even if they're doing bad things.
typedescription_t *_td;
if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL)) != NULL)
{
return _td;
}
} }
} }
} }
@@ -479,11 +284,6 @@ SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
} }
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset) typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
{
return this->FindInDataMap(pMap, offset, NULL);
}
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested)
{ {
typedescription_t *td = NULL; typedescription_t *td = NULL;
DataMapTrie &val = m_Maps[pMap]; DataMapTrie &val = m_Maps[pMap];
@@ -494,7 +294,7 @@ typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset
} }
if (!sm_trie_retrieve(val.trie, offset, (void **)&td)) if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
{ {
if ((td = UTIL_FindInDataMap(pMap, offset, isNested)) != NULL) if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
{ {
sm_trie_insert(val.trie, offset, td); sm_trie_insert(val.trie, offset, td);
} }
@@ -526,9 +326,7 @@ void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
bool CHalfLife2::TextMsg(int client, int dest, const char *msg) bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
{ {
#if SOURCE_ENGINE != SE_CSGO
bf_write *pBitBuf = NULL; bf_write *pBitBuf = NULL;
#endif
cell_t players[] = {client}; cell_t players[] = {client};
if (dest == HUD_PRINTTALK) if (dest == HUD_PRINTTALK)
@@ -541,18 +339,7 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
char buffer[192]; char buffer[192];
UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg); UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
#if SOURCE_ENGINE == SE_CSGO if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
CCSUsrMsg_SayText *pMsg;
if ((pMsg = (CCSUsrMsg_SayText *)g_UserMsgs.StartProtobufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_ent_idx(0);
pMsg->set_text(buffer);
pMsg->set_chat(false);
#else
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{ {
return false; return false;
} }
@@ -560,7 +347,6 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
pBitBuf->WriteByte(0); pBitBuf->WriteByte(0);
pBitBuf->WriteString(buffer); pBitBuf->WriteString(buffer);
pBitBuf->WriteByte(1); pBitBuf->WriteByte(1);
#endif
g_UserMsgs.EndMessage(); g_UserMsgs.EndMessage();
@@ -568,29 +354,13 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
} }
} }
#if SOURCE_ENGINE == SE_CSGO if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
CCSUsrMsg_TextMsg *pMsg;
if ((pMsg = (CCSUsrMsg_TextMsg *)g_UserMsgs.StartProtobufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
// Client tries to read all 5 'params' and will crash if less
pMsg->set_msg_dst(dest);
pMsg->add_params(msg);
pMsg->add_params("");
pMsg->add_params("");
pMsg->add_params("");
pMsg->add_params("");
#else
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{ {
return false; return false;
} }
pBitBuf->WriteByte(dest); pBitBuf->WriteByte(dest);
pBitBuf->WriteString(msg); pBitBuf->WriteString(msg);
#endif
g_UserMsgs.EndMessage(); g_UserMsgs.EndMessage();
@@ -599,20 +369,10 @@ bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
bool CHalfLife2::HintTextMsg(int client, const char *msg) bool CHalfLife2::HintTextMsg(int client, const char *msg)
{ {
bf_write *pBitBuf = NULL;
cell_t players[] = {client}; cell_t players[] = {client};
#if SOURCE_ENGINE == SE_CSGO if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_text(msg);
#else
bf_write *pBitBuf = NULL;
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
{ {
return false; return false;
} }
@@ -623,38 +383,6 @@ bool CHalfLife2::HintTextMsg(int client, const char *msg)
pBitBuf->WriteByte(1); pBitBuf->WriteByte(1);
} }
pBitBuf->WriteString(msg); pBitBuf->WriteString(msg);
#endif
g_UserMsgs.EndMessage();
return true;
}
bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
{
#if SOURCE_ENGINE == SE_CSGO
CCSUsrMsg_HintText *pMsg;
if ((pMsg = (CCSUsrMsg_HintText *)g_UserMsgs.StartProtobufMessage(m_HinTextMsg, players, count, USERMSG_RELIABLE)) == NULL)
{
return false;
}
pMsg->set_text(msg);
#else
bf_write *pBitBuf = NULL;
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_HinTextMsg, players, count, 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);
#endif
g_UserMsgs.EndMessage(); g_UserMsgs.EndMessage();
return true; return true;
@@ -662,23 +390,15 @@ bool CHalfLife2::HintTextMsg(cell_t *players, int count, const char *msg)
bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show) bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
{ {
bf_write *pBitBuf = NULL;
KeyValues *SubKey = NULL; KeyValues *SubKey = NULL;
int count = 0; int count = 0;
cell_t players[] = {client}; cell_t players[] = {client};
#if SOURCE_ENGINE == SE_CSGO if ((pBitBuf = g_UserMsgs.StartMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
CCSUsrMsg_VGUIMenu *pMsg;
if ((pMsg = (CCSUsrMsg_VGUIMenu *)g_UserMsgs.StartProtobufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{ {
return false; return false;
} }
#else
bf_write *pBitBuf = NULL;
if ((pBitBuf = g_UserMsgs.StartBitBufMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
{
return false;
}
#endif
if (data) if (data)
{ {
@@ -691,18 +411,6 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
SubKey = data->GetFirstSubKey(); SubKey = data->GetFirstSubKey();
} }
#if SOURCE_ENGINE == SE_CSGO
pMsg->set_name(name);
pMsg->set_show(show);
while (SubKey)
{
CCSUsrMsg_VGUIMenu_Subkey *key = pMsg->add_subkeys();
key->set_name(SubKey->GetName());
key->set_str(SubKey->GetString());
SubKey = SubKey->GetNextKey();
}
#else
pBitBuf->WriteString(name); pBitBuf->WriteString(name);
pBitBuf->WriteByte((show) ? 1 : 0); pBitBuf->WriteByte((show) ? 1 : 0);
pBitBuf->WriteByte(count); pBitBuf->WriteByte(count);
@@ -712,8 +420,6 @@ bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, boo
pBitBuf->WriteString(SubKey->GetString()); pBitBuf->WriteString(SubKey->GetString());
SubKey = SubKey->GetNextKey(); SubKey = SubKey->GetNextKey();
} }
#endif
g_UserMsgs.EndMessage(); g_UserMsgs.EndMessage();
return true; return true;
@@ -751,7 +457,6 @@ void CHalfLife2::ProcessFakeCliCmdQueue()
} }
m_CmdQueue.pop(); m_CmdQueue.pop();
m_FreeCmds.push(pFake);
} }
} }
@@ -769,7 +474,7 @@ bool CHalfLife2::IsLANServer()
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID) bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
{ {
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11 #if defined METAMOD_PLAPI_VERSION
if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL) if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
#else #else
if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0) if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
@@ -846,14 +551,6 @@ const char *CHalfLife2::CurrentCommandName()
void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg) void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
{ {
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer || !pPlayer->IsConnected() || pPlayer->IsInKickQueue())
{
return;
}
pPlayer->MarkAsBeingKicked();
DelayedKickInfo kick; DelayedKickInfo kick;
kick.client = client; kick.client = client;
@@ -902,10 +599,7 @@ edict_t *CHalfLife2::GetHandleEntity(CBaseHandle &hndl)
edict_t *pStoredEdict; edict_t *pStoredEdict;
CBaseEntity *pStoredEntity; CBaseEntity *pStoredEntity;
if (!IndexToAThings(index, &pStoredEntity, &pStoredEdict)) pStoredEdict = GetEntity(index, &pStoredEntity);
{
return NULL;
}
if (pStoredEdict == NULL || pStoredEntity == NULL) if (pStoredEdict == NULL || pStoredEntity == NULL)
{ {
@@ -948,275 +642,3 @@ void CHalfLife2::ServerCommand(const char *buffer)
{ {
engine->ServerCommand(buffer); engine->ServerCommand(buffer);
} }
cell_t CHalfLife2::EntityToReference(CBaseEntity *pEntity)
{
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
CBaseHandle hndl = pUnknown->GetRefEHandle();
return (hndl.ToInt() | (1<<31));
}
CBaseEntity *CHalfLife2::ReferenceToEntity(cell_t entRef)
{
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
{
return NULL;
}
CEntInfo *pInfo = NULL;
if (entRef & (1<<31))
{
/* Proper ent reference */
int hndlValue = entRef & ~(1<<31);
CBaseHandle hndl(hndlValue);
pInfo = LookupEntity(hndl.GetEntryIndex());
if (!pInfo || pInfo->m_SerialNumber != hndl.GetSerialNumber())
{
return NULL;
}
}
else
{
/* Old style index only */
pInfo = LookupEntity(entRef);
}
if (!pInfo)
{
return NULL;
}
IServerUnknown *pUnk = static_cast<IServerUnknown *>(pInfo->m_pEntity);
if (pUnk)
{
return pUnk->GetBaseEntity();
}
return NULL;
}
/**
* Retrieves the CEntInfo pointer from g_EntList for a given entity index
*/
CEntInfo *CHalfLife2::LookupEntity(int entIndex)
{
// Make sure that our index is within the bounds of the global ent array
if (entIndex < 0 || entIndex >= NUM_ENT_ENTRIES)
{
return NULL;
}
CEntInfo *entInfos = EntInfoArray();
if (!entInfos)
{
/* Attempt to use engine interface instead */
static CEntInfo tempInfo;
tempInfo.m_pNext = NULL;
tempInfo.m_pPrev = NULL;
edict_t *pEdict = PEntityOfEntIndex(entIndex);
if (!pEdict)
{
return NULL;
}
IServerUnknown *pUnk = pEdict->GetUnknown();
if (!pUnk)
{
return NULL;
}
tempInfo.m_pEntity = pUnk;
tempInfo.m_SerialNumber = pUnk->GetRefEHandle().GetSerialNumber();
return &tempInfo;
}
return &entInfos[entIndex];
}
/**
SERIAL_MASK = 0x7fff (15 bits)
#define MAX_EDICT_BITS 11
#define NUM_ENT_ENTRY_BITS (MAX_EDICT_BITS + 1)
m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS);
Top 5 bits of a handle are unused.
Bit 31 - Our 'reference' flag indicator
*/
cell_t CHalfLife2::IndexToReference(int entIndex)
{
CBaseEntity *pEnt = ReferenceToEntity(entIndex);
if (!pEnt)
{
return INVALID_EHANDLE_INDEX;
}
return EntityToReference(pEnt);
}
int CHalfLife2::ReferenceToIndex(cell_t entRef)
{
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
{
return INVALID_EHANDLE_INDEX;
}
if (entRef & (1<<31))
{
/* Proper ent reference */
int hndlValue = entRef & ~(1<<31);
CBaseHandle hndl(hndlValue);
CEntInfo *pInfo = LookupEntity(hndl.GetEntryIndex());
if (pInfo->m_SerialNumber != hndl.GetSerialNumber())
{
return INVALID_EHANDLE_INDEX;
}
return hndl.GetEntryIndex();
}
return entRef;
}
cell_t CHalfLife2::EntityToBCompatRef(CBaseEntity *pEntity)
{
if (pEntity == NULL)
{
return INVALID_EHANDLE_INDEX;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
CBaseHandle hndl = pUnknown->GetRefEHandle();
if (hndl == INVALID_EHANDLE_INDEX)
{
return INVALID_EHANDLE_INDEX;
}
if (hndl.GetEntryIndex() >= MAX_EDICTS)
{
return (hndl.ToInt() | (1<<31));
}
else
{
return hndl.GetEntryIndex();
}
}
cell_t CHalfLife2::ReferenceToBCompatRef(cell_t entRef)
{
if ((unsigned)entRef == INVALID_EHANDLE_INDEX)
{
return INVALID_EHANDLE_INDEX;
}
int hndlValue = entRef & ~(1<<31);
CBaseHandle hndl(hndlValue);
if (hndl.GetEntryIndex() < MAX_EDICTS)
{
return hndl.GetEntryIndex();
}
return entRef;
}
void *CHalfLife2::GetGlobalEntityList()
{
return g_EntList;
}
int CHalfLife2::GetSendPropOffset(SendProp *prop)
{
return prop->GetOffset();
}
const char *CHalfLife2::GetEntityClassname(edict_t * pEdict)
{
if (pEdict == NULL || pEdict->IsFree())
{
return NULL;
}
IServerUnknown *pUnk = pEdict->GetUnknown();
if (pUnk == NULL)
{
return NULL;
}
CBaseEntity * pEntity = pUnk->GetBaseEntity();
if (pEntity == NULL)
{
return NULL;
}
return GetEntityClassname(pEntity);
}
const char *CHalfLife2::GetEntityClassname(CBaseEntity *pEntity)
{
static int offset = -1;
if (offset == -1)
{
datamap_t *pMap = GetDataMap(pEntity);
typedescription_t *pDesc = FindInDataMap(pMap, "m_iClassname");
offset = GetTypeDescOffs(pDesc);
}
return *(const char **)(((unsigned char *)pEntity) + offset);
}
#if SOURCE_ENGINE >= SE_LEFT4DEAD
static bool ResolveFuzzyMapName(const char *fuzzyName, char *outFullname, int size)
{
static ConCommand *pHelperCmd = g_pCVar->FindCommand("changelevel");
if (!pHelperCmd || !pHelperCmd->CanAutoComplete())
return false;
static size_t helperCmdLen = strlen(pHelperCmd->GetName());
CUtlVector<CUtlString> results;
pHelperCmd->AutoCompleteSuggest(fuzzyName, results);
if (results.Count() == 0)
return false;
// Results come back as you'd see in autocomplete. (ie. "changelevel fullmapnamehere"),
// so skip ahead to start of map path/name
// Like the engine, we're only going to deal with the first match.
strncopy(outFullname, &results[0][helperCmdLen + 1], size);
return true;
}
#endif
bool CHalfLife2::IsMapValid(const char *map)
{
if (!map || !map[0])
return false;
bool ret = engine->IsMapValid(map);
#if SOURCE_ENGINE >= SE_LEFT4DEAD
if (!ret)
{
static char szFuzzyName[PLATFORM_MAX_PATH];
if (ResolveFuzzyMapName(map, szFuzzyName, sizeof(szFuzzyName)))
{
ret = engine->IsMapValid(szFuzzyName);
}
}
#endif
return ret;
}
+2 -41
View File
@@ -43,11 +43,6 @@
#include <KeyValues.h> #include <KeyValues.h>
#include <server_class.h> #include <server_class.h>
#include <datamap.h> #include <datamap.h>
#include <ihandleentity.h>
#include <tier0/icommandline.h>
#if SOURCE_ENGINE >= SE_PORTAL2
#include <string_t.h>
#endif
class CCommand; class CCommand;
@@ -91,20 +86,6 @@ struct DelayedKickInfo
char buffer[384]; char buffer[384];
}; };
// copy from game/shared/entitylist_base.h
class CEntInfo
{
public:
IHandleEntity *m_pEntity;
int m_SerialNumber;
CEntInfo *m_pPrev;
CEntInfo *m_pNext;
#if SOURCE_ENGINE >= SE_PORTAL2
string_t m_iName;
string_t m_iClassName;
#endif
};
class CHalfLife2 : class CHalfLife2 :
public SMGlobalClass, public SMGlobalClass,
public IGameHelpers public IGameHelpers
@@ -115,7 +96,6 @@ public:
public: public:
void OnSourceModStartup(bool late); void OnSourceModStartup(bool late);
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModAllInitialized_Post();
/*void OnSourceModAllShutdown();*/ /*void OnSourceModAllShutdown();*/
public: //IGameHelpers public: //IGameHelpers
SendProp *FindInSendTable(const char *classname, const char *offset); SendProp *FindInSendTable(const char *classname, const char *offset);
@@ -123,11 +103,9 @@ public: //IGameHelpers
datamap_t *GetDataMap(CBaseEntity *pEntity); datamap_t *GetDataMap(CBaseEntity *pEntity);
ServerClass *FindServerClass(const char *classname); ServerClass *FindServerClass(const char *classname);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset); typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested);
void SetEdictStateChanged(edict_t *pEdict, unsigned short offset); void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
bool TextMsg(int client, int dest, const char *msg); bool TextMsg(int client, int dest, const char *msg);
bool HintTextMsg(int client, const char *msg); bool HintTextMsg(int client, const char *msg);
bool HintTextMsg(cell_t *players, int count, const char *msg);
bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show); bool ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show);
bool IsLANServer(); bool IsLANServer();
bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL); bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL);
@@ -137,19 +115,6 @@ public: //IGameHelpers
void SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt); void SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt);
const char *GetCurrentMap(); const char *GetCurrentMap();
void ServerCommand(const char *buffer); void ServerCommand(const char *buffer);
CBaseEntity *ReferenceToEntity(cell_t entRef);
cell_t EntityToReference(CBaseEntity *pEntity);
cell_t IndexToReference(int entIndex);
int ReferenceToIndex(cell_t entRef);
cell_t ReferenceToBCompatRef(cell_t entRef);
CEntInfo *LookupEntity(int entIndex);
cell_t EntityToBCompatRef(CBaseEntity *pEntity);
void *GetGlobalEntityList();
int GetSendPropOffset(SendProp *prop);
ICommandLine *GetValveCommandLine();
const char *GetEntityClassname(edict_t *pEdict);
const char *GetEntityClassname(CBaseEntity *pEntity);
bool IsMapValid(const char *map);
public: public:
void AddToFakeCliCmdQueue(int client, int userid, const char *cmd); void AddToFakeCliCmdQueue(int client, int userid, const char *cmd);
void ProcessFakeCliCmdQueue(); void ProcessFakeCliCmdQueue();
@@ -160,14 +125,11 @@ public:
const char *CurrentCommandName(); const char *CurrentCommandName();
void AddDelayedKick(int client, int userid, const char *msg); void AddDelayedKick(int client, int userid, const char *msg);
void ProcessDelayedKicks(); void ProcessDelayedKicks();
#if !defined METAMOD_PLAPI_VERSION || PLAPI_VERSION < 11 #if !defined METAMOD_PLAPI_VERSION
bool IsOriginalEngine(); bool IsOriginalEngine();
#endif #endif
private: private:
DataTableInfo *_FindServerClass(const char *classname); DataTableInfo *_FindServerClass(const char *classname);
private:
void InitLogicalEntData();
void InitCommandLine();
private: private:
Trie *m_pClasses; Trie *m_pClasses;
List<DataTableInfo *> m_Tables; List<DataTableInfo *> m_Tables;
@@ -180,11 +142,10 @@ private:
CStack<DelayedFakeCliCmd *> m_FreeCmds; CStack<DelayedFakeCliCmd *> m_FreeCmds;
CStack<CachedCommandInfo> m_CommandStack; CStack<CachedCommandInfo> m_CommandStack;
Queue<DelayedKickInfo> m_DelayedKicks; Queue<DelayedKickInfo> m_DelayedKicks;
void *m_pGetCommandLine;
}; };
extern CHalfLife2 g_HL2; extern CHalfLife2 g_HL2;
bool IndexToAThings(cell_t, CBaseEntity **pEntData, edict_t **pEdictData); edict_t *GetEntity(cell_t num, CBaseEntity **pData);
#endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_ #endif //_INCLUDE_SOURCEMOD_CHALFLIFE2_H_
+41 -91
View File
@@ -579,7 +579,6 @@ HandleError HandleSystem::CloneHandle(QHandle *pHandle, unsigned int index, Hand
} }
pNewHandle->clone = index; pNewHandle->clone = index;
pNewHandle->object = NULL;
pHandle->refcount++; pHandle->refcount++;
*newhandle = new_handle; *newhandle = new_handle;
@@ -621,53 +620,8 @@ HandleError HandleSystem::CloneHandle(Handle_t handle, Handle_t *newhandle, Iden
return CloneHandle(pHandle, index, newhandle, newOwner); return CloneHandle(pHandle, index, newhandle, newOwner);
} }
Handle_t HandleSystem::FastCloneHandle(QHandle *pHandle, unsigned int index)
{
if (pHandle->clone)
return FastCloneHandle(&m_Handles[pHandle->clone], pHandle->clone);
Handle_t hndl;
if (CloneHandle(pHandle, index, &hndl, g_pCoreIdent) != HandleError_None)
return BAD_HANDLE;
return hndl;
}
Handle_t HandleSystem::FastCloneHandle(Handle_t hndl)
{
QHandle *pHandle;
unsigned int index;
GetHandleUnchecked(hndl, pHandle, index);
return FastCloneHandle(pHandle, index);
}
void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index)
{
#ifndef NDEBUG
unsigned int serial = (hndl >> 16);
#endif
index = (hndl & HANDLESYS_HANDLE_MASK);
assert(index != 0 && index <= m_HandleTail && index < HANDLESYS_MAX_HANDLES);
pHandle = &m_Handles[index];
assert(pHandle->set && pHandle->set != HandleSet_Freed);
assert(pHandle->serial == serial);
}
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
{ {
if (pHandle->is_destroying)
{
/* Someone tried to free this recursively.
* We'll just ignore this safely.
*/
return HandleError_None;
}
QHandleType *pType = &m_Types[pHandle->type]; QHandleType *pType = &m_Types[pHandle->type];
if (pHandle->clone) if (pHandle->clone)
@@ -682,7 +636,6 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
pMaster = &m_Handles[master]; pMaster = &m_Handles[master];
/* Release the clone now */ /* Release the clone now */
pHandle->is_destroying = true;
ReleasePrimHandle(index); ReleasePrimHandle(index);
/* Decrement the master's reference count */ /* Decrement the master's reference count */
@@ -691,27 +644,20 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
/* Type should be the same but do this anyway... */ /* Type should be the same but do this anyway... */
pType = &m_Types[pMaster->type]; pType = &m_Types[pMaster->type];
pMaster->is_destroying = true; pMaster->is_destroying = true;
if (pMaster->object) pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
{
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
}
ReleasePrimHandle(master); ReleasePrimHandle(master);
} }
} else if (pHandle->set == HandleSet_Identity) { } else if (pHandle->set == HandleSet_Identity) {
/* If we're an identity, skip all this stuff! /* If we're an identity, skip all this stuff!
* NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR * NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
*/ */
pHandle->is_destroying = true;
ReleasePrimHandle(index); ReleasePrimHandle(index);
} else { } else {
/* Decrement, free if necessary */ /* Decrement, free if necessary */
if (--pHandle->refcount == 0) if (--pHandle->refcount == 0)
{ {
pHandle->is_destroying = true; pHandle->is_destroying = true;
if (pHandle->object) pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
{
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
}
ReleasePrimHandle(index); ReleasePrimHandle(index);
} else { } else {
/* We must be cloned, so mark ourselves as freed */ /* We must be cloned, so mark ourselves as freed */
@@ -744,6 +690,14 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSec
return HandleError_Access; return HandleError_Access;
} }
if (pHandle->is_destroying)
{
/* Someone tried to free this recursively.
* We'll just ignore this safely.
*/
return HandleError_None;
}
return FreeHandle(pHandle, index); return FreeHandle(pHandle, index);
} }
@@ -802,9 +756,6 @@ void HandleSystem::UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index)
assert(pHandle->owner == 0); assert(pHandle->owner == 0);
return; return;
} }
pHandle->owner = NULL;
/* Note that since 0 is an invalid handle, if any of these links are 0, /* Note that since 0 is an invalid handle, if any of these links are 0,
* the data can still be set. * the data can still be set.
*/ */
@@ -929,9 +880,29 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
{ {
continue; continue;
} }
if (pHandle->clone)
FreeHandle(pHandle, i); {
/* Get parent */
QHandle *pOther = &m_Handles[pHandle->clone];
if (--pOther->refcount == 0)
{
/* Free! */
dispatch->OnHandleDestroy(type, pOther->object);
ReleasePrimHandle(pHandle->clone);
}
/* Unlink ourselves since we don't have a reference count */
ReleasePrimHandle(i);
} else {
/* If it's not a clone, we still have to check the reference count.
* Either way, we'll be destroyed eventually because the handle types do not change.
*/
if (--pHandle->refcount == 0)
{
/* Free! */
dispatch->OnHandleDestroy(type, pHandle->object);
ReleasePrimHandle(i);
}
}
if (pType->opened == 0) if (pType->opened == 0)
{ {
break; break;
@@ -979,17 +950,14 @@ bool HandleSystem::InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHa
return true; return true;
} }
#define HANDLE_LOG_VERY_BAD(message, ...) \
g_Logger.LogFatal(message, ##__VA_ARGS__); \
g_Logger.LogError(message, ##__VA_ARGS__);
bool HandleSystem::TryAndFreeSomeHandles() bool HandleSystem::TryAndFreeSomeHandles()
{ {
IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
IPlugin *highest_owner = NULL; IPlugin *highest_owner = NULL;
unsigned int highest_handle_count = 0; unsigned int highest_handle_count = 0;
/* Search all plugins */ /* Search all plugins */
for (IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator(); pl_iter->MorePlugins(); pl_iter->NextPlugin()) while (pl_iter->MorePlugins())
{ {
IPlugin *plugin = pl_iter->GetPlugin(); IPlugin *plugin = pl_iter->GetPlugin();
IdentityToken_t *identity = plugin->GetIdentity(); IdentityToken_t *identity = plugin->GetIdentity();
@@ -1018,6 +986,8 @@ bool HandleSystem::TryAndFreeSomeHandles()
highest_owner = plugin; highest_owner = plugin;
highest_handle_count = handle_count; highest_handle_count = handle_count;
} }
pl_iter->NextPlugin();
} }
if (highest_owner == NULL || highest_handle_count == 0) if (highest_owner == NULL || highest_handle_count == 0)
@@ -1025,9 +995,9 @@ bool HandleSystem::TryAndFreeSomeHandles()
return false; return false;
} }
HANDLE_LOG_VERY_BAD("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename()); g_Logger.LogFatal("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
HANDLE_LOG_VERY_BAD("[SM] Unloading plugin to free %d handles.", highest_handle_count); g_Logger.LogFatal("[SM] Unloading plugin to free %d handles.", highest_handle_count);
HANDLE_LOG_VERY_BAD("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count); g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak"); highest_owner->GetBaseContext()->ThrowNativeErrorEx(SP_ERROR_MEMACCESS, "Memory leak");
@@ -1084,32 +1054,12 @@ void HandleSystem::Dump(HANDLE_REPORTER rep)
const char *type = "ANON"; const char *type = "ANON";
QHandleType *pType = &m_Types[m_Handles[i].type]; QHandleType *pType = &m_Types[m_Handles[i].type];
unsigned int size = 0; unsigned int size = 0;
unsigned int parentIdx;
bool bresult;
if (pType->nameIdx != -1) if (pType->nameIdx != -1)
{ {
type = m_strtab->GetString(pType->nameIdx); type = m_strtab->GetString(pType->nameIdx);
} }
if ((parentIdx = m_Handles[i].clone) != 0)
{
if (m_Handles[parentIdx].refcount > 0)
{
size = 0;
bresult = true;
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[parentIdx].type, m_Handles[parentIdx].object, &size);
}
}
else
{
bresult = pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size);
}
if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION if (pType->dispatch->GetDispatchVersion() < HANDLESYS_MEMUSAGE_MIN_VERSION
|| !bresult) || !pType->dispatch->GetHandleApproxSize(m_Handles[i].type, m_Handles[i].object, &size))
{ {
rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1"); rep("0x%08x\t%-20.20s\t%-20.20s\t%-10.10s", index, owner, type, "-1");
} }
-29
View File
@@ -160,9 +160,6 @@ public: //IHandleSystem
HandleError *err); HandleError *err);
void Dump(HANDLE_REPORTER rep); void Dump(HANDLE_REPORTER rep);
/* Bypasses security checks. */
Handle_t FastCloneHandle(Handle_t hndl);
protected: protected:
/** /**
* Decodes a handle with sanity and security checking. * Decodes a handle with sanity and security checking.
@@ -173,9 +170,6 @@ protected:
unsigned int *index, unsigned int *index,
bool ignoreFree=false); bool ignoreFree=false);
Handle_t FastCloneHandle(QHandle *pHandle, unsigned int index);
void GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigned int &index);
/** /**
* Creates a basic handle and sets its reference count to 1. * Creates a basic handle and sets its reference count to 1.
* Does not do any type or security checking. * Does not do any type or security checking.
@@ -228,27 +222,4 @@ private:
extern HandleSystem g_HandleSys; extern HandleSystem g_HandleSys;
struct AutoHandleRooter
{
public:
AutoHandleRooter(Handle_t hndl)
{
if (hndl != BAD_HANDLE)
this->hndl = g_HandleSys.FastCloneHandle(hndl);
else
this->hndl = BAD_HANDLE;
}
~AutoHandleRooter()
{
if (hndl != BAD_HANDLE)
{
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
g_HandleSys.FreeHandle(hndl, &sec);
}
}
private:
Handle_t hndl;
};
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_ #endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
+2 -2
View File
@@ -241,7 +241,7 @@ bool LibrarySystem::IsPathDirectory(const char *path)
return true; return true;
} }
#elif defined PLATFORM_POSIX #elif defined PLATFORM_LINUX
struct stat s; struct stat s;
if (stat(path, &s) != 0) if (stat(path, &s) != 0)
@@ -410,7 +410,7 @@ size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char
size_t length = strlen(path); size_t length = strlen(path);
for (size_t i = length - 1; for (size_t i = length - 1;
i <= length - 1; i >= 0 && i <= length - 1;
i--) i--)
{ {
if (path[i] == '/' if (path[i] == '/'
+9 -20
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -36,7 +36,7 @@
#include "Logger.h" #include "Logger.h"
#include "LibrarySys.h" #include "LibrarySys.h"
#include "TimerSys.h" #include "TimerSys.h"
#include <sourcemod_version.h> #include "sm_version.h"
Logger g_Logger; Logger g_Logger;
@@ -149,7 +149,7 @@ void Logger::_NewMapFile()
} else { } else {
char date[32]; char date[32];
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); 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, SOURCEMOD_VERSION); 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); fclose(fp);
} }
} }
@@ -265,8 +265,6 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
return; return;
} }
static ConVar *sv_logecho = icvar->FindVar("sv_logecho");
char buffer[3072]; char buffer[3072];
UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap);
@@ -277,11 +275,7 @@ void Logger::LogToOpenFileEx(FILE *fp, const char *msg, va_list ap)
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
fprintf(fp, "L %s: %s\n", date, buffer); fprintf(fp, "L %s: %s\n", date, buffer);
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
if (!sv_logecho || sv_logecho->GetBool())
{
g_SMAPI->ConPrintf("L %s: %s\n", date, buffer);
}
} }
void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap) void Logger::LogToFileOnlyEx(FILE *fp, const char *msg, va_list ap)
@@ -362,7 +356,7 @@ void Logger::LogMessage(const char *vafmt, ...)
char date[32]; char date[32];
m_DailyPrintHdr = false; m_DailyPrintHdr = false;
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); 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, SOURCEMOD_VERSION); 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_list ap;
va_start(ap, vafmt); va_start(ap, vafmt);
@@ -384,14 +378,6 @@ print_error:
} }
void Logger::LogError(const char *vafmt, ...) void Logger::LogError(const char *vafmt, ...)
{
va_list ap;
va_start(ap, vafmt);
LogErrorEx(vafmt, ap);
va_end(ap);
}
void Logger::LogErrorEx(const char *vafmt, va_list ap)
{ {
if (!m_Active) if (!m_Active)
{ {
@@ -422,7 +408,10 @@ void Logger::LogErrorEx(const char *vafmt, va_list ap)
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); 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; m_ErrMapStart = true;
} }
va_list ap;
va_start(ap, vafmt);
LogToOpenFileEx(fp, vafmt, ap); LogToOpenFileEx(fp, vafmt, ap);
va_end(ap);
fclose(fp); fclose(fp);
} }
else else
-1
View File
@@ -75,7 +75,6 @@ public:
void DisableLogging(); void DisableLogging();
void LogMessage(const char *msg, ...); void LogMessage(const char *msg, ...);
void LogError(const char *msg, ...); void LogError(const char *msg, ...);
void LogErrorEx(const char *msg, va_list ap);
void LogFatal(const char *msg, ...); void LogFatal(const char *msg, ...);
void LogToOpenFile(FILE *fp, const char *msg, ...); void LogToOpenFile(FILE *fp, const char *msg, ...);
void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap); void LogToOpenFileEx(FILE *fp, const char *msg, va_list ap);
+48 -101
View File
@@ -2,33 +2,32 @@
# Makefile written by David "BAILOPAN" Anderson # Makefile written by David "BAILOPAN" Anderson
SMSDK = .. SMSDK = ..
SRCDS_BASE = ~/srcds
HL2SDK_ORIG = ../../hl2sdk HL2SDK_ORIG = ../../hl2sdk
HL2SDK_OB = ../../hl2sdk-ob HL2SDK_OB = ../../hl2sdk-ob
HL2SDK_CSS = ../../hl2sdk-css
HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve
HL2SDK_L4D = ../../hl2sdk-l4d HL2SDK_L4D = ../../hl2sdk-l4d
HL2SDK_L4D2 = ../../hl2sdk-l4d2 MMSOURCE17 = ../../mmsource-1.7
HL2SDK_CSGO = ../../hl2sdk-csgo
MMSOURCE = ../../mmsource-central
##################################### #####################################
### EDIT BELOW FOR OTHER PROJECTS ### ### EDIT BELOW FOR OTHER PROJECTS ###
##################################### #####################################
OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \ OBJECTS = AdminCache.cpp CDataPack.cpp ConCmdManager.cpp ConVarManager.cpp CoreConfig.cpp \
Database.cpp DebugReporter.cpp EventManager.cpp HalfLife2.cpp Logger.cpp \ Database.cpp DebugReporter.cpp EventManager.cpp GameConfigs.cpp HalfLife2.cpp Logger.cpp \
PlayerManager.cpp TimerSys.cpp UserMessages.cpp \ MemoryUtils.cpp PlayerManager.cpp TextParsers.cpp TimerSys.cpp Translator.cpp UserMessages.cpp \
sm_autonatives.cpp sm_srvcmds.cpp sm_stringutil.cpp sm_trie.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 \ sourcemm_api.cpp sourcemod.cpp MenuStyle_Base.cpp MenuStyle_Valve.cpp MenuManager.cpp \
MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp \ MenuStyle_Radio.cpp ChatTriggers.cpp ADTFactory.cpp MenuVoting.cpp sm_crc32.cpp \
frame_hooks.cpp concmd_cleaner.cpp NextMap.cpp \ frame_hooks.cpp concmd_cleaner.cpp Profiler.cpp PhraseCollection.cpp NextMap.cpp \
NativeOwner.cpp logic_bridge.cpp ConsoleDetours.cpp NativeOwner.cpp
OBJECTS += smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \ OBJECTS += smn_admin.cpp smn_bitbuffer.cpp smn_console.cpp smn_core.cpp \
smn_database.cpp smn_entities.cpp smn_events.cpp \ smn_datapacks.cpp smn_entities.cpp smn_events.cpp smn_fakenatives.cpp \
smn_fakenatives.cpp smn_filesystem.cpp smn_halflife.cpp \ smn_filesystem.cpp smn_float.cpp smn_functions.cpp smn_gameconfigs.cpp smn_halflife.cpp \
smn_keyvalues.cpp smn_player.cpp \ smn_handles.cpp smn_keyvalues.cpp smn_banning.cpp smn_maplists.cpp \
smn_usermsgs.cpp smn_menus.cpp smn_vector.cpp \ smn_lang.cpp smn_player.cpp smn_string.cpp smn_sorting.cpp smn_textparse.cpp smn_timers.cpp \
smn_hudtext.cpp smn_nextmap.cpp smn_usermsgs.cpp smn_menus.cpp smn_database.cpp smn_vector.cpp smn_adt_array.cpp \
smn_adt_trie.cpp smn_hudtext.cpp smn_adt_stack.cpp smn_nextmap.cpp
OBJECTS += ExtensionSys.cpp \ OBJECTS += ExtensionSys.cpp \
ForwardSys.cpp \ ForwardSys.cpp \
HandleSys.cpp \ HandleSys.cpp \
@@ -37,6 +36,7 @@ OBJECTS += ExtensionSys.cpp \
PluginSys.cpp \ PluginSys.cpp \
ShareSys.cpp \ ShareSys.cpp \
NativeInvoker.cpp NativeInvoker.cpp
OBJECTS += thread/ThreadWorker.cpp thread/BaseWorker.cpp thread/PosixThreads.cpp ThreadSupport.cpp
############################################## ##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
@@ -49,119 +49,64 @@ CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc CPP = gcc
override ENGSET = false override ENGSET = false
ifneq (,$(filter original orangebox css orangeboxvalve left4dead left4dead2 csgo,$(ENGINE)))
override ENGSET = true
endif
ifeq "$(ENGINE)" "original" ifeq "$(ENGINE)" "original"
HL2SDK = $(HL2SDK_ORIG) HL2SDK = $(HL2SDK_ORIG)
HL2PUB = $(HL2SDK)/public
HL2LIB = $(HL2SDK)/linux_sdk HL2LIB = $(HL2SDK)/linux_sdk
CFLAGS += -DSOURCE_ENGINE=1 CFLAGS += -DSOURCE_ENGINE=1
METAMOD = $(MMSOURCE)/core-legacy METAMOD = $(MMSOURCE17)/core-legacy
INCLUDE += -I$(HL2SDK)/public/dlls INCLUDE += -I$(HL2SDK)/public/dlls
SRCDS = $(SRCDS_BASE)
BINARY = sourcemod.1.ep1.so BINARY = sourcemod.1.ep1.so
override ENGSET = true
endif endif
ifeq "$(ENGINE)" "orangebox" ifeq "$(ENGINE)" "orangebox"
HL2SDK = $(HL2SDK_OB) HL2SDK = $(HL2SDK_OB)
HL2PUB = $(HL2SDK)/public
HL2LIB = $(HL2SDK)/lib/linux HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=3 CFLAGS += -DSOURCE_ENGINE=3
METAMOD = $(MMSOURCE)/core METAMOD = $(MMSOURCE17)/core
INCLUDE += -I$(HL2SDK)/public/game/server INCLUDE += -I$(HL2SDK)/public/game/server
SRCDS = $(SRCDS_BASE)/orangebox
BINARY = sourcemod.2.ep2.so BINARY = sourcemod.2.ep2.so
endif override ENGSET = true
ifeq "$(ENGINE)" "css"
HL2SDK = $(HL2SDK_CSS)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=6
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.css.so
endif endif
ifeq "$(ENGINE)" "orangeboxvalve" ifeq "$(ENGINE)" "orangeboxvalve"
HL2SDK = $(HL2SDK_OB_VALVE) HL2SDK = $(HL2SDK_OB_VALVE)
HL2PUB = $(HL2SDK)/public
HL2LIB = $(HL2SDK)/lib/linux HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=7 CFLAGS += -DSOURCE_ENGINE=4
METAMOD = $(MMSOURCE)/core METAMOD = $(MMSOURCE17)/core
INCLUDE += -I$(HL2SDK)/public/game/server INCLUDE += -I$(HL2SDK)/public/game/server
SRCDS = $(SRCDS_BASE)/orangebox
BINARY = sourcemod.2.ep2v.so BINARY = sourcemod.2.ep2v.so
override ENGSET = true
endif endif
ifeq "$(ENGINE)" "left4dead" ifeq "$(ENGINE)" "left4dead"
HL2SDK = $(HL2SDK_L4D) HL2SDK = $(HL2SDK_L4D)
HL2PUB = $(HL2SDK)/public
HL2LIB = $(HL2SDK)/lib/linux HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=8 CFLAGS += -DSOURCE_ENGINE=5
METAMOD = $(MMSOURCE)/core METAMOD = $(MMSOURCE17)/core
INCLUDE += -I$(HL2SDK)/public/game/server INCLUDE += -I$(HL2SDK)/public/game/server
SRCDS = $(SRCDS_BASE)/l4d
BINARY = sourcemod.2.l4d.so BINARY = sourcemod.2.l4d.so
endif override ENGSET = true
ifeq "$(ENGINE)" "left4dead2"
HL2SDK = $(HL2SDK_L4D2)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=9
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.l4d2.so
endif
ifeq "$(ENGINE)" "csgo"
HL2SDK = $(HL2SDK_CSGO)
HL2LIB = $(HL2SDK)/lib/linux
CFLAGS += -DSOURCE_ENGINE=12
METAMOD = $(MMSOURCE)/core
INCLUDE += -I$(HL2SDK)/public/game/server
BINARY = sourcemod.2.csgo.so
endif endif
HL2PUB = $(HL2SDK)/public CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_ORANGEBOXVALVE=4 -DSE_LEFT4DEAD=5
OS := $(shell uname -s) LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so \
tier0_i486.so -lpthread -static-libgcc
ifeq "$(OS)" "Darwin"
LIB_EXT = dylib
HL2LIB = $(HL2SDK)/lib/mac
else
LIB_EXT = so
ifeq "$(ENGINE)" "original"
HL2LIB = $(HL2SDK)/linux_sdk
else
HL2LIB = $(HL2SDK)/lib/linux
endif
endif
ifneq (,$(filter original orangebox left4dead,$(ENGINE)))
LIB_SUFFIX = _i486.$(LIB_EXT)
else
LIB_PREFIX = lib
ifneq (,$(filter orangeboxvalve css,$(ENGINE)))
ifneq "$(OS)" "Darwin"
LIB_SUFFIX = _srv.$(LIB_EXT)
else
LIB_SUFFIX = .$(LIB_EXT)
endif
else
LIB_SUFFIX = .$(LIB_EXT)
endif
endif
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \
-DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \
-DSE_PORTAL2=11 -DSE_CSGO=12
LINK += $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) \
$(LIB_PREFIX)tier0$(LIB_SUFFIX) -static-libgcc
ifeq "$(ENGINE)" "csgo"
LINK += $(HL2LIB)/interfaces_i486.a
endif
INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \ INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \
-I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \ -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) -I$(METAMOD)/sourcehook \
-I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
CFLAGS += -D_LINUX -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \ CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \ -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
-Wno-uninitialized -Wno-unused -Wno-switch -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H \ -Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32
-DSM_DEFAULT_THREADER -m32 -DCOMPILER_GCC CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
CPPFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -fno-threadsafe-statics -fno-exceptions -fno-rtti
################################################ ################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### ### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
@@ -191,15 +136,15 @@ $(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all: check all: check
mkdir -p $(BIN_DIR) mkdir -p $(BIN_DIR)/systems
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX) mkdir -p $(BIN_DIR)/thread
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX) ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so;
ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so;
$(MAKE) -f Makefile sourcemod $(MAKE) -f Makefile sourcemod
check: check:
if [ "$(ENGSET)" = "false" ]; then \ if [ "$(ENGSET)" = "false" ]; then \
echo "You must supply one of the following values for ENGINE:"; \ echo "You must supply ENGINE=left4dead or ENGINE=orangebox or ENGINE=original"; \
echo "csgo, left4dead2, left4dead, orangeboxvalve, css, orangebox, or original"; \
exit 1; \ exit 1; \
fi fi
@@ -213,4 +158,6 @@ default: all
clean: check clean: check
rm -rf $(BIN_DIR)/*.o rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/systems/*.o
rm -rf $(BIN_DIR)/thread/*.o
rm -rf $(BIN_DIR)/$(BINARY) rm -rf $(BIN_DIR)/$(BINARY)
+220
View File
@@ -0,0 +1,220 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 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,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -25,64 +25,34 @@
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ #ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_ #define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
#include "common_logic.h"
#include <IMemoryUtils.h> #include <IMemoryUtils.h>
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE #include "sm_globals.h"
#include <sh_vector.h>
#include "sm_symtable.h"
using namespace SourceHook;
#endif
using namespace SourceMod; using namespace SourceMod;
#ifdef PLATFORM_APPLE
#include <CoreServices/CoreServices.h>
#endif
struct DynLibInfo struct DynLibInfo
{ {
void *baseAddress; void *baseAddress;
size_t memorySize; size_t memorySize;
}; };
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
struct LibSymbolTable
{
SymbolTable table;
uintptr_t lib_base;
uint32_t last_pos;
};
#endif
class MemoryUtils : class MemoryUtils :
public IMemoryUtils, public IMemoryUtils,
public SMGlobalClass public SMGlobalClass
{ {
public:
MemoryUtils();
~MemoryUtils();
public: // SMGlobalClass public: // SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
public: // IMemoryUtils public: // IMemoryUtils
void *FindPattern(const void *libPtr, const char *pattern, size_t len); void *FindPattern(const void *libPtr, const char *pattern, size_t len);
void *ResolveSymbol(void *handle, const char *symbol);
public:
bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
private: private:
CVector<LibSymbolTable *> m_SymTables; bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
#ifdef PLATFORM_APPLE
struct dyld_all_image_infos *m_ImageList;
SInt32 m_OSXMajor;
SInt32 m_OSXMinor;
#endif
#endif
}; };
extern MemoryUtils g_MemUtils; extern MemoryUtils g_MemUtils;
+5 -25
View File
@@ -41,7 +41,7 @@
#include "ShareSys.h" #include "ShareSys.h"
#include "HandleSys.h" #include "HandleSys.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "logic_bridge.h" #include "Translator.h"
MenuManager g_Menus; MenuManager g_Menus;
VoteMenuHandler s_VoteHandler; VoteMenuHandler s_VoteHandler;
@@ -231,7 +231,6 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
unsigned int pgn = menu->GetPagination(); unsigned int pgn = menu->GetPagination();
unsigned int maxItems = style->GetMaxPageItems(); unsigned int maxItems = style->GetMaxPageItems();
bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT; bool exitButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_EXIT) == MENUFLAG_BUTTON_EXIT;
bool novoteButton = (menu->GetMenuOptionFlags() & MENUFLAG_BUTTON_NOVOTE) == MENUFLAG_BUTTON_NOVOTE;
if (pgn != MENU_NO_PAGINATION) if (pgn != MENU_NO_PAGINATION)
{ {
@@ -242,11 +241,6 @@ IMenuPanel *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder ord
maxItems--; maxItems--;
} }
if (novoteButton)
{
maxItems--;
}
/* This is very not allowed! */ /* This is very not allowed! */
if (maxItems < 2) if (maxItems < 2)
{ {
@@ -442,20 +436,6 @@ skip_search:
/* Draw the item according to the order */ /* Draw the item according to the order */
menu_slots_t *slots = md.slots; menu_slots_t *slots = md.slots;
unsigned int position = 0; /* Keep track of the last position */ unsigned int position = 0; /* Keep track of the last position */
if (novoteButton)
{
char text[50];
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "No Vote", &client))
{
UTIL_Format(text, sizeof(text), "No Vote");
}
ItemDrawInfo dr(text, 0);
position = panel->DrawItem(dr);
slots[position].type = ItemSel_Exit;
position++;
}
if (order == ItemOrder_Ascending) if (order == ItemOrder_Ascending)
{ {
md.item_on_page = drawItems[0].position; md.item_on_page = drawItems[0].position;
@@ -606,7 +586,7 @@ skip_search:
{ {
if (exitBackButton) if (exitBackButton)
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client)) if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
{ {
UTIL_Format(text, sizeof(text), "Back"); UTIL_Format(text, sizeof(text), "Back");
} }
@@ -616,7 +596,7 @@ skip_search:
} }
else else
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client)) if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
{ {
UTIL_Format(text, sizeof(text), "Previous"); UTIL_Format(text, sizeof(text), "Previous");
} }
@@ -637,7 +617,7 @@ skip_search:
/* NEXT */ /* NEXT */
if (displayNext || canDrawDisabled) if (displayNext || canDrawDisabled)
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client)) if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
{ {
UTIL_Format(text, sizeof(text), "Next"); UTIL_Format(text, sizeof(text), "Next");
} }
@@ -668,7 +648,7 @@ skip_search:
/* EXIT */ /* EXIT */
if (exitButton) if (exitButton)
{ {
if (!logicore.CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client)) if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
{ {
UTIL_Format(text, sizeof(text), "Exit"); UTIL_Format(text, sizeof(text), "Exit");
} }
+1 -13
View File
@@ -322,24 +322,15 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
if (pCollideable) if (pCollideable)
{ {
const Vector & pos = pCollideable->GetCollisionOrigin(); const Vector & pos = pCollideable->GetCollisionOrigin();
enginesound->EmitSound(filter, enginesound->EmitSound(filter,
client, client,
CHAN_AUTO, CHAN_AUTO,
#if SOURCE_ENGINE >= SE_PORTAL2
sound,
-1,
#endif
sound, sound,
VOL_NORM, VOL_NORM,
ATTN_NORM, ATTN_NORM,
#if SOURCE_ENGINE >= SE_PORTAL2
0,
#endif
0, 0,
PITCH_NORM, PITCH_NORM,
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2
0,
#endif
&pos); &pos);
} }
} }
@@ -386,9 +377,6 @@ void BaseMenuStyle::ClientPressedKey(int client, unsigned int key_press)
RemoveClientFromWatch(client); RemoveClientFromWatch(client);
} }
Handle_t hndl = menu ? menu->GetHandle() : BAD_HANDLE;
AutoHandleRooter ahr(hndl);
if (cancel) if (cancel)
{ {
mh->OnMenuCancel(menu, client, reason); mh->OnMenuCancel(menu, client, reason);
+5 -66
View File
@@ -32,20 +32,11 @@
#include "MenuStyle_Radio.h" #include "MenuStyle_Radio.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "UserMessages.h" #include "UserMessages.h"
#include <IGameConfigs.h> #include "GameConfigs.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#if defined MENU_DEBUG #if defined MENU_DEBUG
#include "Logger.h" #include "Logger.h"
#endif #endif
#include "logic_bridge.h"
#ifdef USE_PROTOBUF_USERMESSAGES
#include <google/protobuf/descriptor.h>
#endif
#if SOURCE_ENGINE == SE_CSGO
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
#endif
extern const char *g_RadioNumTable[]; extern const char *g_RadioNumTable[];
CRadioStyle g_RadioMenuStyle; CRadioStyle g_RadioMenuStyle;
@@ -53,14 +44,6 @@ int g_ShowMenuId = -1;
bool g_bRadioInit = false; bool g_bRadioInit = false;
unsigned int g_RadioMenuTimeout = 0; unsigned int g_RadioMenuTimeout = 0;
// back, next, exit
#define MAX_PAGINATION_OPTIONS 3
#define MAX_MENUSLOT_KEYS 10
static unsigned int s_RadioMaxPageItems = MAX_MENUSLOT_KEYS;
CRadioStyle::CRadioStyle() CRadioStyle::CRadioStyle()
{ {
m_players = new CRadioMenuPlayer[256+1]; m_players = new CRadioMenuPlayer[256+1];
@@ -106,18 +89,6 @@ void CRadioStyle::OnSourceModLevelChange(const char *mapName)
g_RadioMenuTimeout = 0; g_RadioMenuTimeout = 0;
} }
const char *items = g_pGameConf->GetKeyValue("RadioMenuMaxPageItems");
if (items != NULL)
{
int value = atoi(items);
// Only override the mostly-safe default if it's a sane value
if (value > MAX_PAGINATION_OPTIONS && value <= MAX_MENUSLOT_KEYS)
{
s_RadioMaxPageItems = value;
}
}
g_Menus.AddStyle(this); g_Menus.AddStyle(this);
g_Menus.SetDefaultStyle(this); g_Menus.SetDefaultStyle(this);
@@ -163,22 +134,13 @@ static unsigned int g_last_holdtime = 0;
static unsigned int g_last_client_count = 0; static unsigned int g_last_client_count = 0;
static int g_last_clients[256]; static int g_last_clients[256];
#ifdef USE_PROTOBUF_USERMESSAGES
void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
#else
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter) void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
#endif
{ {
int count = pFilter->GetRecipientCount(); int count = pFilter->GetRecipientCount();
#ifdef USE_PROTOBUF_USERMESSAGES
int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
#else
bf_read br(bf->GetBasePointer(), 3); bf_read br(bf->GetBasePointer(), 3);
br.ReadWord(); br.ReadWord();
int c = br.ReadChar(); int c = br.ReadChar();
#endif
g_last_holdtime = (c == -1) ? 0 : (unsigned)c; g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
@@ -226,7 +188,7 @@ IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwn
unsigned int CRadioStyle::GetMaxPageItems() unsigned int CRadioStyle::GetMaxPageItems()
{ {
return s_RadioMaxPageItems; return 10;
} }
const char *CRadioStyle::GetStyleName() const char *CRadioStyle::GetStyleName()
@@ -344,7 +306,7 @@ unsigned int CRadioDisplay::GetCurrentKey()
bool CRadioDisplay::SetCurrentKey(unsigned int key) bool CRadioDisplay::SetCurrentKey(unsigned int key)
{ {
if (key < m_NextPos || m_NextPos > s_RadioMaxPageItems) if (key < m_NextPos || m_NextPos > 10)
{ {
return false; return false;
} }
@@ -380,7 +342,7 @@ void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item) unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
{ {
if (m_NextPos > s_RadioMaxPageItems || !CanDrawItem(item.style)) if (m_NextPos > 10 || !CanDrawItem(item.style))
{ {
return 0; return 0;
} }
@@ -489,15 +451,6 @@ void CRadioMenuPlayer::Radio_Refresh()
time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime); time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
} }
#ifdef USE_PROTOBUF_USERMESSAGES
// If or when we need to support multiple games per engine with this, we can switch to reflection
// TODO: find what happens past 240 on CS:GO
CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
msg->set_bits_valid_slots(display_keys);
msg->set_display_time(time);
msg->set_menu_string(ptr);
g_UserMsgs.EndMessage();
#else
while (true) while (true)
{ {
if (len > 240) if (len > 240)
@@ -505,8 +458,7 @@ void CRadioMenuPlayer::Radio_Refresh()
save = ptr[240]; save = ptr[240];
ptr[240] = '\0'; ptr[240] = '\0';
} }
bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
buffer->WriteWord(display_keys); buffer->WriteWord(display_keys);
buffer->WriteChar(time ? time : -1); buffer->WriteChar(time ? time : -1);
buffer->WriteByte( (len > 240) ? 1 : 0 ); buffer->WriteByte( (len > 240) ? 1 : 0 );
@@ -523,7 +475,6 @@ void CRadioMenuPlayer::Radio_Refresh()
break; break;
} }
} }
#endif
display_last_refresh = gpGlobals->curtime; display_last_refresh = gpGlobals->curtime;
} }
@@ -559,7 +510,6 @@ unsigned int CRadioDisplay::GetApproxMemUsage()
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner) CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
{ {
m_Pagination = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
} }
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr) bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
@@ -600,17 +550,6 @@ bool CRadioMenu::DisplayAtItem(int client,
time); time);
} }
bool CRadioMenu::SetPagination(unsigned int itemsPerPage)
{
const unsigned int maxPerPage = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
if (itemsPerPage > maxPerPage)
{
return false;
}
return CBaseMenu::SetPagination(itemsPerPage);
}
void CRadioMenu::Cancel_Finally() void CRadioMenu::Cancel_Finally()
{ {
g_RadioMenuStyle.CancelMenu(this); g_RadioMenuStyle.CancelMenu(this);
+2 -11
View File
@@ -37,7 +37,7 @@
#include "MenuStyle_Base.h" #include "MenuStyle_Base.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include "UserMessages.h" #include <IUserMessages.h>
#include "sm_fastlink.h" #include "sm_fastlink.h"
#include <sh_stack.h> #include <sh_stack.h>
#include <compat_wrappers.h> #include <compat_wrappers.h>
@@ -65,11 +65,7 @@ private:
class CRadioStyle : class CRadioStyle :
public BaseMenuStyle, public BaseMenuStyle,
public SMGlobalClass, public SMGlobalClass,
#ifdef USE_PROTOBUF_USERMESSAGES public IUserMessageListener
public IProtobufUserMessageListener
#else
public IBitBufUserMessageListener
#endif
{ {
public: public:
CRadioStyle(); CRadioStyle();
@@ -88,11 +84,7 @@ public: //IMenuStyle
unsigned int GetMaxPageItems(); unsigned int GetMaxPageItems();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
public: //IUserMessageListener public: //IUserMessageListener
#ifdef USE_PROTOBUF_USERMESSAGES
void OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter);
#else
void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter); void OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter);
#endif
void OnUserMessageSent(int msg_id); void OnUserMessageSent(int msg_id);
public: public:
bool IsSupported(); bool IsSupported();
@@ -150,7 +142,6 @@ public:
unsigned int time, unsigned int time,
unsigned int start_item, unsigned int start_item,
IMenuHandler *alt_handler/* =NULL */); IMenuHandler *alt_handler/* =NULL */);
bool SetPagination(unsigned int itemsPerPage);
void Cancel_Finally(); void Cancel_Finally();
unsigned int GetApproxMemUsage(); unsigned int GetApproxMemUsage();
}; };
+1
View File
@@ -32,6 +32,7 @@
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "MenuStyle_Valve.h" #include "MenuStyle_Valve.h"
#include "Translator.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "ConCmdManager.h" #include "ConCmdManager.h"
+8 -205
View File
@@ -34,56 +34,9 @@
#include "MenuVoting.h" #include "MenuVoting.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include <sourcemod.h>
#include <Logger.h>
#include <HalfLife2.h>
#include <mathlib.h>
#include <const.h>
#include <ITranslator.h>
#include "logic_bridge.h"
float g_next_vote = 0.0f; float g_next_vote = 0.0f;
#define VOTE_NOT_VOTING -2
#define VOTE_PENDING -1
ConVar sm_vote_hintbox("sm_vote_progress_hintbox",
"0",
0,
"Show current vote progress in a hint box",
true,
0.0,
true,
1.0);
ConVar sm_vote_chat("sm_vote_progress_chat",
"0",
0,
"Show current vote progress as chat messages",
true,
0.0,
true,
1.0);
ConVar sm_vote_console("sm_vote_progress_console",
"0",
0,
"Show current vote progress as console messages",
true,
0.0,
true,
1.0);
ConVar sm_vote_client_console("sm_vote_progress_client_console",
"0",
0,
"Show current vote progress as console messages to clients",
true,
0.0,
true,
1.0);
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue); void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
#else #else
@@ -164,7 +117,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
* newly connected client is not allowed to vote. * newly connected client is not allowed to vote.
*/ */
int item; int item;
if ((item = m_ClientVotes[client]) >= VOTE_PENDING) if ((item = m_ClientVotes[client]) >= -1)
{ {
if (item >= 0) if (item >= 0)
{ {
@@ -172,7 +125,7 @@ void VoteMenuHandler::OnClientDisconnected(int client)
assert(m_Votes[item] > 0); assert(m_Votes[item] > 0);
m_Votes[item]--; m_Votes[item]--;
} }
m_ClientVotes[client] = VOTE_NOT_VOTING; m_ClientVotes[client] = -2;
} }
} }
@@ -236,13 +189,13 @@ bool VoteMenuHandler::IsClientInVotePool(int client)
return false; return false;
} }
return (m_ClientVotes[client] > VOTE_NOT_VOTING); return (m_ClientVotes[client] > -2);
} }
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem) bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
{ {
if (!IsClientInVotePool(client) if (!IsClientInVotePool(client)
|| m_ClientVotes[client] == VOTE_PENDING) || m_ClientVotes[client] == -1)
{ {
return false; return false;
} }
@@ -270,9 +223,7 @@ bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
assert((unsigned)m_ClientVotes[client] < m_Items); assert((unsigned)m_ClientVotes[client] < m_Items);
assert(m_Votes[m_ClientVotes[client]] > 0); assert(m_Votes[m_ClientVotes[client]] > 0);
m_Votes[m_ClientVotes[client]]--; m_Votes[m_ClientVotes[client]]--;
m_ClientVotes[client] = VOTE_PENDING; m_ClientVotes[client] = -1;
m_Revoting[client] = true;
m_NumVotes--;
} }
if (m_nMenuTime == MENU_TIME_FOREVER) if (m_nMenuTime == MENU_TIME_FOREVER)
@@ -308,8 +259,7 @@ bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
/* Mark all clients as not voting */ /* Mark all clients as not voting */
for (int i=1; i<=gpGlobals->maxClients; i++) for (int i=1; i<=gpGlobals->maxClients; i++)
{ {
m_ClientVotes[i] = VOTE_NOT_VOTING; m_ClientVotes[i] = -2;
m_Revoting[i] = false;
} }
m_Items = menu->GetItemCount(); m_Items = menu->GetItemCount();
@@ -353,8 +303,6 @@ void VoteMenuHandler::StartVoting()
m_pHandler->OnMenuVoteStart(m_pCurMenu); m_pHandler->OnMenuVoteStart(m_pCurMenu);
m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
/* By now we know how many clients were set. /* By now we know how many clients were set.
* If there are none, we should end IMMEDIATELY. * If there are none, we should end IMMEDIATELY.
*/ */
@@ -362,8 +310,6 @@ void VoteMenuHandler::StartVoting()
{ {
EndVoting(); EndVoting();
} }
m_TotalClients = m_Clients;
} }
void VoteMenuHandler::DecrementPlayerCount() void VoteMenuHandler::DecrementPlayerCount()
@@ -400,11 +346,6 @@ void VoteMenuHandler::EndVoting()
g_next_vote = gpGlobals->curtime + fVoteDelay; g_next_vote = gpGlobals->curtime + fVoteDelay;
} }
if (m_displayTimer)
{
g_Timers.KillTimer(m_displayTimer);
}
if (m_bCancelled) if (m_bCancelled)
{ {
/* If we were cancelled, don't bother tabulating anything. /* If we were cancelled, don't bother tabulating anything.
@@ -451,7 +392,7 @@ void VoteMenuHandler::EndVoting()
/* Build the client list */ /* Build the client list */
for (int i=1; i<=gpGlobals->maxClients; i++) for (int i=1; i<=gpGlobals->maxClients; i++)
{ {
if (m_ClientVotes[i] >= VOTE_PENDING) if (m_ClientVotes[i] >= -1)
{ {
client_vote[vote.num_clients].client = i; client_vote[vote.num_clients].client = i;
client_vote[vote.num_clients].item = m_ClientVotes[i]; client_vote[vote.num_clients].item = m_ClientVotes[i];
@@ -495,7 +436,7 @@ void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display) void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
{ {
m_ClientVotes[client] = VOTE_PENDING; m_ClientVotes[client] = -1;
m_pHandler->OnMenuDisplay(menu, client, display); m_pHandler->OnMenuDisplay(menu, client, display);
} }
@@ -517,58 +458,6 @@ void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int ite
m_ClientVotes[client] = item; m_ClientVotes[client] = item;
m_Votes[item]++; m_Votes[item]++;
m_NumVotes++; m_NumVotes++;
if (sm_vote_chat.GetBool() || sm_vote_console.GetBool() || sm_vote_client_console.GetBool())
{
static char buffer[1024];
ItemDrawInfo dr;
menu->GetItemInfo(item, &dr);
if (sm_vote_console.GetBool())
{
int target = SOURCEMOD_SERVER_LANGUAGE;
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
&target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
Engine_LogPrintWrapper(buffer);
}
if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
{
int maxclients = g_Players.GetMaxClients();
for (int i=1; i<=maxclients; i++)
{
CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
assert(pPlayer);
if (pPlayer->IsInGame() && !pPlayer->IsFakeClient())
{
if (m_Revoting[client])
{
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote",
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
}
else
{
logicore.CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For",
&i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
}
if (sm_vote_chat.GetBool())
{
g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
}
if (sm_vote_client_console.GetBool())
{
ClientConsolePrint(pPlayer->GetEdict(), buffer);
}
}
}
}
}
BuildVoteLeaders();
DrawHintProgress();
} }
m_pHandler->OnMenuSelect(menu, client, item); m_pHandler->OnMenuSelect(menu, client, item);
@@ -591,9 +480,6 @@ void VoteMenuHandler::InternalReset()
m_NumVotes = 0; m_NumVotes = 0;
m_bCancelled = false; m_bCancelled = false;
m_pHandler = NULL; m_pHandler = NULL;
m_leaderList[0] = '\0';
m_displayTimer = NULL;
m_TotalClients = 0;
} }
void VoteMenuHandler::CancelVoting() void VoteMenuHandler::CancelVoting()
@@ -616,86 +502,3 @@ bool VoteMenuHandler::IsCancelling()
return m_bCancelled; return m_bCancelled;
} }
void VoteMenuHandler::DrawHintProgress()
{
if (!sm_vote_hintbox.GetBool())
{
return;
}
static char buffer[1024];
float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
if (timeRemaining < 0)
{
timeRemaining = 0.0;
}
int iTimeRemaining = RoundFloatToInt(timeRemaining);
int maxclients = g_Players.GetMaxClients();
for (int i=1; i<=maxclients; i++)
{
if (g_Players.GetPlayerByIndex(i)->IsInGame())
{
logicore.CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count",
&i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
g_HL2.HintTextMsg(i, buffer);
}
}
}
void VoteMenuHandler::BuildVoteLeaders()
{
if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
{
return;
}
menu_vote_result_t vote;
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;
assert(vote.num_votes);
/* Sort the item list descending */
qsort(item_vote,
vote.num_items,
sizeof(menu_vote_result_t::menu_item_vote_t),
SortVoteItems);
/* Take the top 3 (if applicable) and draw them */
int len = 0;
for (unsigned int i=0; i<vote.num_items && i<3; i++)
{
int curItem = vote.item_list[i].item;
ItemDrawInfo dr;
m_pCurMenu->GetItemInfo(curItem, &dr);
len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
}
}
SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
{
DrawHintProgress();
return Pl_Continue;
}
void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
{
m_displayTimer = NULL;
}
+1 -12
View File
@@ -36,7 +36,6 @@
#include <IPlayerHelpers.h> #include <IPlayerHelpers.h>
#include <sh_vector.h> #include <sh_vector.h>
#include "sm_globals.h" #include "sm_globals.h"
#include <TimerSys.h>
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
@@ -44,8 +43,7 @@ using namespace SourceMod;
class VoteMenuHandler : class VoteMenuHandler :
public IMenuHandler, public IMenuHandler,
public SMGlobalClass, public SMGlobalClass,
public IClientListener, public IClientListener
public ITimedEvent
{ {
public: //SMGlobalClass public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
@@ -63,9 +61,6 @@ public: //IMenuHandler
void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason); void OnMenuEnd(IBaseMenu *menu, MenuEndReason reason);
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style); 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); unsigned int OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr);
public: //ITimedEvent
ResultType OnTimer(ITimer *pTimer, void *pData);
void OnTimerEnd(ITimer *pTimer, void *pData);
public: public:
bool StartVote(IBaseMenu *menu, bool StartVote(IBaseMenu *menu,
unsigned int num_clients, unsigned int num_clients,
@@ -90,12 +85,9 @@ private:
unsigned int time, unsigned int time,
unsigned int flags); unsigned int flags);
void StartVoting(); void StartVoting();
void DrawHintProgress();
void BuildVoteLeaders();
private: private:
IMenuHandler *m_pHandler; IMenuHandler *m_pHandler;
unsigned int m_Clients; unsigned int m_Clients;
unsigned int m_TotalClients;
unsigned int m_Items; unsigned int m_Items;
CVector<unsigned int> m_Votes; CVector<unsigned int> m_Votes;
IBaseMenu *m_pCurMenu; IBaseMenu *m_pCurMenu;
@@ -107,9 +99,6 @@ private:
float m_fStartTime; float m_fStartTime;
unsigned int m_nMenuTime; unsigned int m_nMenuTime;
int m_ClientVotes[256+1]; int m_ClientVotes[256+1];
bool m_Revoting[256+1];
char m_leaderList[1024];
ITimer *m_displayTimer;
}; };
#endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_ #endif //_INCLUDE_SOURCEMOD_MENUVOTING_H_
+6 -11
View File
@@ -31,7 +31,6 @@
#include "NextMap.h" #include "NextMap.h"
#include "Logger.h" #include "Logger.h"
#include "HalfLife2.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "sourcehook.h" #include "sourcehook.h"
@@ -50,11 +49,7 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &)
#elif SOURCE_ENGINE == SE_DARKMESSIAH #elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#else #else
# if SH_IMPL_VERSION >= 4 extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif #endif
@@ -110,7 +105,7 @@ const char *NextMapManager::GetNextMap()
bool NextMapManager::SetNextMap(const char *map) bool NextMapManager::SetNextMap(const char *map)
{ {
if (!g_HL2.IsMapValid(map)) if (!engine->IsMapValid(map))
{ {
return false; return false;
} }
@@ -134,7 +129,7 @@ void NextMapManager::HookChangeLevel(const char *map, const char *unknown, const
const char *newmap = sm_nextmap.GetString(); const char *newmap = sm_nextmap.GetString();
if (newmap[0] == 0 || !g_HL2.IsMapValid(newmap)) if (newmap[0] == 0 || !engine->IsMapValid(newmap))
{ {
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@@ -184,14 +179,14 @@ void NextMapManager::OnSourceModLevelChange( const char *mapName )
m_tempChangeInfo.m_mapName[0] ='\0'; m_tempChangeInfo.m_mapName[0] ='\0';
m_tempChangeInfo.m_changeReason[0] = '\0'; m_tempChangeInfo.m_changeReason[0] = '\0';
m_tempChangeInfo.startTime = time(NULL); m_tempChangeInfo.startTime = time(NULL);
UTIL_Format(lastMap, sizeof(lastMap), "%s", mapName); UTIL_Format(lastMap, sizeof(lastMap), mapName);
} }
void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason ) void NextMapManager::ForceChangeLevel( const char *mapName, const char* changeReason )
{ {
/* Store the mapname and reason */ /* Store the mapname and reason */
UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), "%s", mapName); UTIL_Format(m_tempChangeInfo.m_mapName, sizeof(m_tempChangeInfo.m_mapName), mapName);
UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), "%s", changeReason); UTIL_Format(m_tempChangeInfo.m_changeReason, sizeof(m_tempChangeInfo.m_changeReason), changeReason);
/* Change level and skip our hook */ /* Change level and skip our hook */
g_forcedChange = true; g_forcedChange = true;
+1 -1
View File
@@ -53,7 +53,7 @@ struct MapChangeData
startTime = 0; startTime = 0;
} }
char m_mapName[PLATFORM_MAX_PATH]; char m_mapName[32];
char m_changeReason[100]; char m_changeReason[100];
time_t startTime; time_t startTime;
}; };
@@ -29,9 +29,9 @@
* Version: $Id$ * Version: $Id$
*/ */
#include "common_logic.h"
#include "PhraseCollection.h" #include "PhraseCollection.h"
#include "Translator.h" #include "Translator.h"
#include "sm_stringutil.h"
CPhraseCollection::CPhraseCollection() CPhraseCollection::CPhraseCollection()
{ {
@@ -54,7 +54,7 @@ IPhraseFile *CPhraseCollection::AddPhraseFile(const char *filename)
char full_name[PLATFORM_MAX_PATH]; char full_name[PLATFORM_MAX_PATH];
/* No compat shim here. The user should have read the doc. */ /* No compat shim here. The user should have read the doc. */
smcore.Format(full_name, sizeof(full_name), "%s.txt", filename); UTIL_Format(full_name, sizeof(full_name), "%s.txt", filename);
fid = g_Translator.FindOrAddPhraseFile(full_name); fid = g_Translator.FindOrAddPhraseFile(full_name);
pFile = g_Translator.GetFileByIndex(fid); pFile = g_Translator.GetFileByIndex(fid);
@@ -113,7 +113,7 @@ bool CPhraseCollection::FormatString(char *buffer,
unsigned int arg; unsigned int arg;
arg = 0; arg = 0;
if (!smcore.gnprintf(buffer, maxlength, format, this, params, numparams, arg, pOutLength, pFailPhrase)) if (!gnprintf(buffer, maxlength, format, this, params, numparams, arg, pOutLength, pFailPhrase))
{ {
return false; return false;
} }
+78 -329
View File
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 tw=99 noet : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -39,23 +39,22 @@
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "CoreConfig.h" #include "CoreConfig.h"
#include "TimerSys.h" #include "TimerSys.h"
#include "Translator.h"
#include "Logger.h" #include "Logger.h"
#include "ChatTriggers.h" #include "ChatTriggers.h"
#include "HalfLife2.h" #include "HalfLife2.h"
#include <inetchannel.h> #include <inetchannel.h>
#include <iclient.h> #include <iclient.h>
#include <IGameConfigs.h> #include "GameConfigs.h"
#include "ExtensionSys.h" #include "ExtensionSys.h"
#include <sourcemod_version.h> #include "sm_version.h"
#include "ConsoleDetours.h"
#include "logic_bridge.h"
PlayerManager g_Players; PlayerManager g_Players;
bool g_OnMapStarted = false; bool g_OnMapStarted = false;
IForward *PreAdminCheck = NULL; IForward *PreAdminCheck = NULL;
IForward *PostAdminCheck = NULL; IForward *PostAdminCheck = NULL;
IForward *PostAdminFilter = NULL; IForward *PostAdminFilter = NULL;
IForward *OnClientConnected = NULL;
const unsigned int *g_NumPlayersToAuth = NULL; const unsigned int *g_NumPlayersToAuth = NULL;
int lifestate_offset = -1; int lifestate_offset = -1;
List<ICommandTargetProcessor *> target_processors; List<ICommandTargetProcessor *> target_processors;
@@ -76,11 +75,7 @@ SH_DECL_EXTERN1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &)
#elif SOURCE_ENGINE == SE_DARKMESSIAH #elif SOURCE_ENGINE == SE_DARKMESSIAH
SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false); SH_DECL_EXTERN0_void(ConCommand, Dispatch, SH_NOATTRIB, false);
#else #else
# if SH_IMPL_VERSION >= 4 extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
extern int __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# else
extern bool __SourceHook_FHAddConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
# endif
extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>); extern bool __SourceHook_FHRemoveConCommandDispatch(void *,bool,class fastdelegate::FastDelegate0<void>);
#endif #endif
@@ -113,11 +108,6 @@ PlayerManager::PlayerManager()
m_FirstPass = false; m_FirstPass = false;
m_maxClients = 0; m_maxClients = 0;
m_SourceTVUserId = -1;
m_ReplayUserId = -1;
m_bAuthstringValidation = false; // don't use steam auth by default... yet
m_UserIdLookUp = new int[USHRT_MAX+1]; m_UserIdLookUp = new int[USHRT_MAX+1];
memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1)); memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1));
} }
@@ -147,7 +137,6 @@ void PlayerManager::OnSourceModAllInitialized()
ParamType p2[] = {Param_Cell}; ParamType p2[] = {Param_Cell};
m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_LowEvent, 3, p1); m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_LowEvent, 3, p1);
m_clconnect_post = g_Forwards.CreateForward("OnClientConnected", ET_Ignore, 1, p2);
m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2); m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2); m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2); m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
@@ -156,6 +145,7 @@ void PlayerManager::OnSourceModAllInitialized()
m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String); m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL); m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL); m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
OnClientConnected = g_Forwards.CreateForward("OnClientConnected", ET_Ignore, 1, p2);
PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1); PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1); PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
@@ -164,6 +154,8 @@ void PlayerManager::OnSourceModAllInitialized()
m_bIsListenServer = !engine->IsDedicatedServer(); m_bIsListenServer = !engine->IsDedicatedServer();
m_ListenClient = 0; m_ListenClient = 0;
g_ConVarManager.AddConVarChangeListener("tv_enable", this);
ConCommand *pCmd = FindCommand("maxplayers"); ConCommand *pCmd = FindCommand("maxplayers");
if (pCmd != NULL) if (pCmd != NULL)
{ {
@@ -175,7 +167,6 @@ void PlayerManager::OnSourceModAllInitialized()
void PlayerManager::OnSourceModShutdown() void PlayerManager::OnSourceModShutdown()
{ {
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect_Post, true);
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
@@ -185,7 +176,6 @@ void PlayerManager::OnSourceModShutdown()
/* Release forwards */ /* Release forwards */
g_Forwards.ReleaseForward(m_clconnect); g_Forwards.ReleaseForward(m_clconnect);
g_Forwards.ReleaseForward(m_clconnect_post);
g_Forwards.ReleaseForward(m_clputinserver); g_Forwards.ReleaseForward(m_clputinserver);
g_Forwards.ReleaseForward(m_cldisconnect); g_Forwards.ReleaseForward(m_cldisconnect);
g_Forwards.ReleaseForward(m_cldisconnect_post); g_Forwards.ReleaseForward(m_cldisconnect_post);
@@ -194,6 +184,7 @@ void PlayerManager::OnSourceModShutdown()
g_Forwards.ReleaseForward(m_clauth); g_Forwards.ReleaseForward(m_clauth);
g_Forwards.ReleaseForward(m_onActivate); g_Forwards.ReleaseForward(m_onActivate);
g_Forwards.ReleaseForward(m_onActivate2); g_Forwards.ReleaseForward(m_onActivate2);
g_Forwards.ReleaseForward(OnClientConnected);
g_Forwards.ReleaseForward(PreAdminCheck); g_Forwards.ReleaseForward(PreAdminCheck);
g_Forwards.ReleaseForward(PostAdminCheck); g_Forwards.ReleaseForward(PostAdminCheck);
@@ -201,6 +192,8 @@ void PlayerManager::OnSourceModShutdown()
delete [] m_Players; delete [] m_Players;
g_ConVarManager.RemoveConVarChangeListener("tv_enable", this);
if (maxplayersCmd != NULL) if (maxplayersCmd != NULL)
{ {
SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, maxplayersCmd, CmdMaxplayersCallback, true); SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, maxplayersCmd, CmdMaxplayersCallback, true);
@@ -231,43 +224,16 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
return ConfigResult_Reject; return ConfigResult_Reject;
} }
return ConfigResult_Accept; return ConfigResult_Accept;
} else if (strcmp( key, "SteamAuthstringValidation" ) == 0) {
if (strcasecmp(value, "yes") == 0)
{
m_bAuthstringValidation = true;
} else if ( strcasecmp(value, "no") == 0) {
m_bAuthstringValidation = false;
} else {
UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
return ConfigResult_Reject;
}
return ConfigResult_Accept;
} }
return ConfigResult_Ignore; return ConfigResult_Ignore;
} }
void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax) void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
{ {
static ConVar *tv_enable = icvar->FindVar("tv_enable");
#if SOURCE_ENGINE == SE_TF2
static ConVar *replay_enable = icvar->FindVar("replay_enable");
#endif
// clientMax will not necessarily be correct here (such as on late SourceTV enable)
m_maxClients = gpGlobals->maxClients;
ICommandLine *commandLine = g_HL2.GetValveCommandLine();
m_bIsSourceTVActive = (tv_enable && tv_enable->GetBool() && (!commandLine || commandLine->FindParm("-nohltv") == 0));
m_bIsReplayActive = false;
#if SOURCE_ENGINE == SE_TF2
m_bIsReplayActive = (replay_enable && replay_enable->GetBool());
#endif
m_PlayersSinceActive = 0;
if (!m_FirstPass) if (!m_FirstPass)
{ {
/* Initialize all players */ /* Initialize all players */
m_maxClients = clientMax;
m_PlayerCount = 0; m_PlayerCount = 0;
m_Players = new CPlayer[ABSOLUTE_PLAYER_LIMIT + 1]; m_Players = new CPlayer[ABSOLUTE_PLAYER_LIMIT + 1];
m_AuthQueue = new unsigned int[ABSOLUTE_PLAYER_LIMIT + 1]; m_AuthQueue = new unsigned int[ABSOLUTE_PLAYER_LIMIT + 1];
@@ -276,13 +242,10 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl
memset(m_AuthQueue, 0, sizeof(unsigned int) * (ABSOLUTE_PLAYER_LIMIT + 1)); memset(m_AuthQueue, 0, sizeof(unsigned int) * (ABSOLUTE_PLAYER_LIMIT + 1));
g_NumPlayersToAuth = &m_AuthQueue[0]; g_NumPlayersToAuth = &m_AuthQueue[0];
g_PluginSys.SyncMaxClients(clientMax);
} }
g_Extensions.CallOnCoreMapStart(pEdictList, edictCount, clientMax);
g_PluginSys.SyncMaxClients(m_maxClients);
g_OnMapStarted = true;
g_Extensions.CallOnCoreMapStart(pEdictList, edictCount, m_maxClients);
m_onActivate->Execute(NULL); m_onActivate->Execute(NULL);
m_onActivate2->Execute(NULL); m_onActivate2->Execute(NULL);
@@ -291,10 +254,12 @@ void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int cl
{ {
if ((*iter)->GetClientListenerVersion() >= 5) if ((*iter)->GetClientListenerVersion() >= 5)
{ {
(*iter)->OnServerActivated(m_maxClients); (*iter)->OnServerActivated(clientMax);
} }
} }
g_OnMapStarted = true;
SMGlobalClass *cls = SMGlobalClass::head; SMGlobalClass *cls = SMGlobalClass::head;
while (cls) while (cls)
{ {
@@ -367,18 +332,11 @@ void PlayerManager::RunAuthChecks()
{ {
pPlayer = &m_Players[m_AuthQueue[i]]; pPlayer = &m_Players[m_AuthQueue[i]];
authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict); authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict);
pPlayer->SetAuthString(authstr);
if (!pPlayer->IsAuthStringValidated())
{
continue; // we're using steam auth, and steam doesn't know about this player yet so we can't do anything about them for now
}
if (authstr && authstr[0] != '\0' if (authstr && authstr[0] != '\0'
&& (strcmp(authstr, "STEAM_ID_PENDING") != 0)) && (strcmp(authstr, "STEAM_ID_PENDING") != 0))
{ {
/* Set authorization */ /* Set authorization */
pPlayer->Authorize(); pPlayer->Authorize(authstr);
/* Mark as removed from queue */ /* Mark as removed from queue */
unsigned int client = m_AuthQueue[i]; unsigned int client = m_AuthQueue[i];
@@ -447,23 +405,7 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
{ {
int client = IndexOfEdict(pEntity); int client = IndexOfEdict(pEntity);
CPlayer *pPlayer = &m_Players[client]; CPlayer *pPlayer = &m_Players[client];
++m_PlayersSinceActive;
pPlayer->Initialize(pszName, pszAddress, pEntity);
/* Get the client's language */
if (m_QueryLang)
{
const char *name;
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
{
unsigned int langid;
pPlayer->m_LangId = (translator->GetLanguageByName(name, &langid)) ? langid : translator->GetServerLanguage();
} else {
pPlayer->m_LangId = translator->GetServerLanguage();
}
}
List<IClientListener *>::iterator iter; List<IClientListener *>::iterator iter;
IClientListener *pListener = NULL; IClientListener *pListener = NULL;
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
@@ -471,12 +413,13 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const
pListener = (*iter); pListener = (*iter);
if (!pListener->InterceptClientConnect(client, reject, maxrejectlen)) if (!pListener->InterceptClientConnect(client, reject, maxrejectlen))
{ {
RETURN_META_VALUE(MRES_SUPERCEDE, false); return false;
} }
} }
cell_t res = 1; cell_t res = 1;
pPlayer->Initialize(pszName, pszAddress, pEntity);
m_clconnect->PushCell(client); m_clconnect->PushCell(client);
m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
m_clconnect->PushCell(maxrejectlen); m_clconnect->PushCell(maxrejectlen);
@@ -518,7 +461,7 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
pListener->OnClientConnected(client); pListener->OnClientConnected(client);
if (!pPlayer->IsConnected()) if (!pPlayer->IsConnected())
{ {
return true; break;
} }
} }
@@ -530,8 +473,8 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName,
} }
cell_t res; cell_t res;
m_clconnect_post->PushCell(client); OnClientConnected->PushCell(client);
m_clconnect_post->Execute(&res, NULL); OnClientConnected->Execute(&res, NULL);
} }
else else
{ {
@@ -553,70 +496,8 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
/* Run manual connection routines */ /* Run manual connection routines */
char error[255]; char error[255];
const char *authid = engine->GetPlayerNetworkIDString(pEntity); const char *authid = engine->GetPlayerNetworkIDString(pEntity);
pPlayer->SetAuthString(authid); pPlayer->Authorize(authid);
pPlayer->Authorize();
pPlayer->m_bFakeClient = true; pPlayer->m_bFakeClient = true;
/*
* While we're already filtered to just bots, we'll do other checks to
* make sure that the requisite services are enabled and that the bots
* have joined at the expected time.
*
* Checking playerinfo's IsHLTV and IsReplay would be better and less
* error-prone but will always show false until later in the frame,
* after PutInServer and Activate, and we want it now!
*
* These checks are hairy as hell due to differences between engines and games.
*
* Most engines use "Replay" and "SourceTV" as bot names for these when they're
* created. EP2V, CSS and Nuclear Dawn (but not L4D2) differ from this by now using
* replay_/tv_name directly when creating the bot(s). To complicate it slightly
* further, the cvar can be empty and the engine's fallback to "unnamed" will be used.
* We can maybe just rip out the name checks at some point and rely solely on whether
* they're enabled and the join order.
*/
// This doesn't actually get incremented until OnClientConnect. Fake it to check.
int newCount = m_PlayersSinceActive + 1;
int userId = engine->GetPlayerUserId(pEntity);
#if (SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_NUCLEARDAWN || SOURCE_ENGINE == SE_LEFT4DEAD2)
static ConVar *tv_name = icvar->FindVar("tv_name");
#endif
#if SOURCE_ENGINE == SE_TF2
static ConVar *replay_name = icvar->FindVar("replay_name");
#endif
#if SOURCE_ENGINE == SE_TF2
if (m_bIsReplayActive && newCount == 1
&& (m_ReplayUserId == userId
|| (replay_name && strcmp(playername, replay_name->GetString()) == 0) || (replay_name && replay_name->GetString()[0] == 0 && strcmp(playername, "unnamed") == 0)
)
)
{
pPlayer->m_bIsReplay = true;
m_ReplayUserId = userId;
}
#endif
if (m_bIsSourceTVActive
&& ((!m_bIsReplayActive && newCount == 1)
|| (m_bIsReplayActive && newCount == 2))
&& (m_SourceTVUserId == userId
#if SOURCE_ENGINE == SE_CSGO
|| strcmp(playername, "GOTV") == 0
#elif (SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_NUCLEARDAWN)
|| (tv_name && strcmp(playername, tv_name->GetString()) == 0) || (tv_name && tv_name->GetString()[0] == 0 && strcmp(playername, "unnamed") == 0)
#else
|| strcmp(playername, "SourceTV") == 0
#endif
)
)
{
pPlayer->m_bIsSourceTV = true;
m_SourceTVUserId = userId;
}
if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error))) if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error)))
{ {
/* :TODO: kick the bot if it's rejected */ /* :TODO: kick the bot if it's rejected */
@@ -634,11 +515,6 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
return; return;
} }
} }
cell_t res;
m_clconnect_post->PushCell(client);
m_clconnect_post->Execute(&res, NULL);
/* Now do authorization */ /* Now do authorization */
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
{ {
@@ -660,6 +536,19 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername
pPlayer->m_Info = playerinfo->GetPlayerInfo(pEntity); pPlayer->m_Info = playerinfo->GetPlayerInfo(pEntity);
} }
/* Get the client's language */
if (m_QueryLang)
{
const char *name;
if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
{
unsigned int langid;
pPlayer->m_LangId = (g_Translator.GetLanguageByName(name, &langid)) ? langid : g_Translator.GetServerLanguage();
} else {
pPlayer->m_LangId = g_Translator.GetServerLanguage();
}
}
pPlayer->Connect(); pPlayer->Connect();
m_PlayerCount++; m_PlayerCount++;
@@ -793,30 +682,23 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
g_PluginSys.ListPluginsToClient(pPlayer, args); g_PluginSys.ListPluginsToClient(pPlayer, args);
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
else if (args.ArgC() > 1 && strcmp(args.Arg(1), "exts") == 0)
{
g_Extensions.ListExtensionsToClient(pPlayer, args);
RETURN_META(MRES_SUPERCEDE);
}
else if (args.ArgC() > 1 && strcmp(args.Arg(1), "credits") == 0) else if (args.ArgC() > 1 && strcmp(args.Arg(1), "credits") == 0)
{ {
ClientConsolePrint(pEntity,
"SourceMod would not be possible without:");
ClientConsolePrint(pEntity,
" David \"BAILOPAN\" Anderson, Matt \"pRED\" Woodrow");
ClientConsolePrint(pEntity,
" Scott \"DS\" Ehlert, Fyren");
ClientConsolePrint(pEntity,
" Nicholas \"psychonic\" Hastings, Asher \"asherkin\" Baker");
ClientConsolePrint(pEntity, ClientConsolePrint(pEntity,
" Borja \"faluco\" Ferrer, Pavol \"PM OnoTo\" Marko"); "SourceMod would not be possible without:");
ClientConsolePrint(pEntity,
" David \"BAILOPAN\" Anderson, Borja \"faluco\" Ferrer");
ClientConsolePrint(pEntity,
" Scott \"Damaged Soul\" Ehlert, Matt \"pRED\" Woodrow");
ClientConsolePrint(pEntity,
" Michael \"ferret\" McKoy, Pavol \"PM OnoTo\" Marko");
ClientConsolePrint(pEntity, ClientConsolePrint(pEntity,
"SourceMod is open source under the GNU General Public License."); "SourceMod is open source under the GNU General Public License.");
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
ClientConsolePrint(pEntity, ClientConsolePrint(pEntity,
"SourceMod %s, by AlliedModders LLC", SOURCEMOD_VERSION); "SourceMod %s, by AlliedModders LLC", SVN_FULL_VERSION);
ClientConsolePrint(pEntity, ClientConsolePrint(pEntity,
"To see running plugins, type \"sm plugins\""); "To see running plugins, type \"sm plugins\"");
ClientConsolePrint(pEntity, ClientConsolePrint(pEntity,
@@ -843,27 +725,10 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
} }
} }
if (g_ConsoleDetours.IsEnabled())
{
cell_t res2 = g_ConsoleDetours.InternalDispatch(client, args);
if (res2 >= Pl_Stop)
{
g_HL2.PopCommandStack();
RETURN_META(MRES_SUPERCEDE);
}
else if (res2 > res)
{
res = res2;
}
}
cell_t res2 = Pl_Continue; cell_t res2 = Pl_Continue;
if (pPlayer->IsInGame()) m_clcommand->PushCell(client);
{ m_clcommand->PushCell(argcount);
m_clcommand->PushCell(client); m_clcommand->Execute(&res2, NULL);
m_clcommand->PushCell(argcount);
m_clcommand->Execute(&res2, NULL);
}
if (res2 > res) if (res2 > res)
{ {
@@ -909,19 +774,6 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name"); const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
const char *old_name = pPlayer->m_Name.c_str(); const char *old_name = pPlayer->m_Name.c_str();
#if SOURCE_ENGINE >= SE_LEFT4DEAD
const char *networkid_force;
if ((networkid_force = engine->GetClientConVarValue(client, "networkid_force")) && networkid_force[0] != '\0')
{
unsigned int accountId = pPlayer->GetSteamAccountID();
g_Logger.LogMessage("\"%s<%d><STEAM_1:%d:%d><>\" has bad networkid (id \"%s\") (ip \"%s\")",
new_name, pPlayer->GetUserId(), accountId & 1, accountId >> 1, networkid_force, pPlayer->GetIPAddress());
pPlayer->Kick("NetworkID spoofing detected.");
RETURN_META(MRES_IGNORED);
}
#endif
if (strcmp(old_name, new_name) != 0) if (strcmp(old_name, new_name) != 0)
{ {
AdminId id = g_Admins.FindAdminByIdentity("name", new_name); AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
@@ -929,9 +781,7 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
{ {
if (!CheckSetAdminName(client, pPlayer, id)) if (!CheckSetAdminName(client, pPlayer, id))
{ {
char kickMsg[128]; pPlayer->Kick("Your name is reserved by SourceMod; set your password to use it.");
logicore.CoreTranslate(kickMsg, sizeof(kickMsg), "%T", 2, NULL, "Name Reserved", &client);
pPlayer->Kick(kickMsg);
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
} else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) { } else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
@@ -959,17 +809,6 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
} }
} }
} }
/* Notify Extensions */
List<IClientListener *>::iterator iter;
IClientListener *pListener = NULL;
for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
{
pListener = (*iter);
if (pListener->GetClientListenerVersion() >= 13)
{
pListener->OnClientSettingsChanged(client);
}
}
} }
int PlayerManager::GetMaxClients() int PlayerManager::GetMaxClients()
@@ -1259,12 +1098,11 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
{ {
continue; continue;
} }
if (!pTarget->IsConnected()) if (!pTarget->IsConnected() || !pTarget->IsAuthorized())
{ {
continue; continue;
} }
const char *authstr = pTarget->GetAuthString(false); // We want to make it easy for people to be kicked/banned, so don't require validation for command targets. if (strcmp(pTarget->GetAuthString(), new_pattern) == 0)
if (authstr && strcmp(authstr, new_pattern) == 0)
{ {
if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags)) if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags))
== COMMAND_TARGET_VALID) == COMMAND_TARGET_VALID)
@@ -1315,18 +1153,10 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
if (strcmp(info->pattern, "@me") == 0 && info->admin != 0) if (strcmp(info->pattern, "@me") == 0 && info->admin != 0)
{ {
info->reason = FilterCommandTarget(pAdmin, pAdmin, info->flags); info->targets[0] = info->admin;
if (info->reason == COMMAND_TARGET_VALID) info->num_targets = 1;
{ strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
info->targets[0] = info->admin; info->target_name_style = COMMAND_TARGETNAME_RAW;
info->num_targets = 1;
strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
info->target_name_style = COMMAND_TARGETNAME_RAW;
}
else
{
info->num_targets = 0;
}
return; return;
} }
@@ -1374,7 +1204,7 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
if ((info->flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS) if ((info->flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS)
{ {
info->num_targets = 0; info->num_targets = 0;
info->reason = COMMAND_TARGET_NOT_HUMAN; info->reason = COMMAND_FILTER_NO_BOTS;
return; return;
} }
strncopy(info->target_name, "all bots", info->target_name_maxlength); strncopy(info->target_name, "all bots", info->target_name_maxlength);
@@ -1440,7 +1270,7 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
continue; continue;
} }
if (logicore.stristr(pTarget->GetName(), info->pattern) != NULL) if (stristr(pTarget->GetName(), info->pattern) != NULL)
{ {
if (found_client) if (found_client)
{ {
@@ -1478,6 +1308,18 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
} }
} }
void PlayerManager::OnConVarChanged( ConVar *pConVar, const char *oldValue, float flOldValue )
{
if (pConVar->GetBool() && !atoi(oldValue))
{
MaxPlayersChanged(gpGlobals->maxClients + 1);
}
else
{
MaxPlayersChanged();
}
}
void PlayerManager::OnSourceModMaxPlayersChanged( int newvalue ) void PlayerManager::OnSourceModMaxPlayersChanged( int newvalue )
{ {
m_maxClients = newvalue; m_maxClients = newvalue;
@@ -1569,15 +1411,10 @@ CPlayer::CPlayer()
m_TempAdmin = false; m_TempAdmin = false;
m_Info = NULL; m_Info = NULL;
m_bAdminCheckSignalled = false; m_bAdminCheckSignalled = false;
m_UserId = -1;
m_bIsInKickQueue = false; m_bIsInKickQueue = false;
m_LastPassword.clear(); m_LastPassword.clear();
m_LangId = SOURCEMOD_LANGUAGE_ENGLISH; m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
m_bFakeClient = false; m_bFakeClient = false;
m_bIsSourceTV = false;
m_bIsReplay = false;
m_Serial.value = -1;
m_SteamAccountID = 0;
} }
void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity) void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
@@ -1587,7 +1424,7 @@ void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
m_Ip.assign(ip); m_Ip.assign(ip);
m_pEdict = pEntity; m_pEdict = pEntity;
m_iIndex = IndexOfEdict(pEntity); m_iIndex = IndexOfEdict(pEntity);
m_LangId = translator->GetServerLanguage(); m_LangId = g_Translator.GetServerLanguage();
m_Serial.bits.index = m_iIndex; m_Serial.bits.index = m_iIndex;
m_Serial.bits.serial = g_PlayerSerialCount++; m_Serial.bits.serial = g_PlayerSerialCount++;
@@ -1623,20 +1460,15 @@ void CPlayer::Connect()
} }
} }
void CPlayer::SetAuthString(const char *steamid) void CPlayer::Authorize(const char *steamid)
{ {
if (m_IsAuthorized) if (m_IsAuthorized)
{ {
return; return;
} }
m_AuthID.assign(steamid);
}
// Ensure a valid AuthString is set before calling.
void CPlayer::Authorize()
{
m_IsAuthorized = true; m_IsAuthorized = true;
m_AuthID.assign(steamid);
} }
void CPlayer::Disconnect() void CPlayer::Disconnect()
@@ -1654,10 +1486,6 @@ void CPlayer::Disconnect()
m_UserId = -1; m_UserId = -1;
m_bIsInKickQueue = false; m_bIsInKickQueue = false;
m_bFakeClient = false; m_bFakeClient = false;
m_bIsSourceTV = false;
m_bIsReplay = false;
m_Serial.value = -1;
m_SteamAccountID = 0;
} }
void CPlayer::SetName(const char *name) void CPlayer::SetName(const char *name)
@@ -1680,45 +1508,11 @@ const char *CPlayer::GetIPAddress()
return m_Ip.c_str(); return m_Ip.c_str();
} }
const char *CPlayer::GetAuthString(bool validated) const char *CPlayer::GetAuthString()
{ {
if (validated && !IsAuthStringValidated())
{
return NULL;
}
return m_AuthID.c_str(); return m_AuthID.c_str();
} }
unsigned int CPlayer::GetSteamAccountID(bool validated)
{
if (IsFakeClient() || (validated && !IsAuthStringValidated()))
{
return 0;
}
if (m_SteamAccountID != 0)
{
return m_SteamAccountID;
}
#if SOURCE_ENGINE < SE_ORANGEBOX
const char * pAuth = GetAuthString();
/* STEAM_0:1:123123 | STEAM_ID_LAN | STEAM_ID_PENDING */
if (pAuth && (strlen(pAuth) > 10) && pAuth[8] != '_')
{
m_SteamAccountID = (atoi(&pAuth[8]) | (atoi(&pAuth[10]) << 1));
}
#else
unsigned long long *steamId = (unsigned long long *)engine->GetClientSteamID(m_pEdict);
if (steamId)
{
m_SteamAccountID = (*steamId & 0xFFFFFFFF);
}
#endif
return m_SteamAccountID;
}
edict_t *CPlayer::GetEdict() edict_t *CPlayer::GetEdict()
{ {
return m_pEdict; return m_pEdict;
@@ -1744,18 +1538,6 @@ bool CPlayer::IsAuthorized()
return m_IsAuthorized; return m_IsAuthorized;
} }
bool CPlayer::IsAuthStringValidated()
{
#if SOURCE_ENGINE >= SE_ORANGEBOX
if (g_Players.m_bAuthstringValidation && !g_HL2.IsLANServer())
{
return engine->IsClientFullyAuthenticated(m_pEdict);
}
#endif
return true;
}
IPlayerInfo *CPlayer::GetPlayerInfo() IPlayerInfo *CPlayer::GetPlayerInfo()
{ {
if (m_pEdict->GetUnknown()) if (m_pEdict->GetUnknown())
@@ -1771,16 +1553,6 @@ bool CPlayer::IsFakeClient()
return m_bFakeClient; return m_bFakeClient;
} }
bool CPlayer::IsSourceTV() const
{
return m_bIsSourceTV;
}
bool CPlayer::IsReplay() const
{
return m_bIsReplay;
}
void CPlayer::SetAdminId(AdminId id, bool temporary) void CPlayer::SetAdminId(AdminId id, bool temporary)
{ {
if (!m_IsConnected) if (!m_IsConnected)
@@ -1816,26 +1588,8 @@ void CPlayer::Kick(const char *str)
{ {
MarkAsBeingKicked(); MarkAsBeingKicked();
INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex)); INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
if (pNetChan == NULL) IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
{ pClient->Disconnect("%s", str);
/* What does this even mean? Hell if I know. */
int userid = GetUserId();
if (userid > 0)
{
char buffer[255];
UTIL_Format(buffer, sizeof(buffer), "kickid %d %s\n", userid, str);
engine->ServerCommand(buffer);
}
}
else
{
IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
#if SOURCE_ENGINE == SE_CSGO
pClient->Disconnect(str);
#else
pClient->Disconnect("%s", str);
#endif
}
} }
void CPlayer::Authorize_Post() void CPlayer::Authorize_Post()
@@ -1977,11 +1731,6 @@ unsigned int CPlayer::GetLanguageId()
return m_LangId; return m_LangId;
} }
void CPlayer::SetLanguageId(unsigned int id)
{
m_LangId = id;
}
int CPlayer::GetUserId() int CPlayer::GetUserId()
{ {
if (m_UserId == -1) if (m_UserId == -1)
+8 -21
View File
@@ -56,7 +56,7 @@ union serial_t
uint32_t value; uint32_t value;
struct struct
{ {
uint32_t index : 8; uint8_t index;
uint32_t serial : 24; uint32_t serial : 24;
} bits; } bits;
}; };
@@ -69,29 +69,25 @@ public:
public: public:
const char *GetName(); const char *GetName();
const char *GetIPAddress(); const char *GetIPAddress();
const char *GetAuthString(bool validated = true); const char *GetAuthString();
unsigned int GetSteamAccountID(bool validated = true);
edict_t *GetEdict(); edict_t *GetEdict();
bool IsInGame(); bool IsInGame();
bool WasCountedAsInGame(); bool WasCountedAsInGame();
bool IsConnected(); bool IsConnected();
bool IsAuthorized(); bool IsAuthorized();
bool IsFakeClient(); bool IsFakeClient();
bool IsSourceTV() const;
bool IsReplay() const;
void SetAdminId(AdminId id, bool temporary); void SetAdminId(AdminId id, bool temporary);
AdminId GetAdminId(); AdminId GetAdminId();
void Kick(const char *str); void Kick(const char *str);
bool IsInKickQueue();
IPlayerInfo *GetPlayerInfo(); IPlayerInfo *GetPlayerInfo();
unsigned int GetLanguageId(); unsigned int GetLanguageId();
void SetLanguageId(unsigned int id);
int GetUserId(); int GetUserId();
bool RunAdminCacheChecks(); bool RunAdminCacheChecks();
void NotifyPostAdminChecks(); void NotifyPostAdminChecks();
unsigned int GetSerial(); unsigned int GetSerial();
public: public:
void DoBasicAdminChecks(); void DoBasicAdminChecks();
bool IsInKickQueue();
void MarkAsBeingKicked(); void MarkAsBeingKicked();
int GetLifeState(); int GetLifeState();
private: private:
@@ -100,11 +96,9 @@ private:
void Disconnect(); void Disconnect();
void SetName(const char *name); void SetName(const char *name);
void DumpAdmin(bool deleting); void DumpAdmin(bool deleting);
void SetAuthString(const char *auth); void Authorize(const char *auth);
void Authorize();
void Authorize_Post(); void Authorize_Post();
void DoPostConnectAuthorization(); void DoPostConnectAuthorization();
bool IsAuthStringValidated();
private: private:
bool m_IsConnected; bool m_IsConnected;
bool m_IsInGame; bool m_IsInGame;
@@ -124,15 +118,13 @@ private:
unsigned int m_LangId; unsigned int m_LangId;
int m_UserId; int m_UserId;
bool m_bFakeClient; bool m_bFakeClient;
bool m_bIsSourceTV;
bool m_bIsReplay;
serial_t m_Serial; serial_t m_Serial;
unsigned int m_SteamAccountID;
}; };
class PlayerManager : class PlayerManager :
public SMGlobalClass, public SMGlobalClass,
public IPlayerManager public IPlayerManager,
public IConVarChangeListener
{ {
friend class CPlayer; friend class CPlayer;
public: public:
@@ -177,6 +169,8 @@ public: //IPlayerManager
void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler); void UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler);
void ProcessCommandTarget(cmd_target_info_t *info); void ProcessCommandTarget(cmd_target_info_t *info);
int GetClientFromSerial(unsigned int serial); int GetClientFromSerial(unsigned int serial);
public: // IConVarChangeListener
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
public: public:
inline int MaxClients() inline int MaxClients()
{ {
@@ -203,7 +197,6 @@ private:
private: private:
List<IClientListener *> m_hooks; List<IClientListener *> m_hooks;
IForward *m_clconnect; IForward *m_clconnect;
IForward *m_clconnect_post;
IForward *m_cldisconnect; IForward *m_cldisconnect;
IForward *m_cldisconnect_post; IForward *m_cldisconnect_post;
IForward *m_clputinserver; IForward *m_clputinserver;
@@ -216,18 +209,12 @@ private:
int *m_UserIdLookUp; int *m_UserIdLookUp;
int m_maxClients; int m_maxClients;
int m_PlayerCount; int m_PlayerCount;
int m_PlayersSinceActive;
bool m_FirstPass; bool m_FirstPass;
unsigned int *m_AuthQueue; unsigned int *m_AuthQueue;
String m_PassInfoVar; String m_PassInfoVar;
bool m_QueryLang; bool m_QueryLang;
bool m_bAuthstringValidation; // are we validating admins with steam before authorizing?
bool m_bIsListenServer; bool m_bIsListenServer;
int m_ListenClient; int m_ListenClient;
bool m_bIsSourceTVActive;
bool m_bIsReplayActive;
int m_SourceTVUserId;
int m_ReplayUserId;
}; };
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
+1 -1
View File
@@ -276,7 +276,7 @@ SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
{ {
m_infodb_size *= 2; m_infodb_size *= 2;
} }
int newidx = memtab->CreateMem(m_infodb_size * sizeof(int), (void **)&table); int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
if (m_infodb != -1) if (m_infodb != -1)
{ {
void *oldtable = (int *)memtab->GetAddress(m_infodb); void *oldtable = (int *)memtab->GetAddress(m_infodb);
+137 -195
View File
@@ -37,6 +37,7 @@
#include "ForwardSys.h" #include "ForwardSys.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sourcemod.h" #include "sourcemod.h"
#include "TextParsers.h"
#include "Logger.h" #include "Logger.h"
#include "ExtensionSys.h" #include "ExtensionSys.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
@@ -44,7 +45,7 @@
#include "ConCmdManager.h" #include "ConCmdManager.h"
#include "PlayerManager.h" #include "PlayerManager.h"
#include "CoreConfig.h" #include "CoreConfig.h"
#include "logic_bridge.h" #include "Translator.h"
CPluginManager g_PluginSys; CPluginManager g_PluginSys;
HandleType_t g_PluginType = 0; HandleType_t g_PluginType = 0;
@@ -56,18 +57,17 @@ CPlugin::CPlugin(const char *file)
m_type = PluginType_Private; m_type = PluginType_Private;
m_status = Plugin_Uncompiled; m_status = Plugin_Uncompiled;
m_bSilentlyFailed = false;
m_serial = ++MySerial; m_serial = ++MySerial;
m_pRuntime = NULL; m_pRuntime = NULL;
m_errormsg[sizeof(m_errormsg) - 1] = '\0'; m_errormsg[256] = '\0';
UTIL_Format(m_filename, sizeof(m_filename), "%s", file); snprintf(m_filename, sizeof(m_filename), "%s", file);
m_handle = 0; m_handle = 0;
m_ident = NULL; m_ident = NULL;
m_pProps = sm_trie_create(); m_pProps = sm_trie_create();
m_FakeNativesMissing = false; m_FakeNativesMissing = false;
m_LibraryMissing = false; m_LibraryMissing = false;
m_bGotAllLoaded = false; m_bGotAllLoaded = false;
m_pPhrases = translator->CreatePhraseCollection(); m_pPhrases = g_Translator.CreatePhraseCollection();
m_MaxClientsVar = NULL; m_MaxClientsVar = NULL;
} }
@@ -164,7 +164,7 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength)
{ {
if (error) if (error)
{ {
UTIL_Format(error, maxlength, "Unable to open file"); snprintf(error, maxlength, "Unable to open file");
} }
pPlugin->m_status = Plugin_BadLoad; pPlugin->m_status = Plugin_BadLoad;
return pPlugin; return pPlugin;
@@ -210,7 +210,7 @@ void CPlugin::SetErrorState(PluginStatus status, const char *error_fmt, ...)
va_list ap; va_list ap;
va_start(ap, error_fmt); va_start(ap, error_fmt);
UTIL_FormatArgs(m_errormsg, sizeof(m_errormsg), error_fmt, ap); vsnprintf(m_errormsg, sizeof(m_errormsg), error_fmt, ap);
va_end(ap); va_end(ap);
if (m_pRuntime != NULL) if (m_pRuntime != NULL)
@@ -372,7 +372,7 @@ void CPlugin::Call_OnAllPluginsLoaded()
pFunction->Execute(&result); pFunction->Execute(&result);
} }
if (g_SourceMod.IsMapRunning()) if (g_OnMapStarted)
{ {
if ((pFunction = m_pRuntime->GetFunctionByName("OnMapStart")) != NULL) if ((pFunction = m_pRuntime->GetFunctionByName("OnMapStart")) != NULL)
{ {
@@ -386,27 +386,22 @@ void CPlugin::Call_OnAllPluginsLoaded()
} }
} }
APLRes CPlugin::Call_AskPluginLoad(char *error, size_t maxlength) bool CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
{ {
if (m_status != Plugin_Created) if (m_status != Plugin_Created)
{ {
return APLRes_Failure; return false;
} }
m_status = Plugin_Loaded; m_status = Plugin_Loaded;
int err; int err;
cell_t result; cell_t result;
bool haveNewAPL = false; IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad");
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad2");
if (pFunction) if (!pFunction)
{ {
haveNewAPL = true; return true;
}
else if (!(pFunction = m_pRuntime->GetFunctionByName("AskPluginLoad")))
{
return APLRes_Success;
} }
pFunction->PushCell(m_handle); pFunction->PushCell(m_handle);
@@ -415,21 +410,15 @@ APLRes CPlugin::Call_AskPluginLoad(char *error, size_t maxlength)
pFunction->PushCell(maxlength); pFunction->PushCell(maxlength);
if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE) if ((err=pFunction->Execute(&result)) != SP_ERROR_NONE)
{ {
return APLRes_Failure; return false;
} }
if (haveNewAPL) if (!result || m_status != Plugin_Loaded)
{ {
return (APLRes)result; return false;
}
else if (result)
{
return APLRes_Success;
}
else
{
return APLRes_Failure;
} }
return true;
} }
void *CPlugin::GetPluginStructure() void *CPlugin::GetPluginStructure()
@@ -481,11 +470,6 @@ PluginStatus CPlugin::GetStatus()
return m_status; return m_status;
} }
bool CPlugin::IsSilentlyFailed()
{
return m_bSilentlyFailed;
}
bool CPlugin::IsDebugging() bool CPlugin::IsDebugging()
{ {
if (m_pRuntime == NULL) if (m_pRuntime == NULL)
@@ -496,19 +480,14 @@ bool CPlugin::IsDebugging()
return true; return true;
} }
void CPlugin::SetSilentlyFailed(bool sf) void CPlugin::LibraryActions(bool dropping)
{
m_bSilentlyFailed = sf;
}
void CPlugin::LibraryActions(LibraryAction action)
{ {
List<String>::iterator iter; List<String>::iterator iter;
for (iter = m_Libraries.begin(); for (iter = m_Libraries.begin();
iter != m_Libraries.end(); iter != m_Libraries.end();
iter++) iter++)
{ {
g_PluginSys.OnLibraryAction((*iter).c_str(), action); g_PluginSys.OnLibraryAction((*iter).c_str(), true, dropping);
} }
} }
@@ -523,7 +502,7 @@ bool CPlugin::SetPauseState(bool paused)
if (paused) if (paused)
{ {
LibraryActions(LibraryAction_Removed); LibraryActions(true);
} }
IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginPauseChange"); IPluginFunction *pFunction = m_pRuntime->GetFunctionByName("OnPluginPauseChange");
@@ -547,7 +526,7 @@ bool CPlugin::SetPauseState(bool paused)
if (!paused) if (!paused)
{ {
LibraryActions(LibraryAction_Added); LibraryActions(false);
} }
return true; return true;
@@ -789,8 +768,6 @@ CPluginManager::CPluginManager()
m_AllPluginsLoaded = false; m_AllPluginsLoaded = false;
m_MyIdent = NULL; m_MyIdent = NULL;
m_LoadingLocked = false; m_LoadingLocked = false;
m_bBlockBadPlugins = true;
} }
CPluginManager::~CPluginManager() CPluginManager::~CPluginManager()
@@ -874,7 +851,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
if (localpath == NULL) if (localpath == NULL)
{ {
/* If no path yet, don't add a former slash */ /* If no path yet, don't add a former slash */
UTIL_Format(new_local, sizeof(new_local), "%s", dir->GetEntryName()); snprintf(new_local, sizeof(new_local), "%s", dir->GetEntryName());
} else { } else {
g_LibSys.PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName()); g_LibSys.PathFormat(new_local, sizeof(new_local), "%s/%s", localpath, dir->GetEntryName());
} }
@@ -889,7 +866,7 @@ void CPluginManager::LoadPluginsFromDir(const char *basedir, const char *localpa
char plugin[PLATFORM_MAX_PATH]; char plugin[PLATFORM_MAX_PATH];
if (localpath == NULL) if (localpath == NULL)
{ {
UTIL_Format(plugin, sizeof(plugin), "%s", name); snprintf(plugin, sizeof(plugin), "%s", name);
} else { } else {
g_LibSys.PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name); g_LibSys.PathFormat(plugin, sizeof(plugin), "%s/%s", localpath, name);
} }
@@ -988,7 +965,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
{ {
if (error) if (error)
{ {
UTIL_Format(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val); snprintf(error, maxlength, "Unable to set JIT option (key \"%s\") (value \"%s\")", key, val);
} }
co->Abort(); co->Abort();
co = NULL; co = NULL;
@@ -1007,14 +984,11 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
pPlugin->m_pRuntime = g_pSourcePawn2->LoadPlugin(co, fullpath, &err); pPlugin->m_pRuntime = g_pSourcePawn2->LoadPlugin(co, fullpath, &err);
if (pPlugin->m_pRuntime == NULL) if (pPlugin->m_pRuntime == NULL)
{ {
if (error) snprintf(error,
{ maxlength,
UTIL_Format(error, "Unable to load plugin (error %d: %s)",
maxlength, err,
"Unable to load plugin (error %d: %s)", g_pSourcePawn2->GetErrorString(err));
err,
g_pSourcePawn2->GetErrorString(err));
}
pPlugin->m_status = Plugin_BadLoad; pPlugin->m_status = Plugin_BadLoad;
} }
else else
@@ -1025,74 +999,25 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
} }
else else
{ {
if (error) UTIL_Format(error, maxlength, "%s", pPlugin->m_errormsg);
{
UTIL_Format(error, maxlength, "%s", pPlugin->m_errormsg);
}
}
}
}
if (pPlugin->GetStatus() == Plugin_Created)
{
unsigned char *pCodeHash = pPlugin->m_pRuntime->GetCodeHash();
char codeHashBuf[40];
UTIL_Format(codeHashBuf, 40, "plugin_");
for (int i = 0; i < 16; i++)
UTIL_Format(codeHashBuf + 7 + (i * 2), 3, "%02x", pCodeHash[i]);
const char *bulletinUrl = g_pGameConf->GetKeyValue(codeHashBuf);
if (bulletinUrl != NULL)
{
if (m_bBlockBadPlugins)
{
if (error)
{
if (bulletinUrl[0] != '\0')
{
UTIL_Format(error, maxlength, "Known malware detected and blocked. See %s for more info", bulletinUrl);
} else {
UTIL_Format(error, maxlength, "Possible malware or illegal plugin detected and blocked");
}
}
pPlugin->m_status = Plugin_BadLoad;
} else {
if (bulletinUrl[0] != '\0')
{
g_Logger.LogMessage("%s: Known malware detected. See %s for more info, blocking disabled in core.cfg", pPlugin->GetFilename(), bulletinUrl);
} else {
g_Logger.LogMessage("%s: Possible malware or illegal plugin detected, blocking disabled in core.cfg", pPlugin->GetFilename());
}
} }
} }
} }
LoadRes loadFailure = LoadRes_Failure;
/* Get the status */ /* Get the status */
if (pPlugin->GetStatus() == Plugin_Created) if (pPlugin->GetStatus() == Plugin_Created)
{ {
/* First native pass - add anything from Core */ /* First native pass - add anything from Core */
g_ShareSys.BindNativesToPlugin(pPlugin, true); g_ShareSys.BindNativesToPlugin(pPlugin, true);
pPlugin->InitIdentity(); pPlugin->InitIdentity();
APLRes result = pPlugin->Call_AskPluginLoad(error, maxlength); if (pPlugin->Call_AskPluginLoad(error, maxlength))
switch (result)
{ {
case APLRes_Success:
/* Autoload any modules */ /* Autoload any modules */
LoadOrRequireExtensions(pPlugin, 1, error, maxlength); LoadOrRequireExtensions(pPlugin, 1, error, maxlength);
break; }
case APLRes_Failure: else
{
pPlugin->SetErrorState(Plugin_Failed, "%s", error); pPlugin->SetErrorState(Plugin_Failed, "%s", error);
loadFailure = LoadRes_Failure;
break;
case APLRes_SilentFailure:
pPlugin->SetErrorState(Plugin_Failed, "%s", error);
loadFailure = LoadRes_SilentFailure;
pPlugin->SetSilentlyFailed(true);
break;
default:
assert(false);
} }
} }
@@ -1105,7 +1030,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool de
*_plugin = pPlugin; *_plugin = pPlugin;
} }
return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : loadFailure; return (pPlugin->GetStatus() == Plugin_Loaded) ? LoadRes_Successful : LoadRes_Failure;
} }
IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t maxlength, bool *wasloaded) IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t maxlength, bool *wasloaded)
@@ -1128,16 +1053,13 @@ IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType typ
if (res == LoadRes_NeverLoad) if (res == LoadRes_NeverLoad)
{ {
if (error) if (m_LoadingLocked)
{ {
if (m_LoadingLocked) UTIL_Format(error, maxlength, "There is a global plugin loading lock in effect");
{ }
UTIL_Format(error, maxlength, "There is a global plugin loading lock in effect"); else
} {
else UTIL_Format(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
{
UTIL_Format(error, maxlength, "This plugin is blocked from loading (see plugin_settings.cfg)");
}
} }
return NULL; return NULL;
} }
@@ -1166,14 +1088,14 @@ void CPluginManager::LoadAutoPlugin(const char *plugin)
if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure) if ((res=_LoadPlugin(&pl, plugin, false, PluginType_MapUpdated, error, sizeof(error))) == LoadRes_Failure)
{ {
g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s.", plugin, error); g_Logger.LogError("[SM] Failed to load plugin \"%s\": %s", plugin, error);
pl->SetErrorState( pl->SetErrorState(
pl->GetStatus() <= Plugin_Created ? Plugin_BadLoad : pl->GetStatus(), pl->GetStatus() == Plugin_BadLoad ? Plugin_BadLoad : Plugin_Failed,
"%s", "%s",
error); error);
} }
if (res == LoadRes_Successful || res == LoadRes_Failure || res == LoadRes_SilentFailure) if (res == LoadRes_Successful || res == LoadRes_Failure)
{ {
AddPlugin(pl); AddPlugin(pl);
} }
@@ -1267,7 +1189,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
{ {
if (error) if (error)
{ {
UTIL_Format(error, maxlength, "Fatal error during initializing plugin load"); snprintf(error, maxlength, "Fatal error during initializing plugin load");
} }
return false; return false;
} }
@@ -1300,7 +1222,7 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size
{ {
if (error) if (error)
{ {
UTIL_Format(error, maxlength, "Could not find required plugin \"%s\"", name); snprintf(error, maxlength, "Could not find required plugin \"%s\"", name);
} }
return false; return false;
} }
@@ -1351,8 +1273,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
if (ext->autoload) if (ext->autoload)
{ {
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file); g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s", file);
bool bErrorOnMissing = ext->required ? true : false; g_Extensions.LoadAutoExtension(path);
g_Extensions.LoadAutoExtension(path, bErrorOnMissing);
} }
} }
else if (pass == 2) else if (pass == 2)
@@ -1372,7 +1293,7 @@ bool CPluginManager::LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass
{ {
if (error) if (error)
{ {
UTIL_Format(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file); snprintf(error, maxlength, "Required extension \"%s\" file(\"%s\") not running", name, file);
} }
return false; return false;
} }
@@ -1440,7 +1361,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
{ {
if (error) if (error)
{ {
UTIL_Format(error, maxlength, "Native \"%s\" was not found", native->name); snprintf(error, maxlength, "Native \"%s\" was not found", native->name);
} }
return false; return false;
} }
@@ -1495,7 +1416,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng
s_iter != pPlugin->m_Libraries.end(); s_iter != pPlugin->m_Libraries.end();
s_iter++) s_iter++)
{ {
OnLibraryAction((*s_iter).c_str(), LibraryAction_Added); OnLibraryAction((*s_iter).c_str(), true, false);
} }
/* :TODO: optimize? does this even matter? */ /* :TODO: optimize? does this even matter? */
@@ -1547,9 +1468,7 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin)
{ {
break; break;
} }
if (native->status == SP_NATIVE_UNBOUND if (native->status == SP_NATIVE_UNBOUND && !(native->flags & SP_NTVFLAG_OPTIONAL))
&& native->name[0] != '@'
&& !(native->flags & SP_NTVFLAG_OPTIONAL))
{ {
pPlugin->SetErrorState(Plugin_Error, "Native not found: %s", native->name); pPlugin->SetErrorState(Plugin_Error, "Native not found: %s", native->name);
return; return;
@@ -1597,7 +1516,7 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
s_iter != pPlugin->m_Libraries.end(); s_iter != pPlugin->m_Libraries.end();
s_iter++) s_iter++)
{ {
OnLibraryAction((*s_iter).c_str(), LibraryAction_Removed); OnLibraryAction((*s_iter).c_str(), true, true);
} }
List<IPluginsListener *>::iterator iter; List<IPluginsListener *>::iterator iter;
@@ -1605,15 +1524,14 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
if (pPlugin->GetStatus() <= Plugin_Error) if (pPlugin->GetStatus() <= Plugin_Error)
{ {
/* Notify plugin */
pPlugin->Call_OnPluginEnd();
/* Notify listeners of unloading */ /* Notify listeners of unloading */
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++) for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)
{ {
pListener = (*iter); pListener = (*iter);
pListener->OnPluginUnloaded(pPlugin); pListener->OnPluginUnloaded(pPlugin);
} }
/* Notify plugin */
pPlugin->Call_OnPluginEnd();
} }
pPlugin->DropEverything(); pPlugin->DropEverything();
@@ -1914,9 +1832,6 @@ void CPluginManager::OnSourceModAllInitialized()
g_RootMenu.AddRootConsoleCommand("plugins", "Manage Plugins", this); g_RootMenu.AddRootConsoleCommand("plugins", "Manage Plugins", this);
g_ShareSys.AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
m_pOnLibraryAdded = g_Forwards.CreateForward("OnLibraryAdded", ET_Ignore, 1, NULL, Param_String);
m_pOnLibraryRemoved = g_Forwards.CreateForward("OnLibraryRemoved", ET_Ignore, 1, NULL, Param_String);
} }
void CPluginManager::OnSourceModShutdown() void CPluginManager::OnSourceModShutdown()
@@ -1928,30 +1843,6 @@ void CPluginManager::OnSourceModShutdown()
g_HandleSys.RemoveType(g_PluginType, m_MyIdent); g_HandleSys.RemoveType(g_PluginType, m_MyIdent);
g_ShareSys.DestroyIdentType(g_PluginIdent); g_ShareSys.DestroyIdentType(g_PluginIdent);
g_ShareSys.DestroyIdentity(m_MyIdent); g_ShareSys.DestroyIdentity(m_MyIdent);
g_Forwards.ReleaseForward(m_pOnLibraryAdded);
g_Forwards.ReleaseForward(m_pOnLibraryRemoved);
}
ConfigResult CPluginManager::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{
if (strcmp(key, "BlockBadPlugins") == 0) {
if (strcasecmp(value, "yes") == 0)
{
m_bBlockBadPlugins = true;
} else if (strcasecmp(value, "no") == 0) {
m_bBlockBadPlugins = false;
} else {
UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\"");
return ConfigResult_Reject;
}
return ConfigResult_Accept;
}
return ConfigResult_Ignore;
} }
void CPluginManager::OnHandleDestroy(HandleType_t type, void *object) void CPluginManager::OnHandleDestroy(HandleType_t type, void *object)
@@ -2060,7 +1951,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
assert(pl->GetStatus() != Plugin_Created); assert(pl->GetStatus() != Plugin_Created);
int len = 0; int len = 0;
const sm_plugininfo_t *info = pl->GetPublicInfo(); const sm_plugininfo_t *info = pl->GetPublicInfo();
if (pl->GetStatus() != Plugin_Running && !pl->IsSilentlyFailed()) if (pl->GetStatus() != Plugin_Running)
{ {
len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetStatus())); len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetStatus()));
@@ -2076,8 +1967,6 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
} }
if (pl->GetStatus() < Plugin_Created) if (pl->GetStatus() < Plugin_Created)
{ {
if (pl->IsSilentlyFailed())
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " Disabled:");
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename()); len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
if (IS_STR_FILLED(info->version)) if (IS_STR_FILLED(info->version))
{ {
@@ -2126,7 +2015,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
char pluginfile[256]; char pluginfile[256];
const char *ext = g_LibSys.GetFileExtension(filename) ? "" : ".smx"; const char *ext = g_LibSys.GetFileExtension(filename) ? "" : ".smx";
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", filename, ext); UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", filename, ext);
IPlugin *pl = LoadPlugin(pluginfile, false, PluginType_MapUpdated, error, sizeof(error), &wasloaded); IPlugin *pl = LoadPlugin(pluginfile, false, PluginType_MapUpdated, error, sizeof(error), &wasloaded);
@@ -2173,7 +2062,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
{ {
char pluginfile[256]; char pluginfile[256];
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx"; const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext); UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl)) if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
{ {
@@ -2263,7 +2152,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
{ {
char pluginfile[256]; char pluginfile[256];
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx"; const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext); UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl)) if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
{ {
@@ -2334,15 +2223,6 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
{ {
g_RootMenu.ConsolePrint(" Timestamp: %s", pl->m_DateTime); g_RootMenu.ConsolePrint(" Timestamp: %s", pl->m_DateTime);
} }
unsigned char *pCodeHash = pl->m_pRuntime->GetCodeHash();
unsigned char *pDataHash = pl->m_pRuntime->GetDataHash();
char combinedHash[33];
for (int i = 0; i < 16; i++)
UTIL_Format(combinedHash + (i * 2), 3, "%02x", pCodeHash[i] ^ pDataHash[i]);
g_RootMenu.ConsolePrint(" Hash: %s", combinedHash);
} }
else else
{ {
@@ -2393,7 +2273,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
{ {
char pluginfile[256]; char pluginfile[256];
const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx"; const char *ext = g_LibSys.GetFileExtension(arg) ? "" : ".smx";
g_SourceMod.BuildPath(Path_None, pluginfile, sizeof(pluginfile), "%s%s", arg, ext); UTIL_Format(pluginfile, sizeof(pluginfile), "%s%s", arg, ext);
if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl)) if (!sm_trie_retrieve(m_LoadLookup, pluginfile, (void **)&pl))
{ {
@@ -2404,10 +2284,7 @@ void CPluginManager::OnRootConsoleCommand(const char *cmdname, const CCommand &c
char name[PLATFORM_MAX_PATH]; char name[PLATFORM_MAX_PATH];
const sm_plugininfo_t *info = pl->GetPublicInfo(); const sm_plugininfo_t *info = pl->GetPublicInfo();
if (pl->GetStatus() <= Plugin_Paused) strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
else
strcpy(name, pl->GetFilename());
if (ReloadPlugin(pl)) if (ReloadPlugin(pl))
{ {
@@ -2557,18 +2434,83 @@ CPlugin *CPluginManager::GetPluginFromIdentity(IdentityToken_t *pToken)
return (CPlugin *)(pToken->ptr); return (CPlugin *)(pToken->ptr);
} }
void CPluginManager::OnLibraryAction(const char *lib, LibraryAction action) void CPluginManager::OnLibraryAction(const char *lib, bool is_a_plugin, bool drop)
{ {
switch (action) List<CPlugin *>::iterator iter;
struct _pl
{ {
case LibraryAction_Removed: cell_t name;
m_pOnLibraryRemoved->PushString(lib); cell_t file;
m_pOnLibraryRemoved->Execute(NULL); cell_t required;
break; } *plc;
case LibraryAction_Added:
m_pOnLibraryAdded->PushString(lib); struct _ext
m_pOnLibraryAdded->Execute(NULL); {
break; cell_t name;
cell_t file;
cell_t autoload;
cell_t required;
} *ext;
const char *name = drop ? "OnLibraryRemoved" : "OnLibraryAdded";
for (iter=m_plugins.begin();
iter!=m_plugins.end();
iter++)
{
CPlugin *pl = (*iter);
if (pl->GetStatus() != Plugin_Running)
{
continue;
}
IPluginContext *pContext = pl->GetBaseContext();
IPluginFunction *pf = pContext->GetFunctionByName(name);
if (!pf)
{
continue;
}
uint32_t num_vars = pContext->GetPubVarsNum();
for (uint32_t i=0; i<num_vars; i++)
{
sp_pubvar_t *pubvar;
if (pContext->GetPubvarByIndex(i, &pubvar) != SP_ERROR_NONE)
{
continue;
}
if (is_a_plugin && strncmp(pubvar->name, "__pl_", 5) == 0)
{
plc = (_pl *)pubvar->offs;
if (plc->required)
{
continue;
}
char *str;
pContext->LocalToString(plc->name, &str);
if (strcmp(str, lib) != 0)
{
continue;
}
pf->PushString(lib);
pf->Execute(NULL);
}
else if (!is_a_plugin && strncmp(pubvar->name, "__ext_", 6) == 0)
{
ext = (_ext *)pubvar->offs;
if (ext->required)
{
continue;
}
char *str;
pContext->LocalToString(ext->name, &str);
if (strcmp(str, lib) != 0)
{
continue;
}
pf->PushString(lib);
pf->Execute(NULL);
}
}
} }
} }
@@ -2759,6 +2701,6 @@ void CPluginManager::ListPluginsToClient(CPlayer *player, const CCommand &args)
/* Do we actually have more plugins? */ /* Do we actually have more plugins? */
if (iter != m_plugins.end()) if (iter != m_plugins.end())
{ {
ClientConsolePrint(e, "To see more, type \"sm plugins %d\"", id); ClientConsolePrint(e, "To see more, type \"sm plugins %d\"", id + 1);
} }
} }
+6 -35
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -47,17 +47,14 @@
#include "sm_trie.h" #include "sm_trie.h"
#include "sourcemod.h" #include "sourcemod.h"
#include <IRootConsoleMenu.h> #include <IRootConsoleMenu.h>
#if SOURCE_ENGINE >= SE_ALIENSWARM #if SOURCE_ENGINE == SE_LEFT4DEAD
#include "convar_sm_swarm.h"
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
#include "convar_sm_l4d.h" #include "convar_sm_l4d.h"
#elif SOURCE_ENGINE >= SE_ORANGEBOX #elif (SOURCE_ENGINE == SE_ORANGEBOX) || (SOURCE_ENGINE == SE_ORANGEBOXVALVE)
#include "convar_sm_ob.h" #include "convar_sm_ob.h"
#else #else
#include "convar_sm.h" #include "convar_sm.h"
#endif #endif
#include "ITranslator.h" #include "ITranslator.h"
#include "IGameConfigs.h"
#include "NativeOwner.h" #include "NativeOwner.h"
#include "ShareSys.h" #include "ShareSys.h"
@@ -120,23 +117,9 @@ enum LoadRes
LoadRes_Successful, LoadRes_Successful,
LoadRes_AlreadyLoaded, LoadRes_AlreadyLoaded,
LoadRes_Failure, LoadRes_Failure,
LoadRes_SilentFailure,
LoadRes_NeverLoad LoadRes_NeverLoad
}; };
enum APLRes
{
APLRes_Success,
APLRes_Failure,
APLRes_SilentFailure
};
enum LibraryAction
{
LibraryAction_Removed,
LibraryAction_Added
};
struct AutoConfig struct AutoConfig
{ {
String autocfg; String autocfg;
@@ -163,8 +146,6 @@ public:
const char *GetFilename(); const char *GetFilename();
bool IsDebugging(); bool IsDebugging();
PluginStatus GetStatus(); PluginStatus GetStatus();
bool IsSilentlyFailed();
void SetSilentlyFailed(bool sf);
const sm_plugininfo_t *GetPublicInfo(); const sm_plugininfo_t *GetPublicInfo();
bool SetPauseState(bool paused); bool SetPauseState(bool paused);
unsigned int GetSerial(); unsigned int GetSerial();
@@ -202,7 +183,7 @@ public:
* *
* If the error buffer is NULL, the error message is cached locally. * If the error buffer is NULL, the error message is cached locally.
*/ */
APLRes Call_AskPluginLoad(char *error, size_t maxlength); bool Call_AskPluginLoad(char *error, size_t maxlength);
/** /**
* Calls the OnPluginStart function. * Calls the OnPluginStart function.
@@ -256,7 +237,7 @@ public:
{ {
m_Libraries.push_back(name); m_Libraries.push_back(name);
} }
void LibraryActions(LibraryAction action); void LibraryActions(bool dropping);
void SyncMaxClients(int max_clients); void SyncMaxClients(int max_clients);
protected: protected:
bool UpdateInfo(); bool UpdateInfo();
@@ -266,7 +247,6 @@ private:
PluginType m_type; PluginType m_type;
char m_filename[PLATFORM_MAX_PATH]; char m_filename[PLATFORM_MAX_PATH];
PluginStatus m_status; PluginStatus m_status;
bool m_bSilentlyFailed;
unsigned int m_serial; unsigned int m_serial;
sm_plugininfo_t m_info; sm_plugininfo_t m_info;
char m_errormsg[256]; char m_errormsg[256];
@@ -333,7 +313,6 @@ public: //IPluginManager
public: //SMGlobalClass public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
ConfigResult OnSourceModConfigChanged(const char *key, const char *value, ConfigSource source, char *error, size_t maxlength);
void OnSourceModMaxPlayersChanged(int newvalue); void OnSourceModMaxPlayersChanged(int newvalue);
public: //IHandleTypeDispatch public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object); void OnHandleDestroy(HandleType_t type, void *object);
@@ -409,7 +388,7 @@ public:
void Shutdown(); void Shutdown();
void OnLibraryAction(const char *lib, LibraryAction action); void OnLibraryAction(const char *lib, bool is_a_plugin, bool drop);
bool LibraryExists(const char *lib); bool LibraryExists(const char *lib);
@@ -478,16 +457,8 @@ private:
List<FakeNative *> m_Natives; List<FakeNative *> m_Natives;
bool m_LoadingLocked; bool m_LoadingLocked;
// Config
bool m_bBlockBadPlugins;
// Forwards
IForward *m_pOnLibraryAdded;
IForward *m_pOnLibraryRemoved;
}; };
extern CPluginManager g_PluginSys; extern CPluginManager g_PluginSys;
#endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_ #endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
+20 -51
View File
@@ -30,13 +30,13 @@
*/ */
#include "Profiler.h" #include "Profiler.h"
#include <ISourceMod.h> #include "PluginSys.h"
#include "sm_stringutil.h"
#include "Logger.h"
#if defined PLATFORM_POSIX #if defined PLATFORM_POSIX
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#endif #endif
#include <IPluginSys.h>
#include "stringutil.h"
ProfileEngine g_Profiler; ProfileEngine g_Profiler;
IProfiler *sm_profiler = &g_Profiler; IProfiler *sm_profiler = &g_Profiler;
@@ -314,74 +314,43 @@ void ProfileEngine::Clear()
void ProfileEngine::OnSourceModAllInitialized() void ProfileEngine::OnSourceModAllInitialized()
{ {
rootmenu->AddRootConsoleCommand2("profiler", "Profiler commands", this); g_RootMenu.AddRootConsoleCommand("profiler", "Profiler commands", this);
} }
void ProfileEngine::OnSourceModShutdown() void ProfileEngine::OnSourceModShutdown()
{ {
rootmenu->RemoveRootConsoleCommand("profiler", this); g_RootMenu.RemoveRootConsoleCommand("profiler", this);
} }
void ProfileEngine::OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command) void ProfileEngine::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
{ {
if (command->ArgC() >= 3) if (command.ArgC() >= 3)
{ {
if (strcmp(command->Arg(2), "flush") == 0) if (strcmp(command.Arg(2), "flush") == 0)
{ {
FILE *fp; FILE *fp;
char path[256]; char path[256];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL)); g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
if ((fp = fopen(path, "wt")) == NULL) if ((fp = fopen(path, "wt")) == NULL)
{ {
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path); g_RootMenu.ConsolePrint("Failed, could not open file for writing: %s", path);
return; return;
} }
GenerateReport(fp); GenerateReport(fp);
fclose(fp); fclose(fp);
Clear();
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path); g_RootMenu.ConsolePrint("Profiler report generated as: %s\n", path);
return; return;
} }
else if (strcmp(command->Arg(2), "report") == 0)
{
FILE *fp;
char path[256];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "logs/profile_%d.xml", (int)time(NULL));
if ((fp = fopen(path, "wt")) == NULL)
{
rootmenu->ConsolePrint("Failed, could not open file for writing: %s", path);
return;
}
GenerateReport(fp);
fclose(fp);
rootmenu->ConsolePrint("Profiler report generated as: %s\n", path);
return;
}
else if (strcmp(command->Arg(2), "clear") == 0)
{
Clear();
rootmenu->ConsolePrint("Profiler statistics cleared.\n");
return;
}
} }
rootmenu->ConsolePrint("Profiler commands:"); g_RootMenu.ConsolePrint("Profiler commands:");
rootmenu->DrawGenericOption("flush", "Flushes statistics to disk and starts over"); g_RootMenu.DrawGenericOption("flush", "Flushes statistics to disk and starts over");
rootmenu->DrawGenericOption("report", "Flushes statistics to disk");
rootmenu->DrawGenericOption("clear", "Clears statistics");
} }
bool ProfileEngine::GenerateReport(FILE *fp) bool ProfileEngine::GenerateReport(FILE *fp)
@@ -419,8 +388,8 @@ void ProfileEngine::WriteReport(FILE *fp, ProfileReport *report, const char *nam
ar = report->GetReport(i); ar = report->GetReport(i);
strncopy(new_name, ar->atom_name, sizeof(new_name)); strncopy(new_name, ar->atom_name, sizeof(new_name));
UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "&lt;", true); UTIL_ReplaceAll(new_name, sizeof(new_name), "<", "&lt;");
UTIL_ReplaceAll(new_name, sizeof(new_name), ">", "&gt;", true); UTIL_ReplaceAll(new_name, sizeof(new_name), ">", "&gt;");
fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n", fprintf(fp, " <item name=\"%s\" numcalls=\"%d\" mintime=\"%f\" maxtime=\"%f\" totaltime=\"%f\"/>\n",
new_name, new_name,
@@ -469,20 +438,20 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
if (atom.atom_type == SP_PROF_NATIVES) if (atom.atom_type == SP_PROF_NATIVES)
{ {
smcore.strncopy(full_name, atom.name, sizeof(full_name)); strncopy(full_name, atom.name, sizeof(full_name));
} }
else else
{ {
IPlugin *pl; CPlugin *pl;
const char *file; const char *file;
file = "unknown"; file = "unknown";
if ((pl = pluginsys->FindPluginByContext(atom.ctx)) != NULL) if ((pl = g_PluginSys.GetPluginByCtx(atom.ctx)) != NULL)
{ {
file = pl->GetFilename(); file = pl->GetFilename();
} }
smcore.Format(full_name, sizeof(full_name), "%s!%s", file, atom.name); UTIL_Format(full_name, sizeof(full_name), "%s!%s", file, atom.name);
} }
atom_time = CalcAtomTime(atom); atom_time = CalcAtomTime(atom);
@@ -491,7 +460,7 @@ void ProfileReport::SaveAtom(const prof_atom_t &atom)
{ {
report = new prof_atom_report_t; report = new prof_atom_report_t;
smcore.strncopy(report->atom_name, full_name, sizeof(report->atom_name)); strncopy(report->atom_name, full_name, sizeof(report->atom_name));
report->max_time = atom_time; report->max_time = atom_time;
report->min_time = atom_time; report->min_time = atom_time;
report->num_calls = 1; report->num_calls = 1;
+4 -4
View File
@@ -38,8 +38,8 @@
#include <sh_vector.h> #include <sh_vector.h>
#include <sh_stack.h> #include <sh_stack.h>
#include <stdio.h> #include <stdio.h>
#include "common_logic.h" #include "sm_globals.h"
#include <IRootConsoleMenu.h> #include "sm_srvcmds.h"
using namespace SourcePawn; using namespace SourcePawn;
using namespace SourceHook; using namespace SourceHook;
@@ -103,7 +103,7 @@ public: //SMGlobalClass
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
void OnSourceModShutdown(); void OnSourceModShutdown();
public: //IRootConsoleCommand public: //IRootConsoleCommand
void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command); void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
public: //IProfiler public: //IProfiler
void OnNativeBegin(IPluginContext *pContext, sp_native_t *native); void OnNativeBegin(IPluginContext *pContext, sp_native_t *native);
void OnNativeEnd() ; void OnNativeEnd() ;
@@ -126,6 +126,6 @@ private:
prof_point_t m_ProfStart; prof_point_t m_ProfStart;
}; };
extern IProfiler *sm_profiler; extern ProfileEngine g_Profiler;
#endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_ #endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_
-82
View File
@@ -527,85 +527,3 @@ NativeEntry *ShareSystem::AddFakeNative(IPluginFunction *pFunc, const char *name
return pEntry; return pEntry;
} }
void ShareSystem::AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name)
{
if (m_caps.retrieve(name) != NULL)
return;
Capability cap;
cap.ext = myself;
cap.provider = provider;
m_caps.insert(name, cap);
}
void ShareSystem::DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name)
{
Capability *pCap = m_caps.retrieve(name);
if (pCap == NULL)
return;
if (pCap->ext != myself || pCap->provider != provider)
return;
m_caps.remove(name);
}
FeatureStatus ShareSystem::TestFeature(IPluginRuntime *pRuntime, FeatureType feature,
const char *name)
{
switch (feature)
{
case FeatureType_Native:
return TestNative(pRuntime, name);
case FeatureType_Capability:
return TestCap(name);
default:
break;
}
return FeatureStatus_Unknown;
}
FeatureStatus ShareSystem::TestNative(IPluginRuntime *pRuntime, const char *name)
{
uint32_t index;
if (pRuntime->FindNativeByName(name, &index) == SP_ERROR_NONE)
{
sp_native_t *native;
if (pRuntime->GetNativeByIndex(index, &native) == SP_ERROR_NONE)
{
if (native->status == SP_NATIVE_BOUND)
return FeatureStatus_Available;
else
return FeatureStatus_Unknown;
}
}
NativeEntry *entry = FindNative(name);
if (entry == NULL)
return FeatureStatus_Unknown;
if ((entry->replacement.owner != NULL || entry->owner != NULL) &&
(entry->replacement.func != NULL || entry->func != NULL))
{
return FeatureStatus_Available;
}
else
{
return FeatureStatus_Unavailable;
}
}
FeatureStatus ShareSystem::TestCap(const char *name)
{
Capability *cap = m_caps.retrieve(name);
if (cap == NULL)
return FeatureStatus_Unknown;
return cap->provider->GetFeatureStatus(FeatureType_Capability, name);
}
+1 -15
View File
@@ -87,13 +87,7 @@ struct NativeEntry
FakeNative *fake; FakeNative *fake;
}; };
struct Capability class ShareSystem :
{
IExtension *ext;
IFeatureProvider *provider;
};
class ShareSystem :
public IShareSys, public IShareSys,
public SMGlobalClass, public SMGlobalClass,
public IHandleTypeDispatch public IHandleTypeDispatch
@@ -116,10 +110,6 @@ public: //IShareSys
void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload); void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload);
void RegisterLibrary(IExtension *myself, const char *name); void RegisterLibrary(IExtension *myself, const char *name);
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives); void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
void AddCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name);
void DropCapabilityProvider(IExtension *myself, IFeatureProvider *provider,
const char *name);
public: //SMGlobalClass public: //SMGlobalClass
/* Pre-empt in case anything tries to register idents early */ /* Pre-empt in case anything tries to register idents early */
void Initialize(); void Initialize();
@@ -129,9 +119,6 @@ public: //IHandleTypeDispatch
public: public:
IdentityToken_t *CreateCoreIdentity(); IdentityToken_t *CreateCoreIdentity();
void RemoveInterfaces(IExtension *pExtension); void RemoveInterfaces(IExtension *pExtension);
FeatureStatus TestFeature(IPluginRuntime *pRuntime, FeatureType feature, const char *name);
FeatureStatus TestNative(IPluginRuntime *pRuntime, const char *name);
FeatureStatus TestCap(const char *name);
public: public:
inline IdentityToken_t *GetIdentRoot() inline IdentityToken_t *GetIdentRoot()
{ {
@@ -156,7 +143,6 @@ private:
HandleType_t m_IfaceType; HandleType_t m_IfaceType;
IdentityType_t m_CoreType; IdentityType_t m_CoreType;
KTrie<NativeEntry *> m_NtvCache; KTrie<NativeEntry *> m_NtvCache;
KTrie<Capability> m_caps;
}; };
extern ShareSystem g_ShareSys; extern ShareSystem g_ShareSys;
@@ -36,7 +36,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include "TextParsers.h" #include "TextParsers.h"
#include <ILibrarySys.h> #include "ShareSys.h"
#include "sm_stringutil.h"
#include "LibrarySys.h"
TextParsers g_TextParser; TextParsers g_TextParser;
ITextParsers *textparsers = &g_TextParser; ITextParsers *textparsers = &g_TextParser;
@@ -69,7 +71,7 @@ TextParsers::TextParsers()
void TextParsers::OnSourceModAllInitialized() void TextParsers::OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
unsigned int TextParsers::GetUTF8CharBytes(const char *stream) unsigned int TextParsers::GetUTF8CharBytes(const char *stream)
@@ -133,8 +135,8 @@ SMCError TextParsers::ParseSMCFile(const char *file,
states->line = 0; states->line = 0;
states->col = 0; states->col = 0;
} }
libsys->GetPlatformError(error, sizeof(error)); g_LibSys.GetPlatformError(error, sizeof(error));
smcore.Format(buffer, maxsize, "File could not be opened: %s", error); UTIL_Format(buffer, maxsize, "File could not be opened: %s", error);
return SMCError_StreamOpen; return SMCError_StreamOpen;
} }
@@ -143,7 +145,7 @@ SMCError TextParsers::ParseSMCFile(const char *file,
fclose(fp); fclose(fp);
errstr = GetSMCErrorString(result); errstr = GetSMCErrorString(result);
smcore.Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error"); UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
return result; return result;
} }
@@ -194,7 +196,7 @@ SMCError TextParsers::ParseSMCStream(const char *stream,
result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states); result = ParseStream_SMC(&rs, RawStreamReader, smc_listener, states);
const char *errstr = GetSMCErrorString(result); const char *errstr = GetSMCErrorString(result);
smcore.Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error"); UTIL_Format(buffer, maxsize, "%s", errstr != NULL ? errstr : "Unknown error");
return result; return result;
} }
@@ -872,7 +874,7 @@ bool TextParsers::ParseFile_INI(const char *file, ITextListener_INI *ini_listene
ptr = save_ptr; ptr = save_ptr;
/* Lastly, strip ending whitespace off */ /* Lastly, strip ending whitespace off */
for (size_t i=len-1; i<len; i--) for (size_t i=len-1; i>=0 && i<len; i--)
{ {
if (g_ws_chartable[(unsigned char)ptr[i]]) if (g_ws_chartable[(unsigned char)ptr[i]])
{ {
@@ -33,7 +33,7 @@
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_ #define _INCLUDE_SOURCEMOD_TEXTPARSERS_H_
#include <ITextParsers.h> #include <ITextParsers.h>
#include "common_logic.h" #include "sm_globals.h"
using namespace SourceMod; using namespace SourceMod;
@@ -1,8 +1,8 @@
/** /**
* vim: set ts=4 sw=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -28,9 +28,10 @@
* *
* Version: $Id$ * Version: $Id$
*/ */
#include <sm_platform.h>
#include "ThreadSupport.h" #include "ThreadSupport.h"
#include "common_logic.h" #include "sm_globals.h"
#include "ShareSys.h"
#if defined PLATFORM_POSIX #if defined PLATFORM_POSIX
#include "thread/PosixThreads.h" #include "thread/PosixThreads.h"
@@ -46,7 +47,6 @@ class RegThreadStuff : public SMGlobalClass
public: public:
void OnSourceModAllInitialized() void OnSourceModAllInitialized()
{ {
sharesys->AddInterface(NULL, g_pThreader); g_ShareSys.AddInterface(NULL, g_pThreader);
} }
} s_RegThreadStuff; } s_RegThreadStuff;
+1 -1
View File
@@ -78,11 +78,11 @@ public: //ITimerSystem
float GetTickedTime(); float GetTickedTime();
void NotifyOfGameStart(float offset /* = 0.0f */); void NotifyOfGameStart(float offset /* = 0.0f */);
bool GetMapTimeLeft(float *pTime); bool GetMapTimeLeft(float *pTime);
IMapTimer *GetMapTimer();
public: public:
void RunFrame(); void RunFrame();
void RemoveMapChangeTimers(); void RemoveMapChangeTimers();
void GameFrame(bool simulating); void GameFrame(bool simulating);
IMapTimer *GetMapTimer();
private: private:
List<ITimer *> m_SingleTimers; List<ITimer *> m_SingleTimers;
List<ITimer *> m_LoopTimers; List<ITimer *> m_LoopTimers;
+121 -109
View File
@@ -29,24 +29,22 @@
* Version: $Id$ * Version: $Id$
*/ */
#include "common_logic.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <sm_platform.h>
#include "Translator.h" #include "Translator.h"
#include <IPlayerHelpers.h> #include "Logger.h"
#include <ISourceMod.h> #include "LibrarySys.h"
#include <ILibrarySys.h> #include "sm_stringutil.h"
#include "sourcemod.h"
#include "PlayerManager.h"
#include "PhraseCollection.h" #include "PhraseCollection.h"
#include "stringutil.h" #include "ShareSys.h"
Translator g_Translator; Translator g_Translator;
IPhraseCollection *g_pCorePhrases = NULL; IPhraseCollection *g_pCorePhrases = NULL;
unsigned int g_pCorePhraseID = 0; unsigned int g_pCorePhraseID = 0;
using namespace SourceMod;
struct trans_t struct trans_t
{ {
int stridx; int stridx;
@@ -69,10 +67,15 @@ CPhraseFile::CPhraseFile(Translator *pTranslator, const char *file)
m_LangCount = pTranslator->GetLanguageCount(); m_LangCount = pTranslator->GetLanguageCount();
m_File.assign(file); m_File.assign(file);
m_pTranslator = pTranslator; m_pTranslator = pTranslator;
m_pPhraseLookup = NULL;
} }
CPhraseFile::~CPhraseFile() CPhraseFile::~CPhraseFile()
{ {
if (m_pPhraseLookup)
{
sm_trie_destroy(m_pPhraseLookup);
}
} }
void CPhraseFile::ParseError(const char *message, ...) void CPhraseFile::ParseError(const char *message, ...)
@@ -96,16 +99,20 @@ void CPhraseFile::ParseWarning(const char *message, ...)
if (!m_FileLogged) if (!m_FileLogged)
{ {
smcore.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str()); g_Logger.LogError("[SM] Warning(s) encountered in translation file \"%s\"", m_File.c_str());
m_FileLogged = true; m_FileLogged = true;
} }
smcore.LogError("[SM] %s", buffer); g_Logger.LogError("[SM] %s", buffer);
} }
void CPhraseFile::ReparseFile() void CPhraseFile::ReparseFile()
{ {
m_PhraseLookup.clear(); if (m_pPhraseLookup)
{
sm_trie_destroy(m_pPhraseLookup);
}
m_pPhraseLookup = sm_trie_create();
m_LangCount = m_pTranslator->GetLanguageCount(); m_LangCount = m_pTranslator->GetLanguageCount();
@@ -116,19 +123,19 @@ void CPhraseFile::ReparseFile()
SMCError err; SMCError err;
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "translations/%s", m_File.c_str()); g_SourceMod.BuildPath(Path_SM, path, PLATFORM_MAX_PATH, "translations/%s", m_File.c_str());
//backwards compatibility shim //backwards compatibility shim
/* :HACKHACK: Change .cfg/.txt and vice versa for compatibility */ /* :HACKHACK: Change .cfg/.txt and vice versa for compatibility */
if (!libsys->PathExists(path)) if (!g_LibSys.PathExists(path))
{ {
if (m_File.compare("common.cfg") == 0) if (m_File.compare("common.cfg") == 0)
{ {
UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt", true); UTIL_ReplaceAll(path, sizeof(path), "common.cfg", "common.phrases.txt");
} else if (strstr(path, ".cfg")) { } else if (strstr(path, ".cfg")) {
UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt", true); UTIL_ReplaceAll(path, sizeof(path), ".cfg", ".txt");
} else if (strstr(path, ".txt")) { } else if (strstr(path, ".txt")) {
UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg", true); UTIL_ReplaceAll(path, sizeof(path), ".txt", ".cfg");
} }
} }
@@ -142,8 +149,8 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str(); msg = m_ParseError.c_str();
} }
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str()); g_Logger.LogError("[SM] Fatal error encountered parsing translation file \"%s\"", m_File.c_str());
smcore.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg); g_Logger.LogError("[SM] Error (line %d, column %d): %s", states.line, states.col, msg);
} }
const char *code; const char *code;
@@ -154,7 +161,7 @@ void CPhraseFile::ReparseFile()
continue; continue;
} }
g_pSM->BuildPath(Path_SM, g_SourceMod.BuildPath(Path_SM,
path, path,
PLATFORM_MAX_PATH, PLATFORM_MAX_PATH,
"translations/%s/%s", "translations/%s/%s",
@@ -162,7 +169,7 @@ void CPhraseFile::ReparseFile()
m_File.c_str()); m_File.c_str());
/* Speculatively load these. */ /* Speculatively load these. */
if (!libsys->PathExists(path)) if (!g_LibSys.PathExists(path))
{ {
continue; continue;
} }
@@ -175,10 +182,10 @@ void CPhraseFile::ReparseFile()
msg = m_ParseError.c_str(); msg = m_ParseError.c_str();
} }
smcore.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"", g_Logger.LogError("[SM] Fatal error encountered parsing translation file \"%s/%s\"",
code, code,
m_File.c_str()); m_File.c_str());
smcore.LogError("[SM] Error (line %d, column %d): %s", g_Logger.LogError("[SM] Error (line %d, column %d): %s",
states.line, states.line,
states.col, states.col,
msg); msg);
@@ -210,17 +217,17 @@ SMCResult CPhraseFile::ReadSMC_NewSection(const SMCStates *states, const char *n
m_ParseState = PPS_InPhrase; m_ParseState = PPS_InPhrase;
recognized = true; recognized = true;
int *pvalue; void *value;
if ((pvalue = m_PhraseLookup.retrieve(name)) != NULL) if (sm_trie_retrieve(m_pPhraseLookup, name, &value))
{ {
m_CurPhrase = *pvalue; m_CurPhrase = reinterpret_cast<int>(value);
} }
else else
{ {
phrase_t *pPhrase; phrase_t *pPhrase;
m_CurPhrase = m_pMemory->CreateMem(sizeof(phrase_t), (void **)&pPhrase); m_CurPhrase = m_pMemory->CreateMem(sizeof(phrase_t), (void **)&pPhrase);
m_PhraseLookup.insert(name, m_CurPhrase); sm_trie_insert(m_pPhraseLookup, name, reinterpret_cast<void *>(m_CurPhrase));
/* Initialize new phrase */ /* Initialize new phrase */
trans_t *pTrans; trans_t *pTrans;
@@ -479,6 +486,13 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
} }
else else
{ {
size_t len = strlen(key);
if (len < 2 || len > 3)
{
ParseWarning("Ignoring translation to invalid language \"%s\" on line %d.", key, states->line);
return SMCResult_Continue;
}
unsigned int lang; unsigned int lang;
if (!m_pTranslator->GetLanguageByCode(key, &lang)) if (!m_pTranslator->GetLanguageByCode(key, &lang))
{ {
@@ -491,7 +505,7 @@ SMCResult CPhraseFile::ReadSMC_KeyValue(const SMCStates *states, const char *key
/* See how many bytes we need for this string, then allocate. /* See how many bytes we need for this string, then allocate.
* NOTE: THIS SHOULD GUARANTEE THAT WE DO NOT NEED TO NEED TO SIZE CHECK * NOTE: THIS SHOULD GUARANTEE THAT WE DO NOT NEED TO NEED TO SIZE CHECK
*/ */
size_t len = strlen(value) + pPhrase->fmt_bytes + 1; len = strlen(value) + pPhrase->fmt_bytes + 1;
char *out_buf; char *out_buf;
int out_idx; int out_idx;
@@ -625,7 +639,9 @@ SMCResult CPhraseFile::ReadSMC_LeavingSection(const SMCStates *states)
if (m_ParseState == PPS_InPhrase) if (m_ParseState == PPS_InPhrase)
{ {
if (m_CurPhrase == -1 && m_LastPhraseString.size()) if (m_CurPhrase == -1 && m_LastPhraseString.size())
m_PhraseLookup.remove(m_LastPhraseString.c_str()); {
sm_trie_delete(m_pPhraseLookup, m_LastPhraseString.c_str());
}
m_CurPhrase = -1; m_CurPhrase = -1;
m_ParseState = PPS_Phrases; m_ParseState = PPS_Phrases;
m_LastPhraseString.assign(""); m_LastPhraseString.assign("");
@@ -642,7 +658,9 @@ void CPhraseFile::ReadSMC_ParseEnd(bool halted, bool failed)
{ {
/* Check to see if we have any dangling phrases that weren't completed, and scrap them */ /* Check to see if we have any dangling phrases that weren't completed, and scrap them */
if ((halted || failed) && m_LastPhraseString.size()) if ((halted || failed) && m_LastPhraseString.size())
m_PhraseLookup.remove(m_LastPhraseString.c_str()); {
sm_trie_delete(m_pPhraseLookup, m_LastPhraseString.c_str());
}
} }
TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_id, Translation *pTrans) TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_id, Translation *pTrans)
@@ -652,11 +670,13 @@ TransError CPhraseFile::GetTranslation(const char *szPhrase, unsigned int lang_i
return Trans_BadLanguage; return Trans_BadLanguage;
} }
int *pvalue; void *object;
if ((pvalue = m_PhraseLookup.retrieve(szPhrase)) == NULL) if (!sm_trie_retrieve(m_pPhraseLookup, szPhrase, &object))
{
return Trans_BadPhrase; return Trans_BadPhrase;
}
phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(*pvalue); phrase_t *pPhrase = (phrase_t *)m_pMemory->GetAddress(reinterpret_cast<int>(object));
trans_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl); trans_t *trans = (trans_t *)m_pMemory->GetAddress(pPhrase->trans_tbl);
trans = &trans[lang_id]; trans = &trans[lang_id];
@@ -685,6 +705,7 @@ const char *CPhraseFile::GetFilename()
Translator::Translator() : m_ServerLang(SOURCEMOD_LANGUAGE_ENGLISH) Translator::Translator() : m_ServerLang(SOURCEMOD_LANGUAGE_ENGLISH)
{ {
m_pStringTab = new BaseStringTable(2048); m_pStringTab = new BaseStringTable(2048);
m_pLCodeLookup = sm_trie_create();
strncopy(m_InitialLang, "en", sizeof(m_InitialLang)); strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
} }
@@ -700,6 +721,8 @@ Translator::~Translator()
delete m_Languages[i]; delete m_Languages[i];
} }
sm_trie_destroy(m_pLCodeLookup);
delete m_pStringTab; delete m_pStringTab;
} }
@@ -716,13 +739,13 @@ ConfigResult Translator::OnSourceModConfigChanged(const char *key,
unsigned int index; unsigned int index;
if (!GetLanguageByCode(value, &index)) if (!GetLanguageByCode(value, &index))
{ {
smcore.Format(error, maxlength, "Language code \"%s\" is not registered", value); UTIL_Format(error, maxlength, "Language code \"%s\" is not registered", value);
return ConfigResult_Reject; return ConfigResult_Reject;
} }
m_ServerLang = index; m_ServerLang = index;
} else { } else {
smcore.strncopy(m_InitialLang, value, sizeof(m_InitialLang)); strncopy(m_InitialLang, value, sizeof(m_InitialLang));
} }
return ConfigResult_Accept; return ConfigResult_Accept;
@@ -735,7 +758,7 @@ void Translator::OnSourceModLevelChange(const char *mapName)
{ {
/* Refresh language stuff */ /* Refresh language stuff */
char path[PLATFORM_MAX_PATH]; char path[PLATFORM_MAX_PATH];
g_pSM->BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg"); g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "configs/languages.cfg");
RebuildLanguageDatabase(path); RebuildLanguageDatabase(path);
} }
@@ -743,16 +766,10 @@ void Translator::OnSourceModAllInitialized()
{ {
AddLanguage("en", "English"); AddLanguage("en", "English");
const char* lang = smcore.GetCoreConfigValue("ServerLang");
if (lang)
{
strncpy(m_InitialLang, lang, sizeof(m_InitialLang));
}
g_pCorePhrases = CreatePhraseCollection(); g_pCorePhrases = CreatePhraseCollection();
g_pCorePhrases->AddPhraseFile("core.phrases"); g_pCorePhrases->AddPhraseFile("core.phrases");
sharesys->AddInterface(NULL, this); g_ShareSys.AddInterface(NULL, this);
} }
void Translator::OnSourceModShutdown() void Translator::OnSourceModShutdown()
@@ -762,38 +779,43 @@ void Translator::OnSourceModShutdown()
bool Translator::GetLanguageByCode(const char *code, unsigned int *index) bool Translator::GetLanguageByCode(const char *code, unsigned int *index)
{ {
unsigned int *pindex; void *_index;
if ((pindex = m_LCodeLookup.retrieve(code)) == NULL) if (!sm_trie_retrieve(m_pLCodeLookup, code, &_index))
{
return false; return false;
}
if (index) if (index)
*index = *pindex; {
*index = reinterpret_cast<unsigned int>(_index);
}
return true; return true;
} }
bool Translator::GetLanguageByName(const char *name, unsigned int *index) bool Translator::GetLanguageByName(const char *name, unsigned int *index)
{ {
char lower[256]; CVector<Language *>::iterator iter;
size_t len = strlen(name); unsigned int id = 0;
if (len > 255) len = 255;
for (size_t i = 0; i < len; i++) for (iter=m_Languages.begin(); iter!=m_Languages.end(); iter++, id++)
{ {
if (name[i] >= 'A' && name[i] <= 'Z') if (strcasecmp(m_pStringTab->GetString((*iter)->m_FullName), name) == 0)
lower[i] = tolower(name[i]); {
else break;
lower[i] = name[i]; }
} }
lower[len] = '\0';
unsigned int *pIndex; if (iter == m_Languages.end())
{
if ((pIndex = m_LAliases.retrieve(lower)) == NULL)
return false; return false;
}
if (index) if (index)
*index = *pIndex; {
*index = id;
}
return true; return true;
} }
@@ -831,8 +853,8 @@ unsigned int Translator::FindOrAddPhraseFile(const char *phrase_file)
void Translator::RebuildLanguageDatabase(const char *lang_header_file) void Translator::RebuildLanguageDatabase(const char *lang_header_file)
{ {
/* Erase everything we have */ /* Erase everything we have */
m_LCodeLookup.clear(); sm_trie_destroy(m_pLCodeLookup);
m_LAliases.clear(); m_pLCodeLookup = sm_trie_create();
m_pStringTab->Reset(); m_pStringTab->Reset();
for (size_t i=0; i<m_Languages.size(); i++) for (size_t i=0; i<m_Languages.size(); i++)
@@ -852,27 +874,25 @@ void Translator::RebuildLanguageDatabase(const char *lang_header_file)
str_err = m_CustomError.c_str(); str_err = m_CustomError.c_str();
} }
smcore.LogError("[SM] Failed to parse language header file: \"%s\"", lang_header_file); g_Logger.LogError("[SM] Failed to parse language header file: \"%s\"", lang_header_file);
smcore.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err); g_Logger.LogError("[SM] Parse error (line %d, column %d): %s", states.line, states.col, str_err);
} }
unsigned int *pServerLang; void *serverLang;
if ((pServerLang = m_LCodeLookup.retrieve(m_InitialLang)) == NULL) if (!sm_trie_retrieve(m_pLCodeLookup, m_InitialLang, &serverLang))
{ {
smcore.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang); g_Logger.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
smcore.strncopy(m_InitialLang, "en", sizeof(m_InitialLang)); strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH; m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
} }
else
{ m_ServerLang = reinterpret_cast<unsigned int>(serverLang);
m_ServerLang = *pServerLang;
}
if (!m_Languages.size()) if (!m_Languages.size())
{ {
smcore.LogError("[SM] Fatal error, no languages found! Translation will not work."); g_Logger.LogError("[SM] Fatal error, no languages found! Translation will not work.");
} }
for (size_t i=0; i<m_Files.size(); i++) for (size_t i=0; i<m_Files.size(); i++)
@@ -899,7 +919,7 @@ SMCResult Translator::ReadSMC_NewSection(const SMCStates *states, const char *na
if (!m_InLanguageSection) if (!m_InLanguageSection)
{ {
smcore.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name); g_Logger.LogError("[SM] Warning: Unrecognized section \"%s\" in languages.cfg", name);
} }
return SMCResult_Continue; return SMCResult_Continue;
@@ -914,6 +934,14 @@ SMCResult Translator::ReadSMC_LeavingSection(const SMCStates *states)
SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value) SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
{ {
size_t len = strlen(key);
if (len < 2 || len > 3)
{
g_Logger.LogError("[SM] Warning encountered parsing languages.cfg file.");
g_Logger.LogError("[SM] Invalid language code \"%s\" is being ignored.", key);
}
AddLanguage(key, value); AddLanguage(key, value);
return SMCResult_Continue; return SMCResult_Continue;
@@ -921,40 +949,20 @@ SMCResult Translator::ReadSMC_KeyValue(const SMCStates *states, const char *key,
bool Translator::AddLanguage(const char *langcode, const char *description) bool Translator::AddLanguage(const char *langcode, const char *description)
{ {
char lower[256]; if (sm_trie_retrieve(m_pLCodeLookup, langcode, NULL))
size_t len = strlen(description);
if (len > 255) len = 255;
for (size_t i = 0; i < len; i++)
{ {
if (description[i] >= 'A' && description[i] <= 'Z')
lower[i] = tolower(description[i]);
else
lower[i] = description[i];
}
lower[len] = '\0';
if (m_LAliases.retrieve(lower))
return false; return false;
unsigned int idx;
if (unsigned int *pIdx = m_LCodeLookup.retrieve(langcode))
{
idx = *pIdx;
} }
else
{
Language *pLanguage = new Language;
idx = m_Languages.size();
smcore.Format(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode); Language *pLanguage = new Language;
pLanguage->m_CanonicalName = m_pStringTab->AddString(lower); unsigned int idx = m_Languages.size();
m_LCodeLookup.insert(langcode, idx); UTIL_Format(pLanguage->m_code2, sizeof(pLanguage->m_code2), "%s", langcode);
pLanguage->m_FullName = m_pStringTab->AddString(description);
m_Languages.push_back(pLanguage); sm_trie_insert(m_pLCodeLookup, langcode, reinterpret_cast<void *>(idx));
}
m_Languages.push_back(pLanguage);
m_LAliases.insert(lower, idx);
return true; return true;
} }
@@ -976,7 +984,7 @@ unsigned int Translator::GetServerLanguage()
unsigned int Translator::GetClientLanguage(int client) unsigned int Translator::GetClientLanguage(int client)
{ {
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
return pPlayer->GetLanguageId(); return pPlayer->GetLanguageId();
} }
@@ -994,7 +1002,7 @@ bool Translator::GetLanguageInfo(unsigned int number, const char **code, const c
} }
if (name) if (name)
{ {
*name = m_pStringTab->GetString(l->m_CanonicalName); *name = m_pStringTab->GetString(l->m_FullName);
} }
return true; return true;
@@ -1017,16 +1025,20 @@ IPhraseCollection *Translator::CreatePhraseCollection()
int Translator::SetGlobalTarget(int index) int Translator::SetGlobalTarget(int index)
{ {
return g_pSM->SetGlobalTarget(index); return g_SourceMod.SetGlobalTarget(index);
} }
int Translator::GetGlobalTarget() const int Translator::GetGlobalTarget() const
{ {
return g_pSM->GetGlobalTarget(); return g_SourceMod.GetGlobalTarget();
} }
bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned int numparams, bool CoreTranslate(char *buffer,
size_t *pOutLength, ...) size_t maxlength,
const char *format,
unsigned int numparams,
size_t *pOutLength,
...)
{ {
va_list ap; va_list ap;
unsigned int i; unsigned int i;
@@ -1056,11 +1068,11 @@ bool CoreTranslate(char *buffer, size_t maxlength, const char *format, unsigned
{ {
if (fail_phrase != NULL) if (fail_phrase != NULL)
{ {
smcore.LogError("[SM] Could not find core phrase: %s", fail_phrase); g_Logger.LogError("[SM] Could not find core phrase: %s", fail_phrase);
} }
else else
{ {
smcore.LogError("[SM] Unknown fatal error while translating a core phrase."); g_Logger.LogError("[SM] Unknown fatal error while translating a core phrase.");
} }
return false; return false;
@@ -1081,7 +1093,7 @@ bool Translator::FormatString(char *buffer,
unsigned int arg; unsigned int arg;
arg = 0; arg = 0;
if (!smcore.gnprintf(buffer, maxlength, format, pPhrases, params, numparams, arg, pOutLength, pFailPhrase)) if (!gnprintf(buffer, maxlength, format, pPhrases, params, numparams, arg, pOutLength, pFailPhrase))
{ {
return false; return false;
} }
@@ -32,14 +32,17 @@
#ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_H_ #ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_H_
#define _INCLUDE_SOURCEMOD_TRANSLATOR_H_ #define _INCLUDE_SOURCEMOD_TRANSLATOR_H_
#include "common_logic.h" #include "sm_trie.h"
#include <sm_trie_tpl.h>
#include <sh_string.h> #include <sh_string.h>
#include <sh_vector.h> #include <sh_vector.h>
#include "sm_globals.h"
#include "sm_memtable.h" #include "sm_memtable.h"
#include "ITextParsers.h" #include "ITextParsers.h"
#include <ITranslator.h> #include <ITranslator.h>
#define MAX_TRANSLATE_PARAMS 32
#define CORELANG_ENGLISH 0
/* :TODO: write a templatized version of tries? */ /* :TODO: write a templatized version of tries? */
using namespace SourceHook; using namespace SourceHook;
@@ -55,7 +58,7 @@ enum PhraseParseState
struct Language struct Language
{ {
char m_code2[4]; char m_code2[4];
int m_CanonicalName; int m_FullName;
}; };
class CPhraseFile : class CPhraseFile :
@@ -79,7 +82,7 @@ private:
void ParseError(const char *message, ...); void ParseError(const char *message, ...);
void ParseWarning(const char *message, ...); void ParseWarning(const char *message, ...);
private: private:
KTrie<int> m_PhraseLookup; Trie *m_pPhraseLookup;
String m_File; String m_File;
Translator *m_pTranslator; Translator *m_pTranslator;
PhraseParseState m_ParseState; PhraseParseState m_ParseState;
@@ -119,6 +122,7 @@ public:
unsigned int FindOrAddPhraseFile(const char *phrase_file); unsigned int FindOrAddPhraseFile(const char *phrase_file);
BaseStringTable *GetStringTable(); BaseStringTable *GetStringTable();
unsigned int GetLanguageCount(); unsigned int GetLanguageCount();
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
bool GetLanguageByCode(const char *code, unsigned int *index); bool GetLanguageByCode(const char *code, unsigned int *index);
bool GetLanguageByName(const char *name, unsigned int *index); bool GetLanguageByName(const char *name, unsigned int *index);
CPhraseFile *GetFileByIndex(unsigned int index); CPhraseFile *GetFileByIndex(unsigned int index);
@@ -145,15 +149,13 @@ public: //ITranslator
unsigned int numparams, unsigned int numparams,
size_t *pOutLength, size_t *pOutLength,
const char **pFailPhrase); const char **pFailPhrase);
bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
private: private:
bool AddLanguage(const char *langcode, const char *description); bool AddLanguage(const char *langcode, const char *description);
private: private:
CVector<Language *> m_Languages; CVector<Language *> m_Languages;
CVector<CPhraseFile *> m_Files; CVector<CPhraseFile *> m_Files;
BaseStringTable *m_pStringTab; BaseStringTable *m_pStringTab;
KTrie<unsigned int> m_LCodeLookup; Trie *m_pLCodeLookup;
KTrie<unsigned int> m_LAliases;
bool m_InLanguageSection; bool m_InLanguageSection;
String m_CustomError; String m_CustomError;
unsigned int m_ServerLang; unsigned int m_ServerLang;
@@ -173,4 +175,3 @@ extern unsigned int g_pCorePhraseID;
extern Translator g_Translator; extern Translator g_Translator;
#endif //_INCLUDE_SOURCEMOD_TRANSLATOR_H_ #endif //_INCLUDE_SOURCEMOD_TRANSLATOR_H_
File diff suppressed because it is too large Load Diff
+37 -303
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -32,32 +32,18 @@
#include "UserMessages.h" #include "UserMessages.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#if SOURCE_ENGINE == SE_CSGO
#include <cstrike15_usermessage_helpers.h>
#endif
UserMessages g_UserMsgs; UserMessages g_UserMsgs;
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_LEFT4DEAD
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
#else
#if SOURCE_ENGINE >= SE_LEFT4DEAD
SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *); SH_DECL_HOOK3(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int, const char *);
#else #else
SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int); SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write *, IRecipientFilter *, int);
#endif #endif
SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0); SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0);
#endif // ==SE_CSGO
UserMessages::UserMessages() UserMessages::UserMessages() : m_InterceptBuffer(m_pBase, 2500)
#ifndef USE_PROTOBUF_USERMESSAGES
: m_InterceptBuffer(m_pBase, 2500)
{ {
m_Names = sm_trie_create(); m_Names = sm_trie_create();
#else
: m_InterceptBuffer(NULL)
{
#endif
m_HookCount = 0; m_HookCount = 0;
m_InExec = false; m_InExec = false;
m_InHook = false; m_InHook = false;
@@ -67,9 +53,7 @@ UserMessages::UserMessages()
UserMessages::~UserMessages() UserMessages::~UserMessages()
{ {
#ifndef USE_PROTOBUF_USERMESSAGES
sm_trie_destroy(m_Names); sm_trie_destroy(m_Names);
#endif
CStack<ListenerInfo *>::iterator iter; CStack<ListenerInfo *>::iterator iter;
for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++) for (iter=m_FreeListeners.begin(); iter!=m_FreeListeners.end(); iter++)
@@ -81,10 +65,8 @@ UserMessages::~UserMessages()
void UserMessages::OnSourceModStartup(bool late) void UserMessages::OnSourceModStartup(bool late)
{ {
#ifndef USE_PROTOBUF_USERMESSAGES
/* -1 means SourceMM was unable to get the user message list */ /* -1 means SourceMM was unable to get the user message list */
m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1); m_FallbackSearch = (g_SMAPI->GetUserMessageCount() == -1);
#endif
} }
void UserMessages::OnSourceModAllInitialized() void UserMessages::OnSourceModAllInitialized()
@@ -96,25 +78,16 @@ void UserMessages::OnSourceModAllShutdown()
{ {
if (m_HookCount) if (m_HookCount)
{ {
#if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false); 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, 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_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif
} }
m_HookCount = 0; m_HookCount = 0;
} }
int UserMessages::GetMessageIndex(const char *msg) int UserMessages::GetMessageIndex(const char *msg)
{ {
#if SOURCE_ENGINE == SE_CSGO
// Can split this per engine and/or game later
return g_Cstrike15UsermessageHelpers.GetIndex(msg);
#else
int msgid; int msgid;
if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid))) if (!sm_trie_retrieve(m_Names, msg, reinterpret_cast<void **>(&msgid)))
@@ -145,19 +118,10 @@ int UserMessages::GetMessageIndex(const char *msg)
} }
return msgid; return msgid;
#endif
} }
bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) const
{ {
#if SOURCE_ENGINE == SE_CSGO
const char *pszName = g_Cstrike15UsermessageHelpers.GetName(msgid);
if (!pszName)
return false;
strncopy(buffer, pszName, maxlength);
return true;
#else
if (m_FallbackSearch) if (m_FallbackSearch)
{ {
int size; int size;
@@ -173,14 +137,10 @@ bool UserMessages::GetMessageName(int msgid, char *buffer, size_t maxlength) con
} }
return false; return false;
#endif
} }
bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags) bf_write *UserMessages::StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES
return NULL;
#else
bf_write *buffer; bf_write *buffer;
if (m_InExec || m_InHook) if (m_InExec || m_InHook)
@@ -208,13 +168,13 @@ bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], u
if (m_CurFlags & USERMSG_BLOCKHOOKS) if (m_CurFlags & USERMSG_BLOCKHOOKS)
{ {
#if SOURCE_ENGINE >= SE_LEFT4DEAD #if SOURCE_ENGINE == SE_LEFT4DEAD
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id)); buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
#else #else
buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id); buffer = ENGINE_CALL(UserMessageBegin)(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
#endif #endif
} else { } else {
#if SOURCE_ENGINE >= SE_LEFT4DEAD #if SOURCE_ENGINE == SE_LEFT4DEAD
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id)); buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, g_SMAPI->GetUserMessage(msg_id));
#else #else
buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id); buffer = engine->UserMessageBegin(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id);
@@ -222,75 +182,6 @@ bf_write *UserMessages::StartBitBufMessage(int msg_id, const cell_t players[], u
} }
return buffer; return buffer;
#endif // USE_PROTOBUF_USERMESSAGES
}
google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags)
{
#ifndef USE_PROTOBUF_USERMESSAGES
return NULL;
#else
protobuf::Message *buffer;
if (m_InExec || m_InHook)
{
return NULL;
}
if (msg_id < 0 || msg_id >= 255)
{
return NULL;
}
m_CurId = msg_id;
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)
{
// direct message creation, return buffer "from engine". keep track
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
} else {
char messageName[32];
if (!GetMessageName(msg_id, messageName, sizeof(messageName)))
{
m_InExec = false;
return NULL;
}
protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
switch (m_FakeMetaRes)
{
case MRES_IGNORED:
case MRES_HANDLED:
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
break;
case MRES_OVERRIDE:
m_FakeEngineBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_id)->New();
// fallthrough
case MRES_SUPERCEDE:
buffer = msg;
break;
}
OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
}
return buffer;
#endif // USE_PROTOBUF_USERMESSAGES
} }
bool UserMessages::EndMessage() bool UserMessages::EndMessage()
@@ -300,37 +191,12 @@ bool UserMessages::EndMessage()
return false; return false;
} }
#if SOURCE_ENGINE == SE_CSGO
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
delete m_FakeEngineBuffer;
m_FakeEngineBuffer = NULL;
} else {
OnMessageEnd_Pre();
switch (m_FakeMetaRes)
{
case MRES_IGNORED:
case MRES_HANDLED:
case MRES_OVERRIDE:
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
delete m_FakeEngineBuffer;
m_FakeEngineBuffer = NULL;
break;
//case MRES_SUPERCEDE:
}
OnMessageEnd_Post();
}
#else
if (m_CurFlags & USERMSG_BLOCKHOOKS) if (m_CurFlags & USERMSG_BLOCKHOOKS)
{ {
ENGINE_CALL(MessageEnd)(); ENGINE_CALL(MessageEnd)();
} else { } else {
engine->MessageEnd(); engine->MessageEnd();
} }
#endif // SE_CSGO
m_InExec = false; m_InExec = false;
m_CurFlags = 0; m_CurFlags = 0;
@@ -339,60 +205,31 @@ bool UserMessages::EndMessage()
return true; return true;
} }
UserMessageType UserMessages::GetUserMessageType() const
{
#ifdef USE_PROTOBUF_USERMESSAGES
return UM_Protobuf;
#else
return UM_BitBuf;
#endif
}
bool UserMessages::HookUserMessage2(int msg_id, bool UserMessages::HookUserMessage2(int msg_id,
IUserMessageListener *pListener, IUserMessageListener *pListener,
bool intercept) bool intercept)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES return InternalHook(msg_id, pListener, intercept, true);
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
#else
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
#endif
} }
bool UserMessages::UnhookUserMessage2(int msg_id, bool UserMessages::UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener, IUserMessageListener *pListener,
bool intercept) bool intercept)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES return InternalUnhook(msg_id, pListener, intercept, true);
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, true);
#else
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, true);
#endif
} }
bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept) bool UserMessages::HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES return InternalHook(msg_id, pListener, intercept, false);
return InternalHook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
#else
return InternalHook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
#endif
} }
bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept) bool UserMessages::UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES return InternalUnhook(msg_id, pListener, intercept, false);
return InternalUnhook(msg_id, (IProtobufUserMessageListener *)pListener, intercept, false);
#else
return InternalUnhook(msg_id, (IBitBufUserMessageListener *)pListener, intercept, false);
#endif
} }
#ifdef USE_PROTOBUF_USERMESSAGES bool UserMessages::InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
bool UserMessages::InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
#else
bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
#endif
{ {
if (msg_id < 0 || msg_id >= 255) if (msg_id < 0 || msg_id >= 255)
{ {
@@ -415,15 +252,10 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
if (!m_HookCount++) if (!m_HookCount++)
{ {
#if SOURCE_ENGINE == SE_CSGO
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else
SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false); 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, 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_Pre, false);
SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true); SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif
} }
if (intercept) if (intercept)
@@ -436,11 +268,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
return true; return true;
} }
#ifdef USE_PROTOBUF_USERMESSAGES bool UserMessages::InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew)
bool UserMessages::InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew)
#else
bool UserMessages::InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew)
#endif
{ {
MsgList *pList; MsgList *pList;
MsgIter iter; MsgIter iter;
@@ -481,69 +309,14 @@ void UserMessages::_DecRefCounter()
{ {
if (--m_HookCount == 0) if (--m_HookCount == 0)
{ {
#if SOURCE_ENGINE == SE_CSGO
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, SendUserMessage, engine, this, &UserMessages::OnSendUserMessage_Post, true);
#else
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &UserMessages::OnStartMessage_Pre, false); 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, 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_Pre, false);
SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true); SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &UserMessages::OnMessageEnd_Post, true);
#endif
} }
} }
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_LEFT4DEAD
void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
{
OnStartMessage_Pre(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
if (m_FakeMetaRes == MRES_SUPERCEDE)
{
int size = msg.ByteSize();
uint8 *data = (uint8 *)stackalloc(size);
msg.SerializePartialToArray(data, size);
m_InterceptBuffer->ParsePartialFromArray(data, size);
}
else
{
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
}
OnStartMessage_Post(&filter, msg_type, g_Cstrike15UsermessageHelpers.GetName(msg_type));
OnMessageEnd_Pre();
if (m_FakeMetaRes == MRES_SUPERCEDE)
RETURN_META(MRES_SUPERCEDE);
RETURN_META(MRES_IGNORED);
}
void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg)
{
OnMessageEnd_Post();
RETURN_META(MRES_IGNORED);
}
#endif
#ifdef USE_PROTOBUF_USERMESSAGES
#define UM_RETURN_META_VALUE(res, val) \
m_FakeMetaRes = res; \
return val;
#define UM_RETURN_META(res) \
m_FakeMetaRes = res; \
return;
#else
#define UM_RETURN_META_VALUE(res, val) \
RETURN_META_VALUE(res, val)
#define UM_RETURN_META(res) \
RETURN_META(res)
#endif
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name) bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#else #else
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type) bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type)
@@ -556,7 +329,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS))) || (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
{ {
m_InHook = false; m_InHook = false;
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
m_CurId = msg_type; m_CurId = msg_type;
@@ -566,23 +339,14 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
if (!is_intercept_empty) if (!is_intercept_empty)
{ {
#ifdef USE_PROTOBUF_USERMESSAGES
if (m_InterceptBuffer)
delete m_InterceptBuffer;
m_InterceptBuffer = g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
#else
m_InterceptBuffer.Reset(); m_InterceptBuffer.Reset();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer); RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
#endif
} }
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_LEFT4DEAD
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name) bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#else #else
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type) bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type)
@@ -590,26 +354,19 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
{ {
if (!m_InHook) if (!m_InHook)
{ {
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
#ifdef USE_PROTOBUF_USERMESSAGES
if (m_FakeMetaRes == MRES_SUPERCEDE)
m_OrigBuffer = m_InterceptBuffer;
else
m_OrigBuffer = m_FakeEngineBuffer;
#else
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *); m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
#endif
UM_RETURN_META_VALUE(MRES_IGNORED, NULL); RETURN_META_VALUE(MRES_IGNORED, NULL);
} }
void UserMessages::OnMessageEnd_Post() void UserMessages::OnMessageEnd_Post()
{ {
if (!m_InHook) if (!m_InHook)
{ {
UM_RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
MsgList *pList; MsgList *pList;
@@ -677,7 +434,7 @@ void UserMessages::OnMessageEnd_Pre()
{ {
if (!m_InHook) if (!m_InHook)
{ {
UM_RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
MsgList *pList; MsgList *pList;
@@ -693,11 +450,7 @@ void UserMessages::OnMessageEnd_Pre()
{ {
pInfo = (*iter); pInfo = (*iter);
pInfo->IsHooked = true; pInfo->IsHooked = true;
#ifdef USE_PROTOBUF_USERMESSAGES
res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
#else
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter); res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
#endif
intercepted = true; intercepted = true;
@@ -745,11 +498,9 @@ void UserMessages::OnMessageEnd_Pre()
if (!handled && intercepted) if (!handled && intercepted)
{ {
#if SOURCE_ENGINE == SE_CSGO
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
#else
bf_write *engine_bfw; bf_write *engine_bfw;
#if SOURCE_ENGINE >= SE_LEFT4DEAD
#if SOURCE_ENGINE == SE_LEFT4DEAD
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId)); engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId, g_SMAPI->GetUserMessage(m_CurId));
#else #else
engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId); engine_bfw = ENGINE_CALL(UserMessageBegin)(m_CurRecFilter, m_CurId);
@@ -757,46 +508,29 @@ void UserMessages::OnMessageEnd_Pre()
m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten()); m_ReadBuffer.StartReading(m_InterceptBuffer.GetBasePointer(), m_InterceptBuffer.GetNumBytesWritten());
engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten()); engine_bfw->WriteBitsFromBuffer(&m_ReadBuffer, m_InterceptBuffer.GetNumBitsWritten());
ENGINE_CALL(MessageEnd)(); ENGINE_CALL(MessageEnd)();
#endif // SE_CSGO
} }
pList = &m_msgHooks[m_CurId];
for (iter=pList->begin(); iter!=pList->end(); )
{ {
#if SOURCE_ENGINE == SE_CSGO pInfo = (*iter);
int size = m_OrigBuffer->ByteSize(); pInfo->IsHooked = true;
uint8 *data = (uint8 *)stackalloc(size); pInfo->Callback->OnUserMessage(m_CurId, m_OrigBuffer, m_CurRecFilter);
m_OrigBuffer->SerializePartialToArray(data, size);
protobuf::Message *pTempMsg = g_Cstrike15UsermessageHelpers.GetPrototype(m_CurId)->New();
pTempMsg->ParsePartialFromArray(data, size);
#else
bf_write *pTempMsg = m_OrigBuffer;
#endif
pList = &m_msgHooks[m_CurId]; if (pInfo->KillMe)
for (iter=pList->begin(); iter!=pList->end(); )
{ {
pInfo = (*iter); iter = pList->erase(iter);
pInfo->IsHooked = true; m_FreeListeners.push(pInfo);
pInfo->Callback->OnUserMessage(m_CurId, pTempMsg, m_CurRecFilter); _DecRefCounter();
continue;
if (pInfo->KillMe)
{
iter = pList->erase(iter);
m_FreeListeners.push(pInfo);
_DecRefCounter();
continue;
}
pInfo->IsHooked = false;
iter++;
} }
#if SOURCE_ENGINE == SE_CSGO pInfo->IsHooked = false;
delete pTempMsg; iter++;
#endif
} }
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED); RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);
supercede: supercede:
m_BlockEndPost = true; m_BlockEndPost = true;
UM_RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
} }
+7 -52
View File
@@ -2,7 +2,7 @@
* vim: set ts=4 : * vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod * SourceMod
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -36,35 +36,16 @@
#include <IUserMessages.h> #include <IUserMessages.h>
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_trie.h" #include "sm_trie.h"
#include "sm_stringutil.h"
#include "CellRecipientFilter.h" #include "CellRecipientFilter.h"
using namespace SourceHook; using namespace SourceHook;
using namespace SourceMod; using namespace SourceMod;
#if SOURCE_ENGINE == SE_CSGO
#define USE_PROTOBUF_USERMESSAGES
#endif
#ifdef USE_PROTOBUF_USERMESSAGES
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <netmessages.pb.h>
using namespace google;
#else
#include <bitbuf.h>
#endif
#define INVALID_MESSAGE_ID -1 #define INVALID_MESSAGE_ID -1
struct ListenerInfo struct ListenerInfo
{ {
#ifdef USE_PROTOBUF_USERMESSAGES IUserMessageListener *Callback;
IProtobufUserMessageListener *Callback;
#else
IBitBufUserMessageListener *Callback;
#endif
bool IsHooked; bool IsHooked;
bool KillMe; bool KillMe;
bool IsNew; bool IsNew;
@@ -89,8 +70,7 @@ public: //IUserMessages
bool GetMessageName(int msgid, char *buffer, size_t maxlength) const; bool GetMessageName(int msgid, char *buffer, size_t maxlength) const;
bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false); bool HookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false); bool UnhookUserMessage(int msg_id, IUserMessageListener *pListener, bool intercept=false);
bf_write *StartBitBufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags); bf_write *StartMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
google::protobuf::Message *StartProtobufMessage(int msg_id, const cell_t players[], unsigned int playersNum, int flags);
bool EndMessage(); bool EndMessage();
bool HookUserMessage2(int msg_id, bool HookUserMessage2(int msg_id,
IUserMessageListener *pListener, IUserMessageListener *pListener,
@@ -98,17 +78,8 @@ public: //IUserMessages
bool UnhookUserMessage2(int msg_id, bool UnhookUserMessage2(int msg_id,
IUserMessageListener *pListener, IUserMessageListener *pListener,
bool intercept=false); bool intercept=false);
UserMessageType GetUserMessageType() const;
public: public:
#if SOURCE_ENGINE == SE_CSGO #if SOURCE_ENGINE == SE_LEFT4DEAD
void OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
void OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type, const protobuf::Message &msg);
#endif
#if SOURCE_ENGINE == SE_CSGO
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name); bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name); bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
#else #else
@@ -118,40 +89,24 @@ public:
void OnMessageEnd_Pre(); void OnMessageEnd_Pre();
void OnMessageEnd_Post(); void OnMessageEnd_Post();
private: private:
#ifdef USE_PROTOBUF_USERMESSAGES bool InternalHook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew); bool InternalUnhook(int msg_id, IUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
#else
bool InternalHook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IBitBufUserMessageListener *pListener, bool intercept, bool isNew);
#endif
void _DecRefCounter(); void _DecRefCounter();
private: private:
List<ListenerInfo *> m_msgHooks[255]; List<ListenerInfo *> m_msgHooks[255];
List<ListenerInfo *> m_msgIntercepts[255]; List<ListenerInfo *> m_msgIntercepts[255];
CStack<ListenerInfo *> m_FreeListeners; CStack<ListenerInfo *> m_FreeListeners;
IRecipientFilter *m_CurRecFilter;
#ifndef USE_PROTOBUF_USERMESSAGES
unsigned char m_pBase[2500]; unsigned char m_pBase[2500];
IRecipientFilter *m_CurRecFilter;
bf_write m_InterceptBuffer; bf_write m_InterceptBuffer;
bf_write *m_OrigBuffer; bf_write *m_OrigBuffer;
bf_read m_ReadBuffer; bf_read m_ReadBuffer;
#else
// The engine used to provide this. Now we track it.
protobuf::Message *m_OrigBuffer;
protobuf::Message *m_FakeEngineBuffer;
META_RES m_FakeMetaRes;
protobuf::Message *m_InterceptBuffer;
#endif
size_t m_HookCount; size_t m_HookCount;
bool m_InHook; bool m_InHook;
bool m_BlockEndPost; bool m_BlockEndPost;
#ifndef USE_PROTOBUF_USERMESSAGES
bool m_FallbackSearch; bool m_FallbackSearch;
Trie *m_Names; Trie *m_Names;
#endif
CellRecipientFilter m_CellRecFilter; CellRecipientFilter m_CellRecFilter;
bool m_InExec; bool m_InExec;
int m_CurFlags; int m_CurFlags;
+2 -31
View File
@@ -39,9 +39,6 @@
#if SOURCE_ENGINE >= SE_ORANGEBOX #if SOURCE_ENGINE >= SE_ORANGEBOX
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *); SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
SH_DECL_HOOK1_void(ICvar, RegisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
#else
SH_DECL_HOOK1_void(ICvar, RegisterConCommandBase, SH_NOATTRIB, 0, ConCommandBase *);
#endif #endif
using namespace SourceHook; using namespace SourceHook;
@@ -54,55 +51,29 @@ struct ConCommandInfo
}; };
List<ConCommandInfo *> tracked_bases; List<ConCommandInfo *> tracked_bases;
IConCommandLinkListener *IConCommandLinkListener::head = NULL;
ConCommandBase *FindConCommandBase(const char *name); ConCommandBase *FindConCommandBase(const char *name);
class ConCommandCleaner : public SMGlobalClass class ConCommandCleaner : public SMGlobalClass
{ {
public: public:
#if SOURCE_ENGINE >= SE_ORANGEBOX
void OnSourceModAllInitialized() void OnSourceModAllInitialized()
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false); SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#else
SH_ADD_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#endif
} }
void OnSourceModShutdown() void OnSourceModShutdown()
{ {
#if SOURCE_ENGINE >= SE_ORANGEBOX
SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false); SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommand, icvar, this, &ConCommandCleaner::LinkConCommandBase, false); }
#else
SH_REMOVE_HOOK_MEMFUNC(ICvar, RegisterConCommandBase, icvar, this, &ConCommandCleaner::LinkConCommandBase, false);
#endif #endif
}
void LinkConCommandBase(ConCommandBase *pBase)
{
IConCommandLinkListener *listener = IConCommandLinkListener::head;
while (listener)
{
listener->OnLinkConCommand(pBase);
listener = listener->next;
}
}
void UnlinkConCommandBase(ConCommandBase *pBase) void UnlinkConCommandBase(ConCommandBase *pBase)
{ {
ConCommandInfo *pInfo; ConCommandInfo *pInfo;
List<ConCommandInfo *>::iterator iter = tracked_bases.begin(); List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
IConCommandLinkListener *listener = IConCommandLinkListener::head;
while (listener)
{
listener->OnUnlinkConCommand(pBase);
listener = listener->next;
}
if (pBase) if (pBase)
{ {
while (iter != tracked_bases.end()) while (iter != tracked_bases.end())
-22
View File
@@ -42,26 +42,4 @@ void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me); void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase); void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
class IConCommandLinkListener
{
friend class ConCommandCleaner;
static IConCommandLinkListener *head;
IConCommandLinkListener *next;
public:
IConCommandLinkListener()
{
next = head;
head = this;
}
virtual void OnLinkConCommand(ConCommandBase *pBase)
{
}
virtual void OnUnlinkConCommand(ConCommandBase *pBase)
{
}
};
#endif //_INCLUDE_CONCMD_TRACKER_H_ #endif //_INCLUDE_CONCMD_TRACKER_H_
+1 -7
View File
@@ -24,7 +24,7 @@
#ifdef _WIN32 #ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE #define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__ #elif _LINUX
#define FORCEINLINE_CVAR inline #define FORCEINLINE_CVAR inline
#else #else
#error "implement me" #error "implement me"
@@ -386,9 +386,6 @@ public:
virtual void SetValue( const char *value ); virtual void SetValue( const char *value );
virtual void SetValue( float value ); virtual void SetValue( float value );
virtual void SetValue( int value ); virtual void SetValue( int value );
#if SOURCE_ENGINE >= SE_NUCLEARDAWN
virtual void SetValue( Color value );
#endif
// Reset to default value // Reset to default value
void Revert( void ); void Revert( void );
@@ -404,9 +401,6 @@ private:
// For CVARs marked FCVAR_NEVER_AS_STRING // For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue ); virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue ); virtual void InternalSetIntValue( int nValue );
#if SOURCE_ENGINE >= SE_LEFT4DEAD2
virtual void InternalSetColorValue( Color value );
#endif
virtual bool ClampValue( float& value ); virtual bool ClampValue( float& value );
virtual void ChangeStringValue( const char *tempVal, float flOldValue ); virtual void ChangeStringValue( const char *tempVal, float flOldValue );
+1 -1
View File
@@ -24,7 +24,7 @@
#ifdef _WIN32 #ifdef _WIN32
#define FORCEINLINE_CVAR FORCEINLINE #define FORCEINLINE_CVAR FORCEINLINE
#elif defined _LINUX || defined __APPLE__ #elif _LINUX
#define FORCEINLINE_CVAR inline #define FORCEINLINE_CVAR inline
#else #else
#error "implement me" #error "implement me"
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -37,7 +37,7 @@
#include "PlayerManager.h" #include "PlayerManager.h"
#include "CoreConfig.h" #include "CoreConfig.h"
#include <sm_queue.h> #include <sm_queue.h>
#include <IThreader.h> #include "ThreadSupport.h"
static IMutex *frame_mutex; static IMutex *frame_mutex;
static Queue<FrameAction> *frame_queue; static Queue<FrameAction> *frame_queue;
-59
View File
@@ -1,59 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
binary = SM.Library(builder, 'sourcemod.logic')
binary.compiler.cxxincludes += [
os.path.join(builder.sourcePath, 'core', 'logic'),
os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
os.path.join(builder.sourcePath, 'public', 'amtl'),
os.path.join(SM.mms_root, 'core', 'sourcehook')
]
binary.compiler.defines += [
'SM_DEFAULT_THREADER',
'SM_LOGIC'
]
if builder.target_platform == 'linux':
binary.compiler.postlink += ['-lpthread', '-lrt']
elif builder.target_platform == 'mac':
binary.compiler.cflags += ['-Wno-deprecated-declarations']
binary.compiler.postlink += ['-framework', 'CoreServices']
binary.sources += [
'common_logic.cpp',
'smn_adt_array.cpp',
'smn_sorting.cpp',
'smn_maplists.cpp',
'smn_adt_stack.cpp',
'thread/ThreadWorker.cpp',
'thread/BaseWorker.cpp',
'ThreadSupport.cpp',
'smn_float.cpp',
'TextParsers.cpp',
'smn_textparse.cpp',
'smn_adt_trie.cpp',
'Profiler.cpp',
'smn_functions.cpp',
'smn_timers.cpp',
'smn_players.cpp',
'MemoryUtils.cpp',
'smn_admin.cpp',
'smn_banning.cpp',
'stringutil.cpp',
'Translator.cpp',
'PhraseCollection.cpp',
'smn_lang.cpp',
'smn_string.cpp',
'smn_handles.cpp',
'smn_datapacks.cpp',
'smn_gameconfigs.cpp',
'GameConfigs.cpp',
'sm_crc32.cpp',
'smn_profiler.cpp',
]
if builder.target_platform == 'windows':
binary.sources += ['thread/WinThreads.cpp']
else:
binary.sources += ['thread/PosixThreads.cpp']
SM.binaries += [builder.Add(binary)]
-92
View File
@@ -1,92 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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_AUTO_HANDLE_ROOTER_H_
#define _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_
#include "common_logic.h"
#include <IHandleSys.h>
class AutoHandleRooter
{
public:
AutoHandleRooter(Handle_t hndl)
{
if (hndl != BAD_HANDLE)
this->hndl = handlesys->FastCloneHandle(hndl);
else
this->hndl = BAD_HANDLE;
}
~AutoHandleRooter()
{
if (hndl != BAD_HANDLE)
{
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
handlesys->FreeHandle(hndl, &sec);
}
}
Handle_t getHandle()
{
return hndl;
}
private:
Handle_t hndl;
};
class AutoHandleCloner
{
Handle_t original;
HandleSecurity sec;
AutoHandleRooter ahr;
public:
AutoHandleCloner(Handle_t original, HandleSecurity sec)
: original(original), sec(sec), ahr(original)
{
}
~AutoHandleCloner()
{
if (original != BAD_HANDLE)
{
handlesys->FreeHandle(original, &sec);
}
}
Handle_t getClone()
{
return ahr.getHandle();
}
};
#endif /* _INCLUDE_SOURCEMOD_AUTO_HANDLE_ROOTER_H_ */
File diff suppressed because it is too large Load Diff
-108
View File
@@ -1,108 +0,0 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
MMSOURCE17 = ../../../mmsource-1.7
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
BINARY = sourcemod.logic.so
OBJECTS = \
common_logic.cpp \
smn_adt_array.cpp \
smn_sorting.cpp \
smn_maplists.cpp \
smn_adt_stack.cpp \
thread/ThreadWorker.cpp \
thread/BaseWorker.cpp \
thread/PosixThreads.cpp \
ThreadSupport.cpp \
smn_float.cpp \
TextParsers.cpp \
smn_textparse.cpp \
smn_adt_trie.cpp \
Profiler.cpp \
smn_functions.cpp \
sm_crc32.cpp \
smn_timers.cpp \
MemoryUtils.cpp \
smn_admin.cpp \
smn_banning.cpp \
stringutil.cpp \
Translator.cpp \
PhraseCollection.cpp \
smn_lang.cpp \
smn_string.cpp \
smn_handles.cpp \
smn_datapacks.cpp \
smn_gameconfigs.cpp \
GameConfigs.cpp \
smn_players.cpp \
smn_profiler.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
LINK += -lpthread -static-libgcc
INCLUDE += -I. -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror \
-Wno-uninitialized -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -DSM_DEFAULT_THREADER -m32 \
-DSM_LOGIC
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/thread
$(MAKE) -f Makefile sourcemod
sourcemod: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o $(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
default: all
clean:
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/thread/*.o
rm -rf $(BIN_DIR)/$(BINARY)
-612
View File
@@ -1,612 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2011 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>.
*/
#include "MemoryUtils.h"
#ifdef PLATFORM_LINUX
#include <fcntl.h>
#include <link.h>
#include <sys/mman.h>
#define PAGE_SIZE 4096
#define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
#endif
#ifdef PLATFORM_APPLE
#include <AvailabilityMacros.h>
#include <mach/task.h>
#include <mach-o/dyld_images.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
/* Define things from 10.6 SDK for older SDKs */
#ifndef MAC_OS_X_VERSION_10_6
struct task_dyld_info
{
mach_vm_address_t all_image_info_addr;
mach_vm_size_t all_image_info_size;
};
typedef struct task_dyld_info task_dyld_info_data_t;
#define TASK_DYLD_INFO 17
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
#endif // MAC_OS_X_VERSION_10_6
#endif // PLATFORM_APPLE
MemoryUtils g_MemUtils;
MemoryUtils::MemoryUtils()
{
#ifdef PLATFORM_APPLE
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);
/* Get pointer to struct that describes all loaded mach-o images in process */
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
{
task_dyld_info_data_t dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
}
else
{
struct nlist list[2];
memset(list, 0, sizeof(list));
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
nlist("/usr/lib/dyld", list);
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
}
#endif
}
MemoryUtils::~MemoryUtils()
{
#if defined PLATFORM_LINUX || defined PLATFORM_APPLE
for (size_t i = 0; i < m_SymTables.size(); i++)
{
delete m_SymTables[i];
}
m_SymTables.clear();
#endif
}
void MemoryUtils::OnSourceModAllInitialized()
{
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 - len;
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;
}
void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
{
#ifdef PLATFORM_WINDOWS
return GetProcAddress((HMODULE)handle, symbol);
#elif defined PLATFORM_LINUX
struct link_map *dlmap;
struct stat dlstat;
int dlfile;
uintptr_t map_base;
Elf32_Ehdr *file_hdr;
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
Elf32_Sym *symtab;
const char *shstrtab, *strtab;
uint16_t section_count;
uint32_t symbol_count;
LibSymbolTable *libtable;
SymbolTable *table;
Symbol *symbol_entry;
dlmap = (struct link_map *)handle;
symtab_hdr = NULL;
strtab_hdr = NULL;
table = NULL;
/* See if we already have a symbol table for this library */
for (size_t i = 0; i < m_SymTables.size(); i++)
{
libtable = m_SymTables[i];
if (libtable->lib_base == dlmap->l_addr)
{
table = &libtable->table;
break;
}
}
/* If we don't have a symbol table for this library, then create one */
if (table == NULL)
{
libtable = new LibSymbolTable();
libtable->table.Initialize();
libtable->lib_base = dlmap->l_addr;
libtable->last_pos = 0;
table = &libtable->table;
m_SymTables.push_back(libtable);
}
/* See if the symbol is already cached in our table */
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
if (symbol_entry != NULL)
{
return symbol_entry->address;
}
/* If symbol isn't in our table, then we have open the actual library */
dlfile = open(dlmap->l_name, O_RDONLY);
if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
{
close(dlfile);
return NULL;
}
/* Map library file into memory */
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
map_base = (uintptr_t)file_hdr;
if (file_hdr == MAP_FAILED)
{
close(dlfile);
return NULL;
}
close(dlfile);
if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
{
munmap(file_hdr, dlstat.st_size);
return NULL;
}
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
section_count = file_hdr->e_shnum;
/* Get ELF section header string table */
shstrtab_hdr = &sections[file_hdr->e_shstrndx];
shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);
/* Iterate sections while looking for ELF symbol table and string table */
for (uint16_t i = 0; i < section_count; i++)
{
Elf32_Shdr &hdr = sections[i];
const char *section_name = shstrtab + hdr.sh_name;
if (strcmp(section_name, ".symtab") == 0)
{
symtab_hdr = &hdr;
}
else if (strcmp(section_name, ".strtab") == 0)
{
strtab_hdr = &hdr;
}
}
/* Uh oh, we don't have a symbol table or a string table */
if (symtab_hdr == NULL || strtab_hdr == NULL)
{
munmap(file_hdr, dlstat.st_size);
return NULL;
}
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
/* Iterate symbol table starting from the position we were at last time */
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
{
Elf32_Sym &sym = symtab[i];
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
const char *sym_name = strtab + sym.st_name;
Symbol *cur_sym;
/* Skip symbols that are undefined or do not refer to functions or objects */
if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
{
continue;
}
/* Caching symbols as we go along */
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value));
if (strcmp(symbol, sym_name) == 0)
{
symbol_entry = cur_sym;
libtable->last_pos = ++i;
break;
}
}
munmap(file_hdr, dlstat.st_size);
return symbol_entry ? symbol_entry->address : NULL;
#elif defined PLATFORM_APPLE
uintptr_t dlbase, linkedit_addr;
uint32_t image_count;
struct mach_header *file_hdr;
struct load_command *loadcmds;
struct segment_command *linkedit_hdr;
struct symtab_command *symtab_hdr;
struct nlist *symtab;
const char *strtab;
uint32_t loadcmd_count;
uint32_t symbol_count;
LibSymbolTable *libtable;
SymbolTable *table;
Symbol *symbol_entry;
dlbase = 0;
image_count = m_ImageList->infoArrayCount;
linkedit_hdr = NULL;
symtab_hdr = NULL;
table = NULL;
/* Loop through mach-o images in process.
* We can skip index 0 since that is just the executable.
*/
for (uint32_t i = 1; i < image_count; i++)
{
const struct dyld_image_info &info = m_ImageList->infoArray[i];
/* "Load" each one until we get a matching handle */
void *h = dlopen(info.imageFilePath, RTLD_NOLOAD);
if (h == handle)
{
dlbase = (uintptr_t)info.imageLoadAddress;
dlclose(h);
break;
}
dlclose(h);
}
if (!dlbase)
{
/* Uh oh, we couldn't find a matching handle */
return NULL;
}
/* See if we already have a symbol table for this library */
for (size_t i = 0; i < m_SymTables.size(); i++)
{
libtable = m_SymTables[i];
if (libtable->lib_base == dlbase)
{
table = &libtable->table;
break;
}
}
/* If we don't have a symbol table for this library, then create one */
if (table == NULL)
{
libtable = new LibSymbolTable();
libtable->table.Initialize();
libtable->lib_base = dlbase;
libtable->last_pos = 0;
table = &libtable->table;
m_SymTables.push_back(libtable);
}
/* See if the symbol is already cached in our table */
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
if (symbol_entry != NULL)
{
return symbol_entry->address;
}
/* If symbol isn't in our table, then we have to locate it in memory */
file_hdr = (struct mach_header *)dlbase;
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
loadcmd_count = file_hdr->ncmds;
/* Loop through load commands until we find the ones for the symbol table */
for (uint32_t i = 0; i < loadcmd_count; i++)
{
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
{
struct segment_command *seg = (struct segment_command *)loadcmds;
if (strcmp(seg->segname, "__LINKEDIT") == 0)
{
linkedit_hdr = seg;
if (symtab_hdr)
{
break;
}
}
}
else if (loadcmds->cmd == LC_SYMTAB)
{
symtab_hdr = (struct symtab_command *)loadcmds;
if (linkedit_hdr)
{
break;
}
}
/* Load commands are not of a fixed size which is why we add the size */
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
}
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
{
/* Uh oh, no symbol table */
return NULL;
}
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
symbol_count = symtab_hdr->nsyms;
/* Iterate symbol table starting from the position we were at last time */
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
{
struct nlist &sym = symtab[i];
/* Ignore the prepended underscore on all symbols, so +1 here */
const char *sym_name = strtab + sym.n_un.n_strx + 1;
Symbol *cur_sym;
/* Skip symbols that are undefined */
if (sym.n_sect == NO_SECT)
{
continue;
}
/* Caching symbols as we go along */
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlbase + sym.n_value));
if (strcmp(symbol, sym_name) == 0)
{
symbol_entry = cur_sym;
libtable->last_pos = ++i;
break;
}
}
return symbol_entry ? symbol_entry->address : NULL;
#endif
}
bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
{
uintptr_t 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<uintptr_t>(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<uintptr_t>(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);
for (uint16_t i = 0; i < phdrCount; i++)
{
Elf32_Phdr &hdr = phdr[i];
/* We only really care about the segment with executable code */
if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R))
{
/* From glibc, elf/dl-load.c:
* c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1)
* & ~(GLRO(dl_pagesize) - 1));
*
* In glibc, the segment file size is aligned up to the nearest page size and
* added to the virtual address of the segment. We just want the size here.
*/
lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz);
break;
}
}
#elif defined PLATFORM_APPLE
Dl_info info;
struct mach_header *file;
struct segment_command *seg;
uint32_t cmd_count;
if (!dladdr(libPtr, &info))
{
return false;
}
if (!info.dli_fbase || !info.dli_fname)
{
return false;
}
/* This is for our insane sanity checks :o */
baseAddr = (uintptr_t)info.dli_fbase;
file = (struct mach_header *)baseAddr;
/* Check Mach-O magic */
if (file->magic != MH_MAGIC)
{
return false;
}
/* Check architecture (32-bit/x86) */
if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL)
{
return false;
}
/* For our purposes, this must be a dynamic library */
if (file->filetype != MH_DYLIB)
{
return false;
}
cmd_count = file->ncmds;
seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header));
/* Add up memory sizes of mapped segments */
for (uint32_t i = 0; i < cmd_count; i++)
{
if (seg->cmd == LC_SEGMENT)
{
lib.memorySize += seg->vmsize;
}
seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize);
}
#endif
lib.baseAddress = reinterpret_cast<void *>(baseAddr);
return true;
}
-399
View File
@@ -1,399 +0,0 @@
// MersenneTwister.h
// Mersenne Twister random number generator -- a C++ class MTRand
// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// Richard J. Wagner v1.0 15 May 2003 [email protected]
// The Mersenne Twister is an algorithm for generating random numbers. It
// was designed with consideration of the flaws in various other generators.
// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
// are far greater. The generator is also fast; it avoids multiplication and
// division, and it benefits from caches and pipelines. For more information
// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
// Reference
// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
// Copyright (C) 2000 - 2003, Richard J. Wagner
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The names of its contributors may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The original code included the following notice:
//
// When you use this, send an email to: [email protected]
// with an appropriate reference to your work.
//
// It would be nice to CC: [email protected] and [email protected]
// when you write.
#ifndef MERSENNETWISTER_H
#define MERSENNETWISTER_H
// Not thread safe (unless auto-initialization is avoided and each thread has
// its own MTRand object)
#include <limits.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
class MTRand {
// Data
public:
typedef unsigned long uint32; // unsigned integer type, at least 32 bits
enum { N = 624 }; // length of state vector
enum { SAVE = N + 1 }; // length of array for save()
protected:
enum { M = 397 }; // period parameter
uint32 state[N]; // internal state
uint32 *pNext; // next value to get from state
int left; // number of values left before reload needed
//Methods
public:
MTRand( const uint32& oneSeed ); // initialize with a simple uint32
MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
MTRand(); // auto-initialize with /dev/urandom or time() and clock()
// Do NOT use for CRYPTOGRAPHY without securely hashing several returned
// values together, otherwise the generator state can be learned after
// reading 624 consecutive values.
// Access to 32-bit random numbers
double rand(); // real number in [0,1]
double rand( const double& n ); // real number in [0,n]
double randExc(); // real number in [0,1)
double randExc( const double& n ); // real number in [0,n)
double randDblExc(); // real number in (0,1)
double randDblExc( const double& n ); // real number in (0,n)
uint32 randInt(); // integer in [0,2^32-1]
uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
double operator()() { return rand(); } // same as rand()
// Access to 53-bit random numbers (capacity of IEEE double precision)
double rand53(); // real number in [0,1)
// Access to nonuniform random number distributions
double randNorm( const double& mean = 0.0, const double& variance = 0.0 );
// Re-seeding functions with same behavior as initializers
void seed( const uint32 oneSeed );
void seed( uint32 *const bigSeed, const uint32 seedLength = N );
void seed();
// Saving and loading generator state
void save( uint32* saveArray ) const; // to array of size SAVE
void load( uint32 *const loadArray ); // from such array
protected:
void initialize( const uint32 oneSeed );
void reload();
uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
uint32 mixBits( const uint32& u, const uint32& v ) const
{ return hiBit(u) | loBits(v); }
uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
{ return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); }
static uint32 hash( time_t t, clock_t c );
};
inline MTRand::MTRand( const uint32& oneSeed )
{ seed(oneSeed); }
inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
{ seed(bigSeed,seedLength); }
inline MTRand::MTRand()
{ seed(); }
inline double MTRand::rand()
{ return double(randInt()) * (1.0/4294967295.0); }
inline double MTRand::rand( const double& n )
{ return rand() * n; }
inline double MTRand::randExc()
{ return double(randInt()) * (1.0/4294967296.0); }
inline double MTRand::randExc( const double& n )
{ return randExc() * n; }
inline double MTRand::randDblExc()
{ return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
inline double MTRand::randDblExc( const double& n )
{ return randDblExc() * n; }
inline double MTRand::rand53()
{
uint32 a = randInt() >> 5, b = randInt() >> 6;
return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
}
inline double MTRand::randNorm( const double& mean, const double& variance )
{
// Return a real number from a normal (Gaussian) distribution with given
// mean and variance by Box-Muller method
double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
return mean + r * cos(phi);
}
inline MTRand::uint32 MTRand::randInt()
{
// Pull a 32-bit integer from the generator state
// Every other access function simply transforms the numbers extracted here
if( left == 0 ) reload();
--left;
register uint32 s1;
s1 = *pNext++;
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9d2c5680UL;
s1 ^= (s1 << 15) & 0xefc60000UL;
return ( s1 ^ (s1 >> 18) );
}
inline MTRand::uint32 MTRand::randInt( const uint32& n )
{
// Find which bits are used in n
// Optimized by Magnus Jonsson ([email protected])
uint32 used = n;
used |= used >> 1;
used |= used >> 2;
used |= used >> 4;
used |= used >> 8;
used |= used >> 16;
// Draw numbers until one is found in [0,n]
uint32 i;
do
i = randInt() & used; // toss unused bits to shorten search
while( i > n );
return i;
}
inline void MTRand::seed( const uint32 oneSeed )
{
// Seed the generator with a simple uint32
initialize(oneSeed);
reload();
}
inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
{
// Seed the generator with an array of uint32's
// There are 2^19937-1 possible initial states. This function allows
// all of those to be accessed by providing at least 19937 bits (with a
// default seed length of N = 624 uint32's). Any bits above the lower 32
// in each element are discarded.
// Just call seed() if you want to get array from /dev/urandom
initialize(19650218UL);
register int i = 1;
register uint32 j = 0;
register int k = ( N > seedLength ? N : seedLength );
for( ; k; --k )
{
state[i] =
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
state[i] &= 0xffffffffUL;
++i; ++j;
if( i >= N ) { state[0] = state[N-1]; i = 1; }
if( j >= seedLength ) j = 0;
}
for( k = N - 1; k; --k )
{
state[i] =
state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
state[i] -= i;
state[i] &= 0xffffffffUL;
++i;
if( i >= N ) { state[0] = state[N-1]; i = 1; }
}
state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
reload();
}
inline void MTRand::seed()
{
// Seed the generator with an array from /dev/urandom if available
// Otherwise use a hash of time() and clock() values
// First try getting an array from /dev/urandom
FILE* urandom = fopen( "/dev/urandom", "rb" );
if( urandom )
{
uint32 bigSeed[N];
register uint32 *s = bigSeed;
register int i = N;
register bool success = true;
while( success && i-- )
success = fread( s++, sizeof(uint32), 1, urandom );
fclose(urandom);
if( success ) { seed( bigSeed, N ); return; }
}
// Was not successful, so use time() and clock() instead
seed( hash( time(NULL), clock() ) );
}
inline void MTRand::initialize( const uint32 seed )
{
// Initialize generator state with seed
// See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
// In previous versions, most significant bits (MSBs) of the seed affect
// only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
register uint32 *s = state;
register uint32 *r = state;
register int i = 1;
*s++ = seed & 0xffffffffUL;
for( ; i < N; ++i )
{
*s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
r++;
}
}
inline void MTRand::reload()
{
// Generate N new values in state
// Made clearer and faster by Matthew Bellew ([email protected])
register uint32 *p = state;
register int i;
for( i = N - M; i--; ++p )
*p = twist( p[M], p[0], p[1] );
for( i = M; --i; ++p )
*p = twist( p[M-N], p[0], p[1] );
*p = twist( p[M-N], p[0], state[0] );
left = N, pNext = state;
}
inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
{
// Get a uint32 from t and c
// Better than uint32(x) in case x is floating point in [0,1]
// Based on code by Lawrence Kirby ([email protected])
static uint32 differ = 0; // guarantee time-based seeds will change
uint32 h1 = 0;
unsigned char *p = (unsigned char *) &t;
for( size_t i = 0; i < sizeof(t); ++i )
{
h1 *= UCHAR_MAX + 2U;
h1 += p[i];
}
uint32 h2 = 0;
p = (unsigned char *) &c;
for( size_t j = 0; j < sizeof(c); ++j )
{
h2 *= UCHAR_MAX + 2U;
h2 += p[j];
}
return ( h1 + differ++ ) ^ h2;
}
inline void MTRand::save( uint32* saveArray ) const
{
register uint32 *sa = saveArray;
register const uint32 *s = state;
register int i = N;
for( ; i--; *sa++ = *s++ ) {}
*sa = left;
}
inline void MTRand::load( uint32 *const loadArray )
{
register uint32 *s = state;
register uint32 *la = loadArray;
register int i = N;
for( ; i--; *s++ = *la++ ) {}
left = *la;
pNext = &state[N-left];
}
#endif // MERSENNETWISTER_H
// Change log:
//
// v0.1 - First release on 15 May 2000
// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
// - Translated from C to C++
// - Made completely ANSI compliant
// - Designed convenient interface for initialization, seeding, and
// obtaining numbers in default or user-defined ranges
// - Added automatic seeding from /dev/urandom or time() and clock()
// - Provided functions for saving and loading generator state
//
// v0.2 - Fixed bug which reloaded generator one step too late
//
// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
//
// v0.4 - Removed trailing newline in saved generator format to be consistent
// with output format of built-in types
//
// v0.5 - Improved portability by replacing static const int's with enum's and
// clarifying return values in seed(); suggested by Eric Heimburg
// - Removed MAXINT constant; use 0xffffffffUL instead
//
// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
// - Changed integer [0,n] generator to give better uniformity
//
// v0.7 - Fixed operator precedence ambiguity in reload()
// - Added access for real numbers in (0,1) and (0,n)
//
// v0.8 - Included time.h header to properly support time_t and clock_t
//
// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
// - Allowed for seeding with arrays of any length
// - Added access for real numbers in [0,1) with 53-bit resolution
// - Added access for real numbers from normal (Gaussian) distributions
// - Increased overall speed by optimizing twist()
// - Doubled speed of integer [0,n] generation
// - Fixed out-of-range number generation on 64-bit machines
// - Improved portability by substituting literal constants for long enum's
// - Changed license from GNU LGPL to BSD
-157
View File
@@ -1,157 +0,0 @@
/**
* vim: set ts=4 sw=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 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 <new>
#include <stdlib.h>
#include <sm_platform.h>
#include <string.h>
#include "common_logic.h"
#include "TextParsers.h"
#include "Profiler.h"
#include "sm_crc32.h"
#include "MemoryUtils.h"
#include "stringutil.h"
#include "ThreadSupport.h"
#include "Translator.h"
#include "GameConfigs.h"
sm_core_t smcore;
IHandleSys *handlesys;
IdentityToken_t *g_pCoreIdent;
SMGlobalClass *SMGlobalClass::head = NULL;
ISourceMod *g_pSM;
ILibrarySys *libsys;
ITextParsers *textparser = &g_TextParser;
IVEngineServer *engine;
IShareSys *sharesys;
IRootConsole *rootmenu;
IPluginManager *pluginsys;
IForwardManager *forwardsys;
ITimerSystem *timersys;
ServerGlobals serverGlobals;
IPlayerManager *playerhelpers;
IAdminSystem *adminsys;
IGameHelpers *gamehelpers;
static void AddCorePhraseFile(const char *filename)
{
g_pCorePhrases->AddPhraseFile(filename);
}
static IGameConfig *GetCoreGameConfig()
{
return g_pGameConf;
}
static sm_logic_t logic =
{
NULL,
g_pThreader,
sm_profiler,
&g_Translator,
stristr,
CoreTranslate,
AddCorePhraseFile,
UTIL_ReplaceAll,
UTIL_ReplaceEx,
UTIL_DecodeHexString,
GetCoreGameConfig
};
static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
{
logic.head = SMGlobalClass::head;
memcpy(&smcore, core, sizeof(sm_core_t));
memcpy(_logic, &logic, sizeof(sm_logic_t));
memcpy(&serverGlobals, core->serverGlobals, sizeof(ServerGlobals));
handlesys = core->handlesys;
libsys = core->libsys;
engine = core->engine;
g_pCoreIdent = core->core_ident;
g_pSM = core->sm;
sharesys = core->sharesys;
rootmenu = core->rootmenu;
pluginsys = core->pluginsys;
forwardsys = core->forwardsys;
timersys = core->timersys;
playerhelpers = core->playerhelpers;
adminsys = core->adminsys;
gamehelpers = core->gamehelpers;
}
PLATFORM_EXTERN_C ITextParsers *get_textparsers()
{
return &g_TextParser;
}
PLATFORM_EXTERN_C LogicInitFunction logic_load(uint32_t magic)
{
if (magic != SM_LOGIC_MAGIC)
{
return NULL;
}
return logic_init;
}
void CoreNativesToAdd::OnSourceModAllInitialized()
{
smcore.AddNatives(m_NativeList);
}
/* Overload a few things to prevent libstdc++ linking */
#if defined __linux__ || defined __APPLE__
extern "C" void __cxa_pure_virtual(void)
{
}
void *operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void *ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
{
free(ptr);
}
#endif
-57
View File
@@ -1,57 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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_COMMON_LOGIC_H_
#define _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_
#include <IHandleSys.h>
#include "../sm_globals.h"
#include "intercom.h"
extern sm_core_t smcore;
extern IHandleSys *handlesys;
extern ISourceMod *g_pSM;
extern ILibrarySys *libsys;
extern ITextParsers *textparser;
extern IVEngineServer *engine;
extern IShareSys *sharesys;
extern IRootConsole *rootmenu;
extern IPluginManager *pluginsys;
extern IForwardManager *forwardsys;
extern ITimerSystem *timersys;
extern ServerGlobals serverGlobals;
extern IPlayerManager *playerhelpers;
extern IAdminSystem *adminsys;
extern IGameHelpers *gamehelpers;
#endif /* _INCLUDE_SOURCEMOD_COMMON_LOGIC_H_ */
-162
View File
@@ -1,162 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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 <sp_vm_api.h>
#include <IHandleSys.h>
#include <IShareSys.h>
#ifndef _INCLUDE_SOURCEMOD_INTERCOM_H_
#define _INCLUDE_SOURCEMOD_INTERCOM_H_
using namespace SourceMod;
/**
* Add 1 to the RHS of this expression to bump the intercom file
* This is to prevent mismatching core/logic binaries
*/
#define SM_LOGIC_MAGIC (0x0F47C0DE - 18)
#if defined SM_LOGIC
class IVEngineServer
#else
class IVEngineServer_Logic
#endif
{
public:
virtual bool IsMapValid(const char *map) = 0;
virtual void ServerCommand(const char *cmd) = 0;
};
typedef int FileFindHandle_t;
#if defined SM_LOGIC
class IFileSystem
#else
class IFileSystem_Logic
#endif
{
public:
virtual const char *FindFirstEx(const char *pWildCard, const char *pPathID, FileFindHandle_t *pHandle) = 0;
virtual const char *FindNext(FileFindHandle_t handle) = 0;
virtual void FindClose(FileFindHandle_t handle) = 0;
};
namespace SourceMod
{
class ISourceMod;
class ILibrarySys;
class ITextParsers;
class IThreader;
class IRootConsole;
class IPluginManager;
class IForwardManager;
class ITimerSystem;
class IPlayerManager;
class IAdminSystem;
class IGameHelpers;
class IPhraseCollection;
class ITranslator;
class IGameConfig;
}
class IVEngineServer;
class IFileSystem;
class ConVar;
struct ServerGlobals
{
const double *universalTime;
float *interval_per_tick;
float *frametime;
};
struct sm_core_t
{
/* Objects */
IHandleSys *handlesys;
IdentityToken_t *core_ident;
ISourceMod *sm;
ILibrarySys *libsys;
IVEngineServer *engine;
IFileSystem *filesystem;
IShareSys *sharesys;
IRootConsole *rootmenu;
IPluginManager *pluginsys;
IForwardManager *forwardsys;
ITimerSystem *timersys;
IPlayerManager *playerhelpers;
IAdminSystem *adminsys;
IGameHelpers *gamehelpers;
/* Functions */
void (*AddNatives)(sp_nativeinfo_t* nlist);
ConVar * (*FindConVar)(const char*);
unsigned int (*strncopy)(char*, const char*, size_t);
char * (*TrimWhitespace)(char *, size_t &);
void (*LogError)(const char*, ...);
const char * (*GetCvarString)(ConVar*);
size_t (*Format)(char*, size_t, const char*, ...);
void (*GenerateError)(IPluginContext *, cell_t, int, const char *, ...);
bool (*gnprintf)(char *, size_t, const char *, IPhraseCollection *, void **,
unsigned int, unsigned int &, size_t *, const char **);
size_t (*atcprintf)(char *, size_t, const char *, IPluginContext *, const cell_t *, int *);
bool (*GetGameName)(char *buffer, size_t maxlength);
const char * (*GetGameDescription)();
const char * (*GetSourceEngineName)();
bool (*SymbolsAreHidden)();
const char * (*GetCoreConfigValue)(const char*);
/* Data */
ServerGlobals *serverGlobals;
void * serverFactory;
void * engineFactory;
void * matchmakingDSFactory;
};
struct sm_logic_t
{
SMGlobalClass *head;
IThreader *threader;
IProfiler *profiler;
ITranslator *translator;
const char *(*stristr)(const char *, const char *);
bool (*CoreTranslate)(char *, size_t, const char *, unsigned int, size_t *, ...);
void (*AddCorePhraseFile)(const char *filename);
unsigned int (*ReplaceAll)(char*, size_t, const char *, const char *, bool);
char *(*ReplaceEx)(char *, size_t, const char *, size_t, const char *, size_t, bool);
size_t (*DecodeHexString)(unsigned char *, size_t, const char *);
IGameConfig * (*GetCoreGameConfig)();
};
typedef void (*LogicInitFunction)(const sm_core_t *core, sm_logic_t *logic);
typedef LogicInitFunction (*LogicLoadFunction)(uint32_t magic);
typedef ITextParsers *(*GetITextParsers)();
#endif /* _INCLUDE_SOURCEMOD_INTERCOM_H_ */
-19
View File
@@ -1,19 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logic", "logic.vcxproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
-175
View File
@@ -1,175 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}</ProjectGuid>
<RootNamespace>jitx86</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">sourcemod.logic</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">sourcemod.logic</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..;$(MMSOURCE19)\core\sourcehook;..\..\..\public;..\..\..\public\sourcepawn;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_DEFAULT_THREADER;SM_LOGIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\..\public</AdditionalIncludeDirectories>
</ResourceCompile>
<PostBuildEvent>
<Command>IF NOT "%SMOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%SMOUTDIR%\bin"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..;$(MMSOURCE19)\core\sourcehook;..\..\..\public;..\..\..\public\sourcepawn;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SM_LOGIC;SM_DEFAULT_THREADER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\..\public</AdditionalIncludeDirectories>
</ResourceCompile>
<PostBuildEvent>
<Command>IF NOT "%SMOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%SMOUTDIR%\bin"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\common_logic.cpp" />
<ClCompile Include="..\GameConfigs.cpp" />
<ClCompile Include="..\MemoryUtils.cpp" />
<ClCompile Include="..\PhraseCollection.cpp" />
<ClCompile Include="..\Profiler.cpp" />
<ClCompile Include="..\sm_crc32.cpp" />
<ClCompile Include="..\smn_admin.cpp" />
<ClCompile Include="..\smn_adt_array.cpp" />
<ClCompile Include="..\smn_adt_stack.cpp" />
<ClCompile Include="..\smn_adt_trie.cpp" />
<ClCompile Include="..\smn_banning.cpp" />
<ClCompile Include="..\smn_datapacks.cpp" />
<ClCompile Include="..\smn_float.cpp" />
<ClCompile Include="..\smn_functions.cpp" />
<ClCompile Include="..\smn_gameconfigs.cpp" />
<ClCompile Include="..\smn_handles.cpp" />
<ClCompile Include="..\smn_lang.cpp" />
<ClCompile Include="..\smn_maplists.cpp" />
<ClCompile Include="..\smn_players.cpp" />
<ClCompile Include="..\smn_sorting.cpp" />
<ClCompile Include="..\smn_string.cpp" />
<ClCompile Include="..\smn_textparse.cpp" />
<ClCompile Include="..\smn_timers.cpp" />
<ClCompile Include="..\stringutil.cpp" />
<ClCompile Include="..\TextParsers.cpp" />
<ClCompile Include="..\ThreadSupport.cpp" />
<ClCompile Include="..\Translator.cpp" />
<ClCompile Include="..\thread\BaseWorker.cpp" />
<ClCompile Include="..\thread\ThreadWorker.cpp" />
<ClCompile Include="..\thread\WinThreads.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\public\sm_platform.h" />
<ClInclude Include="..\..\..\public\sm_trie_tpl.h" />
<ClInclude Include="..\..\..\public\sourcemod_version.h" />
<ClInclude Include="..\AutoHandleRooter.h" />
<ClInclude Include="..\CellArray.h" />
<ClInclude Include="..\common_logic.h" />
<ClInclude Include="..\GameConfigs.h" />
<ClInclude Include="..\intercom.h" />
<ClInclude Include="..\MemoryUtils.h" />
<ClInclude Include="..\MersenneTwister.h" />
<ClInclude Include="..\PhraseCollection.h" />
<ClInclude Include="..\Profiler.h" />
<ClInclude Include="..\sm_crc32.h" />
<ClInclude Include="..\sm_memtable.h" />
<ClInclude Include="..\sm_symtable.h" />
<ClInclude Include="..\stringutil.h" />
<ClInclude Include="..\TextParsers.h" />
<ClInclude Include="..\ThreadSupport.h" />
<ClInclude Include="..\thread\BaseWorker.h" />
<ClInclude Include="..\thread\ThreadWorker.h" />
<ClInclude Include="..\thread\WinThreads.h" />
<ClInclude Include="..\Translator.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
-194
View File
@@ -1,194 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Threads">
<UniqueIdentifier>{67c1ebce-c1f8-4d2c-9ef4-33f0ef6343e9}</UniqueIdentifier>
</Filter>
<Filter Include="Threads\Header Files">
<UniqueIdentifier>{c6e2ebb3-4869-4453-9b83-e49f70cb8a05}</UniqueIdentifier>
</Filter>
<Filter Include="Threads\Source Files">
<UniqueIdentifier>{e6d8a9af-1c1b-4f0c-ae06-a9ebd5cd32e4}</UniqueIdentifier>
</Filter>
<Filter Include="Natives">
<UniqueIdentifier>{126462f2-e517-4854-8a94-759e56787536}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\common_logic.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\GameConfigs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\MemoryUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\PhraseCollection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Profiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sm_crc32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\stringutil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\TextParsers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\ThreadSupport.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Translator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread\BaseWorker.cpp">
<Filter>Threads\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread\ThreadWorker.cpp">
<Filter>Threads\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread\WinThreads.cpp">
<Filter>Threads\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\smn_admin.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_timers.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_adt_array.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_adt_stack.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_adt_trie.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_banning.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_datapacks.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_float.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_functions.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_gameconfigs.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_handles.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_lang.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_maplists.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_players.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_sorting.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_string.cpp">
<Filter>Natives</Filter>
</ClCompile>
<ClCompile Include="..\smn_textparse.cpp">
<Filter>Natives</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\CellArray.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\common_logic.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\intercom.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Profiler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\TextParsers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\ThreadSupport.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\BaseWorker.h">
<Filter>Threads\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\ThreadWorker.h">
<Filter>Threads\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\WinThreads.h">
<Filter>Threads\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\AutoHandleRooter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GameConfigs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\MemoryUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\MersenneTwister.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\PhraseCollection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sm_crc32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sm_memtable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sm_symtable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\stringutil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\Translator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sm_trie_tpl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sourcemod_version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sm_platform.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\version.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
-20
View File
@@ -1,20 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logic", "logic.vcproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
-163
View File
@@ -1,163 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 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_
#include <stdlib.h>
#include <string.h>
class BaseMemTable
{
public:
BaseMemTable(unsigned int init_size)
{
membase = (unsigned char *)malloc(init_size);
size = init_size;
tail = 0;
}
~BaseMemTable()
{
free(membase);
membase = NULL;
}
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 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;
}
/**
* Given an index into the memory table, returns its address.
* Returns NULL if invalid.
*/
void *GetAddress(int index)
{
if (index < 0 || (unsigned int)index >= tail)
return NULL;
return &membase[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()
{
tail = 0;
}
inline unsigned int GetMemUsage()
{
return size;
}
inline unsigned int GetActualMemUsed()
{
return tail;
}
private:
unsigned char *membase;
unsigned int size;
unsigned int tail;
};
class BaseStringTable
{
public:
BaseStringTable(unsigned int init_size) : m_table(init_size)
{
}
public:
/**
* Adds a string to the string table and returns its index.
*/
int 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;
}
/**
* 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()
{
m_table.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_
-231
View File
@@ -1,231 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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>.
*/
#ifndef _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
#define _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define KESTRING_TABLE_START_SIZE 65536
struct Symbol
{
size_t length;
uint32_t hash;
void *address;
Symbol *tbl_next;
inline char *buffer()
{
return reinterpret_cast<char *>(this + 1);
}
};
class SymbolTable
{
public:
~SymbolTable()
{
for (uint32_t i = 0; i < nbuckets; i++)
{
Symbol *sym = buckets[i];
while (sym != NULL)
{
Symbol *next = sym->tbl_next;
free(sym);
sym = next;
}
}
free(buckets);
}
bool Initialize()
{
buckets = (Symbol **)malloc(sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
if (buckets == NULL)
{
return false;
}
memset(buckets, 0, sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
nbuckets = KESTRING_TABLE_START_SIZE;
nused = 0;
bucketmask = KESTRING_TABLE_START_SIZE - 1;
return true;
}
static inline uint32_t HashString(const char *data, size_t len)
{
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
uint32_t hash = len, tmp;
int rem;
if (len <= 0 || data == NULL)
{
return 0;
}
rem = len & 3;
len >>= 2;
/* Main loop */
for (;len > 0; len--) {
hash += get16bits (data);
tmp = (get16bits (data+2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2 * sizeof (uint16_t);
hash += hash >> 11;
}
/* Handle end cases */
switch (rem) {
case 3: hash += get16bits (data);
hash ^= hash << 16;
hash ^= data[sizeof (uint16_t)] << 18;
hash += hash >> 11;
break;
case 2: hash += get16bits (data);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1: hash += *data;
hash ^= hash << 10;
hash += hash >> 1;
}
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
#undef get16bits
}
Symbol **FindSymbolBucket(const char *str, size_t len, uint32_t hash)
{
uint32_t bucket = hash & bucketmask;
Symbol **pkvs = &buckets[bucket];
Symbol *kvs = *pkvs;
while (kvs != NULL)
{
if (len == kvs->length && memcmp(str, kvs->buffer(), len * sizeof(char)) == 0)
{
return pkvs;
}
pkvs = &kvs->tbl_next;
kvs = *pkvs;
}
return pkvs;
}
void ResizeSymbolTable()
{
uint32_t xnbuckets = nbuckets * 2;
Symbol **xbuckets = (Symbol **)malloc(sizeof(Symbol *) * xnbuckets);
if (xbuckets == NULL)
{
return;
}
memset(xbuckets, 0, sizeof(Symbol *) * xnbuckets);
uint32_t xbucketmask = xnbuckets - 1;
for (uint32_t i = 0; i < nbuckets; i++)
{
Symbol *sym = buckets[i];
while (sym != NULL)
{
Symbol *next = sym->tbl_next;
uint32_t bucket = sym->hash & xbucketmask;
sym->tbl_next = xbuckets[bucket];
xbuckets[bucket] = sym;
sym = next;
}
}
free(buckets);
buckets = xbuckets;
nbuckets = xnbuckets;
bucketmask = xbucketmask;
}
Symbol *FindSymbol(const char *str, size_t len)
{
uint32_t hash = HashString(str, len);
Symbol **pkvs = FindSymbolBucket(str, len, hash);
return *pkvs;
}
Symbol *InternSymbol(const char* str, size_t len, void *address)
{
uint32_t hash = HashString(str, len);
Symbol **pkvs = FindSymbolBucket(str, len, hash);
if (*pkvs != NULL)
{
return *pkvs;
}
Symbol *kvs = (Symbol *)malloc(sizeof(Symbol) + sizeof(char) * (len + 1));
kvs->length = len;
kvs->hash = hash;
kvs->address = address;
kvs->tbl_next = NULL;
memcpy(kvs + 1, str, sizeof(char) * (len + 1));
*pkvs = kvs;
nused++;
if (nused > nbuckets && nbuckets <= INT_MAX / 2)
{
ResizeSymbolTable();
}
return kvs;
}
private:
uint32_t nbuckets;
uint32_t nused;
uint32_t bucketmask;
Symbol **buckets;
};
#endif //_INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
-235
View File
@@ -1,235 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 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 "common_logic.h"
#include <IPluginSys.h>
#include <IPlayerHelpers.h>
#include <sh_string.h>
#include <sh_list.h>
#include "AutoHandleRooter.h"
#include "CellArray.h"
using namespace SourceHook;
using namespace SourceMod;
class PlayerLogicHelpers :
public SMGlobalClass,
public IPluginsListener,
public ICommandTargetProcessor
{
struct SimpleMultiTargetFilter
{
IPlugin *plugin;
SourceHook::String pattern;
IPluginFunction *fun;
SourceHook::String phrase;
bool phraseIsML;
SimpleMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
const char *phrase, bool phraseIsML)
: plugin(plugin), pattern(pattern), fun(fun), phrase(phrase), phraseIsML(phraseIsML)
{
}
};
List<SimpleMultiTargetFilter *> simpleMultis;
bool filterEnabled;
public:
void AddMultiTargetFilter(IPlugin *plugin, const char *pattern, IPluginFunction *fun,
const char *phrase, bool phraseIsML)
{
SimpleMultiTargetFilter *smtf = new SimpleMultiTargetFilter(plugin, pattern, fun, phrase,
phraseIsML);
simpleMultis.push_back(smtf);
if (!filterEnabled) {
playerhelpers->RegisterCommandTargetProcessor(this);
filterEnabled = true;
}
}
void RemoveMultiTargetFilter(const char *pattern, IPluginFunction *fun)
{
List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
while (iter != simpleMultis.end()) {
if ((*iter)->fun == fun && strcmp((*iter)->pattern.c_str(), pattern) == 0) {
delete (*iter);
iter = simpleMultis.erase(iter);
break;
}
iter++;
}
}
PlayerLogicHelpers()
: filterEnabled(false)
{
}
public: //ICommandTargetProcessor
bool ProcessCommandTarget(cmd_target_info_t *info)
{
List<SimpleMultiTargetFilter *>::iterator iter;
for (iter = simpleMultis.begin(); iter != simpleMultis.end(); iter++) {
SimpleMultiTargetFilter *smtf = (*iter);
if (strcmp(smtf->pattern.c_str(), info->pattern) == 0) {
CellArray *array = new CellArray(1);
HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
Handle_t hndl = handlesys->CreateHandleEx(htCellArray, array, &sec, NULL, NULL);
AutoHandleCloner ahc(hndl, sec);
if (ahc.getClone() == BAD_HANDLE) {
smcore.LogError("[SM] Could not allocate a handle (%s, %d)", __FILE__, __LINE__);
delete array;
return false;
}
smtf->fun->PushString(info->pattern);
smtf->fun->PushCell(ahc.getClone());
cell_t result = 0;
if (smtf->fun->Execute(&result) != SP_ERROR_NONE || !result)
return false;
IGamePlayer *pAdmin = info->admin
? playerhelpers->GetGamePlayer(info->admin)
: NULL;
info->num_targets = 0;
for (size_t i = 0; i < array->size(); i++) {
cell_t client = *array->at(i);
IGamePlayer *pClient = playerhelpers->GetGamePlayer(client);
if (pClient == NULL || !pClient->IsConnected())
continue;
if (playerhelpers->FilterCommandTarget(pAdmin, pClient, info->flags) ==
COMMAND_TARGET_VALID)
{
info->targets[info->num_targets++] = client;
if (info->num_targets >= unsigned(info->max_targets))
break;
}
}
info->reason = info->num_targets > 0
? COMMAND_TARGET_VALID
: COMMAND_TARGET_EMPTY_FILTER;
if (info->num_targets) {
smcore.strncopy(info->target_name, smtf->phrase.c_str(), info->target_name_maxlength);
info->target_name_style = smtf->phraseIsML
? COMMAND_TARGETNAME_ML
: COMMAND_TARGETNAME_RAW;
}
return true;
}
}
return false;
}
public: //SMGlobalClass
void OnSourceModAllInitialized()
{
pluginsys->AddPluginsListener(this);
}
void OnSourceModShutdown()
{
pluginsys->RemovePluginsListener(this);
if (filterEnabled) {
playerhelpers->UnregisterCommandTargetProcessor(this);
filterEnabled = false;
}
}
public: //IPluginsListener
void OnPluginDestroyed(IPlugin *plugin)
{
List<SimpleMultiTargetFilter *>::iterator iter = simpleMultis.begin();
while (iter != simpleMultis.end()) {
if ((*iter)->plugin != plugin) {
iter++;
} else {
delete (*iter);
iter = simpleMultis.erase(iter);
}
}
}
} s_PlayerLogicHelpers;
static cell_t
AddMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
{
IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
if (fun == NULL)
return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
char *pattern;
char *phrase;
ctx->LocalToString(params[1], &pattern);
ctx->LocalToString(params[3], &phrase);
bool phraseIsML = !!params[4];
IPlugin *plugin = pluginsys->FindPluginByContext(ctx->GetContext());
s_PlayerLogicHelpers.AddMultiTargetFilter(plugin, pattern, fun, phrase, phraseIsML);
return 1;
}
static cell_t
RemoveMultiTargetFilter(IPluginContext *ctx, const cell_t *params)
{
IPluginFunction *fun = ctx->GetFunctionById(funcid_t(params[2]));
if (fun == NULL)
return ctx->ThrowNativeError("Invalid function id (%X)", params[2]);
char *pattern;
ctx->LocalToString(params[1], &pattern);
s_PlayerLogicHelpers.RemoveMultiTargetFilter(pattern, fun);
return 1;
}
REGISTER_NATIVES(playernatives)
{
{"AddMultiTargetFilter", AddMultiTargetFilter},
{"RemoveMultiTargetFilter", RemoveMultiTargetFilter},
{NULL, NULL}
};
-342
View File
@@ -1,342 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 et :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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 <stdio.h>
#include <ctype.h>
#include <sm_platform.h>
#include "stringutil.h"
// We're in logic so we don't have this from the SDK.
#ifndef MIN
#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
#endif
const char *stristr(const char *str, const char *substr)
{
if (!*substr)
{
return ((char *)str);
}
char *needle = (char *)substr;
char *prevloc = (char *)str;
char *haystack = (char *)str;
while (*haystack)
{
if (tolower(*haystack) == tolower(*needle))
{
haystack++;
if (!*++needle)
{
return prevloc;
}
}
else
{
haystack = ++prevloc;
needle = (char *)substr;
}
}
return NULL;
}
unsigned int strncopy(char *dest, const char *src, size_t count)
{
if (!count)
{
return 0;
}
char *start = dest;
while ((*src) && (--count))
{
*dest++ = *src++;
}
*dest = '\0';
return (dest - start);
}
unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace, bool caseSensitive)
{
size_t searchLen = strlen(search);
size_t replaceLen = strlen(replace);
char *ptr = subject;
unsigned int total = 0;
while ((ptr = UTIL_ReplaceEx(ptr, maxlength, search, searchLen, replace, replaceLen, caseSensitive)) != NULL)
{
total++;
if (*ptr == '\0')
{
break;
}
}
return total;
}
/**
* NOTE: Do not edit this for the love of god unless you have
* read the test cases and understand the code behind each one.
* While I don't guarantee there aren't mistakes, I do guarantee
* that plugins will end up relying on tiny idiosyncrasies of this
* function, just like they did with AMX Mod X.
*
* There are explicitly more cases than the AMX Mod X version because
* we're not doing a blind copy. Each case is specifically optimized
* for what needs to be done. Even better, we don't have to error on
* bad buffer sizes. Instead, this function will smartly cut off the
* string in a way that pushes old data out.
*/
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen, bool caseSensitive)
{
char *ptr = subject;
size_t browsed = 0;
size_t textLen = strlen(subject);
/* It's not possible to search or replace */
if (searchLen > textLen)
{
return NULL;
}
/* Handle the case of one byte replacement.
* It's only valid in one case.
*/
if (maxLen == 1)
{
/* If the search matches and the replace length is 0,
* we can just terminate the string and be done.
*/
if ((caseSensitive ? strcmp(subject, search) : strcasecmp(subject, search)) == 0 && replaceLen == 0)
{
*subject = '\0';
return subject;
}
else
{
return NULL;
}
}
/* Subtract one off the maxlength so we can include the null terminator */
maxLen--;
while (*ptr != '\0' && (browsed <= textLen - searchLen))
{
/* See if we get a comparison */
if ((caseSensitive ? strncmp(ptr, search, searchLen) : strncasecmp(ptr, search, searchLen)) == 0)
{
if (replaceLen > searchLen)
{
/* First, see if we have enough space to do this operation */
if (maxLen - textLen < replaceLen - searchLen)
{
/* First, see if the replacement length goes out of bounds. */
if (browsed + replaceLen >= maxLen)
{
/* EXAMPLE CASE:
* Subject: AABBBCCC
* Buffer : 12 bytes
* Search : BBB
* Replace: DDDDDDDDDD
* OUTPUT : AADDDDDDDDD
* POSITION: ^
*/
/* If it does, we'll just bound the length and do a strcpy. */
replaceLen = maxLen - browsed;
/* Note, we add one to the final result for the null terminator */
strncopy(ptr, replace, replaceLen+1);
}
else
{
/* EXAMPLE CASE:
* Subject: AABBBCCC
* Buffer : 12 bytes
* Search : BBB
* Replace: DDDDDDD
* OUTPUT : AADDDDDDDCC
* POSITION: ^
*/
/* We're going to have some bytes left over... */
size_t origBytesToCopy = (textLen - (browsed + searchLen)) + 1;
size_t realBytesToCopy = (maxLen - (browsed + replaceLen)) + 1;
char *moveFrom = ptr + searchLen + (origBytesToCopy - realBytesToCopy);
char *moveTo = ptr + replaceLen;
/* First, move our old data out of the way. */
memmove(moveTo, moveFrom, realBytesToCopy);
/* Now, do our replacement. */
memcpy(ptr, replace, replaceLen);
}
}
else
{
/* EXAMPLE CASE:
* Subject: AABBBCCC
* Buffer : 12 bytes
* Search : BBB
* Replace: DDDD
* OUTPUT : AADDDDCCC
* POSITION: ^
*/
/* Yes, we have enough space. Do a normal move operation. */
char *moveFrom = ptr + searchLen;
char *moveTo = ptr + replaceLen;
/* First move our old data out of the way. */
size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
memmove(moveTo, moveFrom, bytesToCopy);
/* Now do our replacement. */
memcpy(ptr, replace, replaceLen);
}
}
else if (replaceLen < searchLen)
{
/* EXAMPLE CASE:
* Subject: AABBBCCC
* Buffer : 12 bytes
* Search : BBB
* Replace: D
* OUTPUT : AADCCC
* POSITION: ^
*/
/* If the replacement does not grow the string length, we do not
* need to do any fancy checking at all. Yay!
*/
char *moveFrom = ptr + searchLen; /* Start after the search pointer */
char *moveTo = ptr + replaceLen; /* Copy to where the replacement ends */
/* Copy our replacement in, if any */
if (replaceLen)
{
memcpy(ptr, replace, replaceLen);
}
/* Figure out how many bytes to move down, including null terminator */
size_t bytesToCopy = (textLen - (browsed + searchLen)) + 1;
/* Move the rest of the string down */
memmove(moveTo, moveFrom, bytesToCopy);
}
else
{
/* EXAMPLE CASE:
* Subject: AABBBCCC
* Buffer : 12 bytes
* Search : BBB
* Replace: DDD
* OUTPUT : AADDDCCC
* POSITION: ^
*/
/* We don't have to move anything around, just do a straight copy */
memcpy(ptr, replace, replaceLen);
}
return ptr + replaceLen;
}
ptr++;
browsed++;
}
return NULL;
}
size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr)
{
size_t written = 0;
size_t length = strlen(hexstr);
for (size_t i = 0; i < length; i++)
{
if (written >= maxlength)
break;
buffer[written++] = hexstr[i];
if (hexstr[i] == '\\' && hexstr[i + 1] == 'x')
{
if (i + 3 >= length)
continue;
/* Get the hex part. */
char s_byte[3];
int r_byte;
s_byte[0] = hexstr[i + 2];
s_byte[1] = hexstr[i + 3];
s_byte[2] = '\0';
/* Read it as an integer */
sscanf(s_byte, "%x", &r_byte);
/* Save the value */
buffer[written - 1] = r_byte;
/* Adjust index */
i += 3;
}
}
return written;
}
#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/')
void UTIL_StripExtension(const char *in, char *out, int outSize)
{
// Find the last dot. If it's followed by a dot or a slash, then it's part of a
// directory specifier like ../../somedir/./blah.
// scan backward for '.'
int end = strlen(in) - 1;
while (end > 0 && in[end] != '.' && !PATHSEPARATOR(in[end]))
{
--end;
}
if (end > 0 && !PATHSEPARATOR(in[end]) && end < outSize)
{
int nChars = MIN(end, outSize-1);
if (out != in)
{
memcpy(out, in, nChars);
}
out[nChars] = 0;
}
else
{
// nothing found
if (out != in)
{
strncopy(out, in, outSize);
}
}
}
-46
View File
@@ -1,46 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 et :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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_COMMON_STRINGUTIL_H_
#define _INCLUDE_SOURCEMOD_COMMON_STRINGUTIL_H_
const char *stristr(const char *str, const char *substr);
unsigned int strncopy(char *dest, const char *src, size_t count);
unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search,
const char *replace, bool caseSensitive = true);
char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen,
const char *replace, size_t replaceLen, bool caseSensitive = true);
size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr);
void UTIL_StripExtension(const char *in, char *out, int outSize);
#endif /* _INCLUDE_SOURCEMOD_COMMON_STRINGUTIL_H_ */

Some files were not shown because too many files have changed in this diff Show More