mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-12-06 18:08:31 +00:00
Update s2_sample_mm
Adds unified place to edit plugin metadata, plugin versioning with git support and multi-sdk support
This commit is contained in:
parent
5d2bb7e206
commit
aec2a1bb47
@ -1,20 +1,21 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os, sys
|
||||
import os, json, re, subprocess
|
||||
from ambuild2.frontend.v2_2.cpp.builders import TargetSuffix
|
||||
|
||||
# Edit the functions below for the extra functionality, the return should be
|
||||
# a list of path's to wanted locations
|
||||
def additional_libs(context, binary, sdk):
|
||||
def additionalLibs(context, binary, sdk):
|
||||
return [
|
||||
# Path should be relative either to hl2sdk folder or to build folder
|
||||
# 'path/to/lib/example.lib',
|
||||
]
|
||||
|
||||
def additional_defines(context, binary, sdk):
|
||||
def additionalDefines(context, binary, sdk):
|
||||
return [
|
||||
# 'EXAMPLE_DEFINE=2'
|
||||
]
|
||||
|
||||
def additional_includes(context, binary, sdk):
|
||||
def additionalIncludes(context, binary, sdk):
|
||||
return [
|
||||
# Path should be absolute only!
|
||||
# os.path.join(sdk['path'], 'game', 'server'),
|
||||
@ -22,12 +23,40 @@ def additional_includes(context, binary, sdk):
|
||||
# 'D:/absolute/path/to/include/folder/'
|
||||
]
|
||||
|
||||
def ResolveEnvPath(env, folder):
|
||||
def getGitHeadPath():
|
||||
curr_source = builder.currentSourcePath
|
||||
direct_head = os.path.join(curr_source, '.git', 'HEAD')
|
||||
if not os.path.exists(direct_head):
|
||||
return (None, None)
|
||||
|
||||
git_head_path = None
|
||||
with open(direct_head, 'r') as fp:
|
||||
head_contents = fp.read().strip()
|
||||
if re.search('^[a-fA-F0-9]{40}$', head_contents):
|
||||
git_head_path = direct_head
|
||||
else:
|
||||
git_state = head_contents.split(':')[1].strip()
|
||||
git_head_path = os.path.join(curr_source, '.git', git_state)
|
||||
if not os.path.exists(git_head_path):
|
||||
git_head_path = direct_head
|
||||
|
||||
return (direct_head, git_head_path)
|
||||
|
||||
def runAndReturn(argv):
|
||||
p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd = builder.currentSourcePath)
|
||||
output, ignored = p.communicate()
|
||||
rval = p.poll()
|
||||
if rval:
|
||||
raise subprocess.CalledProcessError(rval, argv)
|
||||
text = output.decode('utf8')
|
||||
return text.strip()
|
||||
|
||||
def resolveEnvPath(env, folder = None):
|
||||
if env in os.environ:
|
||||
path = os.environ[env]
|
||||
if os.path.isdir(path):
|
||||
return path
|
||||
else:
|
||||
elif folder is not None:
|
||||
head = os.getcwd()
|
||||
oldhead = None
|
||||
while head != None and head != oldhead:
|
||||
@ -38,35 +67,35 @@ def ResolveEnvPath(env, folder):
|
||||
head, tail = os.path.split(head)
|
||||
return None
|
||||
|
||||
def ResolveMMSRoot():
|
||||
def resolveMMSRoot():
|
||||
prenormalized_path = None
|
||||
if builder.options.mms_path:
|
||||
prenormalized_path = builder.options.mms_path
|
||||
else:
|
||||
prenormalized_path = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12')
|
||||
prenormalized_path = resolveEnvPath('MMSOURCE20', 'mmsource-2.0')
|
||||
if not prenormalized_path:
|
||||
prenormalized_path = ResolveEnvPath('MMSOURCE111', 'mmsource-1.11')
|
||||
prenormalized_path = resolveEnvPath('MMSOURCE_DEV', 'metamod-source')
|
||||
if not prenormalized_path:
|
||||
prenormalized_path = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
|
||||
if not prenormalized_path:
|
||||
prenormalized_path = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
|
||||
if not prenormalized_path:
|
||||
prenormalized_path = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
|
||||
prenormalized_path = resolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
|
||||
if not prenormalized_path or not os.path.isdir(prenormalized_path):
|
||||
raise Exception('Could not find a source copy of Metamod:Source')
|
||||
|
||||
return os.path.abspath(os.path.normpath(prenormalized_path))
|
||||
|
||||
mms_root = ResolveMMSRoot()
|
||||
mms_root = resolveMMSRoot()
|
||||
|
||||
def ResolveHL2SDKManifestsRoot():
|
||||
prenormalized_path = builder.options.hl2sdk_manifests
|
||||
def resolveHL2SDKManifestsRoot():
|
||||
prenormalized_path = None
|
||||
if builder.options.hl2sdk_manifests:
|
||||
prenormalized_path = builder.options.hl2sdk_manifests
|
||||
else:
|
||||
prenormalized_path = resolveEnvPath('HL2SDKMANIFESTS', 'hl2sdk-manifests')
|
||||
if not prenormalized_path or not os.path.isdir(prenormalized_path):
|
||||
raise Exception('Could not find a source copy of HL2SDK manifests')
|
||||
|
||||
return os.path.abspath(os.path.normpath(prenormalized_path))
|
||||
|
||||
hl2sdk_manifests_root = ResolveHL2SDKManifestsRoot()
|
||||
hl2sdk_manifests_root = resolveHL2SDKManifestsRoot()
|
||||
|
||||
SdkHelpers = builder.Eval(os.path.join(hl2sdk_manifests_root, 'SdkHelpers.ambuild'), {
|
||||
'Project': 'metamod'
|
||||
@ -79,18 +108,22 @@ class MMSPluginConfig(object):
|
||||
self.sdk_targets = []
|
||||
self.binaries = []
|
||||
self.mms_root = mms_root
|
||||
self.version_header_deps = []
|
||||
self.versionlib_deps = dict()
|
||||
self.all_targets = []
|
||||
self.target_archs = set()
|
||||
|
||||
if builder.options.plugin_name is not None:
|
||||
self.plugin_name = builder.options.plugin_name
|
||||
else:
|
||||
self.plugin_name = 'sample_mm'
|
||||
|
||||
if builder.options.plugin_alias is not None:
|
||||
self.plugin_alias = builder.options.plugin_alias
|
||||
else:
|
||||
self.plugin_alias = 'sample'
|
||||
self.metadata = {
|
||||
'name': 'sample_mm',
|
||||
'alias': 'sample',
|
||||
'display_name': 'Sample Plugin',
|
||||
'description': 'Sample basic plugin',
|
||||
'author': 'AlliedModders LLC',
|
||||
'url': 'http://www.sourcemm.net/',
|
||||
'log_tag': 'SAMPLE',
|
||||
'license': 'Public Domain',
|
||||
'version': '1.0.0.{{git-shorthash}}',
|
||||
}
|
||||
|
||||
if builder.options.targets:
|
||||
target_archs = builder.options.targets.split(',')
|
||||
@ -114,11 +147,15 @@ class MMSPluginConfig(object):
|
||||
|
||||
def findSdkPath(self, sdk_name):
|
||||
dir_name = 'hl2sdk-{}'.format(sdk_name)
|
||||
if builder.options.hl2sdk_root:
|
||||
sdk_path = os.path.abspath(os.path.normpath(os.path.join(builder.options.hl2sdk_root, dir_name)))
|
||||
hl2sdk_root = builder.options.hl2sdk_root
|
||||
if not hl2sdk_root:
|
||||
hl2sdk_root = resolveEnvPath('HL2SDKROOT')
|
||||
|
||||
if hl2sdk_root:
|
||||
sdk_path = os.path.abspath(os.path.normpath(os.path.join(hl2sdk_root, dir_name)))
|
||||
if os.path.exists(sdk_path):
|
||||
return sdk_path
|
||||
return ResolveEnvPath('HL2SDK{}'.format(sdk_name.upper()), dir_name)
|
||||
return resolveEnvPath('HL2SDK{}'.format(sdk_name.upper()), dir_name)
|
||||
|
||||
def detectSDKs(self):
|
||||
sdk_list = [s for s in builder.options.sdks.split(',') if s]
|
||||
@ -129,17 +166,133 @@ class MMSPluginConfig(object):
|
||||
self.sdk_manifests = SdkHelpers.sdk_manifests
|
||||
self.sdk_targets = SdkHelpers.sdk_targets
|
||||
|
||||
if len(self.sdks) > 1:
|
||||
raise Exception('Only one sdk at a time is supported, for multi-sdk approach use loader based solution.')
|
||||
for sdk_target in self.sdk_targets:
|
||||
if not sdk_target.sdk['source2']:
|
||||
raise Exception('Only Source2 games are supported by this script.')
|
||||
|
||||
def addVersioning(self, cxx):
|
||||
cxx.includes += [
|
||||
os.path.join(builder.buildPath, 'versioning')
|
||||
]
|
||||
|
||||
# Nasty hack to force use lib from ambuild in the vs solution
|
||||
# otherwise it'll be required to compile versionlib separately as a vs solution
|
||||
# which is very annoying to have
|
||||
versionlib = self.versionlib_deps[cxx.target.arch]
|
||||
if builder.options.generator == 'vs':
|
||||
target_path = TargetSuffix(cxx.target)
|
||||
cxx.postlink += [ os.path.join(builder.buildPath, 'versionlib', target_path, 'versionlib.lib') ]
|
||||
cxx.sourcedeps += [ versionlib ]
|
||||
else:
|
||||
cxx.postlink += [ versionlib ]
|
||||
|
||||
cxx.sourcedeps += self.version_header_deps
|
||||
|
||||
def generateVersioningHeaders(self):
|
||||
builder.SetBuildFolder('/')
|
||||
|
||||
# Generate metadata plugin header, which would cause plugin recompilation if changed
|
||||
self.version_header_deps += [
|
||||
builder.AddOutputFile(os.path.join('versioning', 'version_gen.h'), f"""
|
||||
#ifndef _PLUGIN_METADATA_INFORMATION_H_
|
||||
#define _PLUGIN_METADATA_INFORMATION_H_
|
||||
|
||||
#define PLUGIN_NAME \"{self.metadata['name']}\"
|
||||
#define PLUGIN_ALIAS \"{self.metadata['alias']}\"
|
||||
#define PLUGIN_DISPLAY_NAME \"{self.metadata['display_name']}\"
|
||||
#define PLUGIN_DESCRIPTION \"{self.metadata['description']}\"
|
||||
#define PLUGIN_AUTHOR \"{self.metadata['author']}\"
|
||||
#define PLUGIN_URL \"{self.metadata['url']}\"
|
||||
#define PLUGIN_LOGTAG \"{self.metadata['log_tag']}\"
|
||||
#define PLUGIN_LICENSE \"{self.metadata['license']}\"
|
||||
|
||||
extern const char* PLUGIN_FULL_VERSION;
|
||||
extern const char* PLUGIN_REVISION_SHORT;
|
||||
extern const char* PLUGIN_REVISION_LONG;
|
||||
extern const char* PLUGIN_REVISION_COUNT;
|
||||
|
||||
#endif /* _PLUGIN_METADATA_INFORMATION_H_ */
|
||||
""".encode('utf-8'))
|
||||
]
|
||||
|
||||
def generateVersionLib(self):
|
||||
builder.SetBuildFolder('/')
|
||||
|
||||
version = self.metadata['version']
|
||||
|
||||
direct_head, git_head_path = getGitHeadPath()
|
||||
shorthash = longhash = revision_count = '0'
|
||||
if direct_head and git_head_path:
|
||||
# Force track head changes to trigger recompilation
|
||||
builder.AddConfigureFile(git_head_path)
|
||||
builder.AddConfigureFile(direct_head)
|
||||
|
||||
revision_count = runAndReturn(['git', 'rev-list', '--count', 'HEAD'])
|
||||
revision_hash = runAndReturn(['git', 'log', '--pretty=format:%h:%H', '-n', '1'])
|
||||
shorthash, longhash = revision_hash.split(':')
|
||||
|
||||
if '{{git-shorthash}}' in version:
|
||||
version = version.replace('{{git-shorthash}}', shorthash)
|
||||
|
||||
if '{{git-longhash}}' in version:
|
||||
version = version.replace('{{git-longhash}}', longhash)
|
||||
|
||||
if '{{git-count}}' in version:
|
||||
version = version.replace('{{git-count}}', revision_count)
|
||||
|
||||
# For the version strings and git hashes compile that to a static library instead,
|
||||
# to prevent a full recompilation on version/git changes which would only trigger this cpp
|
||||
# and linking to be performed
|
||||
versionlib_cpp = builder.AddOutputFile(os.path.join('versioning', 'versionlib.cpp'), f"""
|
||||
const char *PLUGIN_FULL_VERSION = \"{version}\";
|
||||
const char *PLUGIN_REVISION_SHORT = \"{shorthash}\";
|
||||
const char *PLUGIN_REVISION_LONG = \"{longhash}\";
|
||||
const char *PLUGIN_REVISION_COUNT = \"{revision_count}\";
|
||||
""".encode('utf-8'))
|
||||
|
||||
for cxx in self.all_targets:
|
||||
lib = cxx.StaticLibrary(f'versionlib_{cxx.target.arch}')
|
||||
|
||||
self.configureCXX(lib.compiler)
|
||||
|
||||
# VS generator doesn't like having non string sources, but we need that for correct
|
||||
# dependency tracking
|
||||
if builder.options.generator == 'vs':
|
||||
lib.sources += [ os.path.join(builder.buildPath, 'versioning', 'versionlib.cpp') ]
|
||||
lib.compiler.sourcedeps += [ versionlib_cpp ]
|
||||
else:
|
||||
lib.sources += [ versionlib_cpp ]
|
||||
|
||||
self.versionlib_deps[cxx.target.arch] = builder.Add(lib).binary
|
||||
|
||||
def configure(self):
|
||||
for cxx in self.all_targets:
|
||||
if cxx.target.arch not in ['x86', 'x86_64']:
|
||||
raise Exception('Unknown target architecture: {0}'.format(arch))
|
||||
|
||||
self.configure_cxx(cxx)
|
||||
self.configureCXX(cxx)
|
||||
|
||||
def configure_cxx(self, cxx):
|
||||
def configurePluginMetadata(self):
|
||||
plugin_metadata_path = os.path.join(builder.sourcePath, 'plugin-metadata.json')
|
||||
|
||||
if not os.path.exists(plugin_metadata_path):
|
||||
with open(plugin_metadata_path, 'w') as f:
|
||||
json.dump(self.metadata, f, indent = 4)
|
||||
else:
|
||||
obj = None
|
||||
with open(plugin_metadata_path, 'r') as f:
|
||||
obj = json.load(f)
|
||||
self.metadata.update(obj)
|
||||
|
||||
# If some fields are missing, add them back in from a sample metadata
|
||||
if len(obj) < len(self.metadata):
|
||||
with open(plugin_metadata_path, 'w') as f:
|
||||
json.dump(self.metadata, f, indent = 4)
|
||||
|
||||
self.generateVersioningHeaders()
|
||||
self.generateVersionLib()
|
||||
|
||||
def configureCXX(self, cxx):
|
||||
if cxx.behavior == 'gcc':
|
||||
cxx.defines += [
|
||||
'stricmp=strcasecmp',
|
||||
@ -168,7 +321,6 @@ class MMSPluginConfig(object):
|
||||
cxx.cxxflags += ['-fvisibility-inlines-hidden']
|
||||
cxx.cxxflags += [
|
||||
'-fno-exceptions',
|
||||
'-fno-rtti',
|
||||
'-fno-threadsafe-statics',
|
||||
'-Wno-non-virtual-dtor',
|
||||
'-Wno-overloaded-virtual',
|
||||
@ -265,12 +417,6 @@ class MMSPluginConfig(object):
|
||||
elif cxx.target.platform == 'windows':
|
||||
cxx.defines += ['WIN32', '_WINDOWS']
|
||||
|
||||
# Finish up.
|
||||
# Custom defines here
|
||||
cxx.defines += [ ]
|
||||
# Custom includes here
|
||||
cxx.includes += [ ]
|
||||
|
||||
def Library(self, cxx, name):
|
||||
binary = cxx.Library(name)
|
||||
return binary
|
||||
@ -279,14 +425,15 @@ class MMSPluginConfig(object):
|
||||
binary = self.Library(compiler, name)
|
||||
mms_core_path = os.path.join(self.mms_root, 'core')
|
||||
cxx = binary.compiler
|
||||
|
||||
self.addVersioning(cxx)
|
||||
|
||||
cxx.cxxincludes += [
|
||||
os.path.join(context.currentSourcePath),
|
||||
os.path.join(mms_core_path),
|
||||
os.path.join(mms_core_path),
|
||||
os.path.join(mms_core_path, 'sourcehook'),
|
||||
]
|
||||
|
||||
defines = []
|
||||
for other_sdk in self.sdk_manifests:
|
||||
cxx.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])]
|
||||
|
||||
@ -299,14 +446,16 @@ class MMSPluginConfig(object):
|
||||
|
||||
SdkHelpers.configureCxx(context, binary, sdk)
|
||||
|
||||
cxx.linkflags += additional_libs(context, binary, sdk)
|
||||
cxx.defines += additional_defines(context, binary, sdk)
|
||||
cxx.cxxincludes += additional_includes(context, binary, sdk)
|
||||
cxx.linkflags += additionalLibs(context, binary, sdk)
|
||||
cxx.defines += additionalDefines(context, binary, sdk)
|
||||
cxx.cxxincludes += additionalIncludes(context, binary, sdk)
|
||||
context.AddConfigureFile(os.path.join(context.currentSourcePath, 'plugin-metadata.json'))
|
||||
|
||||
return binary
|
||||
|
||||
MMSPlugin = MMSPluginConfig()
|
||||
MMSPlugin.detectSDKs()
|
||||
MMSPlugin.configurePluginMetadata()
|
||||
MMSPlugin.configure()
|
||||
|
||||
BuildScripts = [
|
||||
|
||||
@ -1,19 +1,14 @@
|
||||
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
|
||||
import os
|
||||
|
||||
# Here only one sdk should be available to generate only one executable in the end,
|
||||
# as multi-sdk loading isn't supported out of the box by metamod, and would require specifying the full path in the vdf
|
||||
# which in the end would ruin the multi-platform (unix, win etc) loading by metamod as it won't be able to append platform specific extension
|
||||
# so just fall back to the single binary.
|
||||
# Multi-sdk solutions should be manually loaded with a custom plugin loader (examples being sourcemod, stripper:source)
|
||||
for sdk_target in MMSPlugin.sdk_targets:
|
||||
sdk = sdk_target.sdk
|
||||
cxx = sdk_target.cxx
|
||||
|
||||
binary = MMSPlugin.HL2Library(builder, cxx, MMSPlugin.plugin_name, sdk)
|
||||
binary = MMSPlugin.HL2Library(builder, cxx, f'{MMSPlugin.metadata["name"]}.{sdk["name"]}', sdk)
|
||||
|
||||
binary.sources += [
|
||||
'sample_mm.cpp',
|
||||
'src/plugin.cpp',
|
||||
]
|
||||
|
||||
binary.custom = [builder.tools.Protoc(protoc = sdk_target.protoc, sources = [
|
||||
|
||||
@ -1,48 +1,114 @@
|
||||
# vim: set ts=2 sw=2 tw=99 noet ft=python:
|
||||
import os
|
||||
import glob
|
||||
|
||||
builder.SetBuildFolder('package')
|
||||
|
||||
metamod_folder = builder.AddFolder(os.path.join('addons', 'metamod'))
|
||||
bin_folder_path = os.path.join('addons', MMSPlugin.plugin_name, 'bin')
|
||||
bin_folder = builder.AddFolder(bin_folder_path)
|
||||
class SDKPackage:
|
||||
sdk_name = None
|
||||
|
||||
for cxx in MMSPlugin.all_targets:
|
||||
if cxx.target.arch == 'x86_64':
|
||||
if cxx.target.platform == 'windows':
|
||||
bin64_folder_path = os.path.join('addons', MMSPlugin.plugin_name, 'bin', 'win64')
|
||||
bin64_folder = builder.AddFolder(bin64_folder_path)
|
||||
elif cxx.target.platform == 'linux':
|
||||
bin64_folder_path = os.path.join('addons', MMSPlugin.plugin_name, 'bin', 'linuxsteamrt64')
|
||||
bin64_folder = builder.AddFolder(bin64_folder_path)
|
||||
elif cxx.target.platform == 'mac':
|
||||
bin64_folder_path = os.path.join('addons', MMSPlugin.plugin_name, 'bin', 'osx64')
|
||||
bin64_folder = builder.AddFolder(bin64_folder_path)
|
||||
plugin_folder_path = None
|
||||
plugin_folder = None
|
||||
|
||||
metamod_path = None
|
||||
metamod = None
|
||||
|
||||
bin_path = None
|
||||
bin = None
|
||||
|
||||
def __init__(self, cxx, sdk_name):
|
||||
self.sdk_name = sdk_name
|
||||
|
||||
self.plugin_folder_path = os.path.join(self.sdk_name, 'addons', MMSPlugin.metadata['name'])
|
||||
self.plugin_folder = builder.AddFolder(self.plugin_folder_path)
|
||||
|
||||
self.metamod_path = os.path.join(self.sdk_name, 'addons', 'metamod')
|
||||
self.metamod = builder.AddFolder(self.metamod_path)
|
||||
|
||||
self.addBinFolder(cxx)
|
||||
self.generateVDF()
|
||||
|
||||
def addBinFolder(self, cxx):
|
||||
platform64_path_map = {
|
||||
'windows': 'win64',
|
||||
'linux': 'linuxsteamrt64',
|
||||
'mac': 'osx64'
|
||||
}
|
||||
|
||||
if cxx.target.arch == 'x86_64':
|
||||
self.bin_path = os.path.join(self.plugin_folder_path, 'bin', platform64_path_map[cxx.target.platform])
|
||||
else:
|
||||
self.bin_path = os.path.join(self.plugin_folder_path, 'bin')
|
||||
|
||||
self.bin = builder.AddFolder(self.bin_path)
|
||||
|
||||
def generateVDF(self):
|
||||
vdf_content = '"Metamod Plugin"\n'
|
||||
vdf_content += '{\n'
|
||||
vdf_content += f'\t"alias"\t"{MMSPlugin.metadata["alias"]}"\n'
|
||||
vdf_content += f'\t"file"\t"{os.path.join(os.path.relpath(self.bin_path, self.sdk_name), MMSPlugin.metadata["name"])}"\n'
|
||||
vdf_content += '}'
|
||||
|
||||
builder.AddOutputFile(os.path.join(self.metamod_path, f'{MMSPlugin.metadata["name"]}.vdf'), vdf_content.encode('utf8'))
|
||||
|
||||
def addBinary(self, binary):
|
||||
(_, plugin_bin_name) = os.path.split(binary.path)
|
||||
plugin_bin_ext = os.path.splitext(plugin_bin_name)[1]
|
||||
|
||||
builder.AddCopy(binary, os.path.join(self.bin_path, MMSPlugin.metadata['name'] + plugin_bin_ext))
|
||||
|
||||
# Adds file relative to plugin folder
|
||||
def addFile(self, file_path, result_path = None):
|
||||
if not os.path.isabs(file_path):
|
||||
file_path = os.path.join(builder.sourcePath, file_path)
|
||||
|
||||
if result_path is None:
|
||||
result_path = os.path.join(self.plugin_folder_path, os.path.basename(file_path))
|
||||
else:
|
||||
result_path = os.path.join(self.plugin_folder_path, result_path)
|
||||
|
||||
builder.AddFolder(os.path.dirname(result_path))
|
||||
builder.AddCopy(file_path, result_path)
|
||||
|
||||
# Adds directory relative to plugins folder
|
||||
def addFolder(self, folder_path, result_path = None, search_ext = '*', recursive = True):
|
||||
if not os.path.isabs(folder_path):
|
||||
folder_path = os.path.join(builder.sourcePath, folder_path)
|
||||
|
||||
if result_path is None:
|
||||
result_path = os.path.join(self.plugin_folder_path, os.path.basename(folder_path))
|
||||
|
||||
search_param = f'*.{search_ext}'
|
||||
if recursive:
|
||||
search_param = os.path.join('**', search_param)
|
||||
|
||||
for file in glob.glob(os.path.join(folder_path, search_param), recursive = recursive):
|
||||
self.addFile(file, os.path.join(result_path, os.path.relpath(file, folder_path)))
|
||||
|
||||
packages = dict()
|
||||
|
||||
for sdk_target in MMSPlugin.sdk_targets:
|
||||
sdk = sdk_target.sdk
|
||||
cxx = sdk_target.cxx
|
||||
|
||||
packages[sdk['name']] = SDKPackage(cxx, sdk['name'])
|
||||
|
||||
pdb_list = []
|
||||
for task in MMSPlugin.binaries:
|
||||
# This hardly assumes there's only 1 targetted platform and would be overwritten
|
||||
# with whatever comes last if multiple are used!
|
||||
with open(os.path.join(builder.buildPath, MMSPlugin.plugin_name + '.vdf'), 'w') as fp:
|
||||
fp.write('"Metamod Plugin"\n')
|
||||
fp.write('{\n')
|
||||
fp.write(f'\t"alias"\t"{MMSPlugin.plugin_alias}"\n')
|
||||
if task.target.arch == 'x86_64':
|
||||
fp.write(f'\t"file"\t"{os.path.join(bin64_folder_path, MMSPlugin.plugin_name)}"\n')
|
||||
else:
|
||||
fp.write(f'\t"file"\t"{os.path.join(bin_folder_path, MMSPlugin.plugin_name)}"\n')
|
||||
fp.write('}\n')
|
||||
# Determine which sdk this binary belongs to since we encode it in its name
|
||||
binary_filename = os.path.splitext(os.path.basename(task.binary.path))[0]
|
||||
sdk_name = binary_filename.split('.')[-1]
|
||||
|
||||
packages[sdk_name].addBinary(task.binary)
|
||||
|
||||
if task.target.arch == 'x86_64':
|
||||
builder.AddCopy(task.binary, bin64_folder)
|
||||
else:
|
||||
builder.AddCopy(task.binary, bin_folder)
|
||||
# Add custom stuff here
|
||||
# Examples:
|
||||
# packages[sdk_name].addFolder('some_folder_with_files')
|
||||
# packages[sdk_name].addFile('configs/config.cfg', 'other/new_name_for_a_config.cfg')
|
||||
|
||||
if task.debug:
|
||||
pdb_list.append(task.debug)
|
||||
|
||||
builder.AddCopy(os.path.join(builder.buildPath, MMSPlugin.plugin_name + '.vdf'), metamod_folder)
|
||||
|
||||
# Generate PDB info.
|
||||
with open(os.path.join(builder.buildPath, 'pdblog.txt'), 'wt') as fp:
|
||||
for line in pdb_list:
|
||||
|
||||
@ -1,35 +1,58 @@
|
||||
## Manual building example
|
||||
|
||||
### Prerequisites
|
||||
* [hl2sdk](https://github.com/alliedmodders/hl2sdk) of the game you plan on writing plugin for (the current plugin build scripts allows only for 1 sdk and 1 platform at a time!);
|
||||
* [hl2sdk](https://github.com/alliedmodders/hl2sdk) of games you plan on writing plugin for (this sample only supports Source2 based games);
|
||||
* [hl2sdk-manifests](https://github.com/alliedmodders/hl2sdk-manifests);
|
||||
* [metamod-source](https://github.com/alliedmodders/metamod-source);
|
||||
* [python3](https://www.python.org/)
|
||||
* [ambuild](https://github.com/alliedmodders/ambuild), make sure ``ambuild`` command is available via the ``PATH`` environment variable;
|
||||
|
||||
### Setting up
|
||||
* Edit ``plugin-metadata.json`` with your plugin details (if you don't have that file run configure step once to generate it), where:
|
||||
* ``name``: Plugin name which is used for the resulting binary name and folder naming scheme;
|
||||
* ``alias``: Plugin alias which is used as a short hand name to load, unload, list info etc via the [metamod-source](https://github.com/alliedmodders/metamod-source) menu (example being ``meta unload sample``, where ``sample`` is the alias);
|
||||
* ``log_tag``: Plugin log tag, used for logging purposes;
|
||||
* Additional plugin info used when printing plugin info by ``meta list`` or alike:
|
||||
* ``display_name``: Display name;
|
||||
* ``description``: Description;
|
||||
* ``author``: Author;
|
||||
* ``url``: Url link;
|
||||
* ``license``: License;
|
||||
* ``version``: Version string, can also contain git revisions, like ``"1.0.0.{{git-shorthash}}"``:
|
||||
* ``{{git-shorthash}}``: Git shorthash of head commit (7 symbols wide);
|
||||
* ``{{git-longhash}}``: Git full hash of head commit;
|
||||
* ``{{git-count}}``: Git commit count to current head;
|
||||
* Would be 0 for all cases if no git info was located;
|
||||
* ``mkdir build`` & ``cd build`` in the root of the plugin folder.
|
||||
* Open the [MSVC developer console](https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line) with the correct platform (x86 or x86_64) that you plan on targetting.
|
||||
* Run ``python3 ../configure.py --plugin-name={PLUGIN_NAME} --plugin-alias={PLUGIN_ALIAS} -s {SDKNAME} --targets={TARGET} --mms_path={MMS_PATH} --hl2sdk-root {HL2SDKROOT} --hl2sdk-manifests {HL2SDKMANIFESTS} `` where:
|
||||
* ``{PLUGIN_NAME}`` should be the plugin name which is used for the resulting binary name and folder naming scheme (this doesn't affect the plugin name you'd see in the plugin list if you don't modify the base plugin functions);
|
||||
* ``{PLUGIN_ALIAS}`` should be used to set the plugin alias that is used as a short hand version to load, unload, list info etc via the metamod-source menu (example being ``meta unload sample``, where ``sample`` is the alias);
|
||||
* ``{SDKNAME}`` should be the hl2sdk game name that you are building for;
|
||||
* ``{TARGET}`` should be the target platform you are targeting (``x86`` or ``x86_64``);
|
||||
* ``{MMS_PATH}`` should point to the root of the metamod-source folder;
|
||||
* ``{HL2SDKROOT}`` should point to the root of the hl2sdk's folders, note that it should **not** point to the actual ``hl2sdk-GAME`` folder but a root parent of it;
|
||||
* ``{HL2SDKMANIFESTS}`` should point to the root of a clone of the https://github.com/alliedmodders/hl2sdk-manifests repository. It is suggested that you use a submodule for this, as this folder must live within your project for AMBuild to be able to consume the helper script within;
|
||||
* Alternatively ``{MMS_PATH}`` & ``{HL2SDKROOT}`` could be put as a ``PATH`` environment variables, like ``MMSOURCE112=D:\mmsource-1.12`` & ``HL2SDKCS2=D:\hl2sdks\hl2sdk-cs2`` (note the metamod version and that here hl2sdk environment variable should point directly to the game's hl2sdk folder and not to the root of it!)
|
||||
* Example: ``python3 ../configure.py --plugin-name=sample_mm --plugin-alias=sample -s cs2 --targets=x86_64 --mms_path=D:\mmsource-1.12 --hl2sdk-root=D:\hl2sdks``
|
||||
* Run ``python3 ../configure.py -s {SDKNAMES} --targets={TARGET} --mms_path={MMS_PATH} --hl2sdk-root {HL2SDKROOT} --hl2sdk-manifests {HL2SDKMANIFESTS}`` where:
|
||||
* ``{SDKNAMES}`` should be the hl2sdk game names that you are building for, separated by comma (e.g. ``cs2,dota``);
|
||||
* ``{TARGET}`` should be the target platform you are targeting (``x86`` or ``x86_64``, source2 games are mostly ``x86_64``);
|
||||
* ``{MMS_PATH}`` should point to the root of the [metamod-source](https://github.com/alliedmodders/metamod-source) folder;
|
||||
* ``{HL2SDKROOT}`` should point to the root of the [hl2sdk](https://github.com/alliedmodders/hl2sdk)'s folders, note that it should **not** point to the actual ``hl2sdk-GAME`` folder but a parent directory of it (Game specific folders inside the root needs to be named as ``hl2sdk-GAME`` where ``GAME`` is a game name like ``cs2``);
|
||||
* ``{HL2SDKMANIFESTS}`` should point to the root of a clone of the [hl2sdk-manifests](https://github.com/alliedmodders/hl2sdk-manifests) repository.
|
||||
> **Example**: ``python3 ../configure.py -s cs2,dota --targets=x86_64 --mms_path=D:\mmsource-1.12 --hl2sdk-root=D:\hl2sdks``
|
||||
* If the process of configuring was successful, you should be able to run ``ambuild`` in the ``\build`` folder to compile the plugin.
|
||||
* Once the plugin is compiled the files would be packaged and placed in ``\build\package`` folder.
|
||||
* To run the plugin on the server, place the files preserving the layout provided in ``\package``. Be aware that plugins get loaded either by corresponding ``.vdf`` files (automatic step) in the metamod folder, or by listing them in ``addons/metamod/metaplugins.ini`` file (manual step).
|
||||
* Once the plugin is compiled the files would be packaged and placed in ``\build\package`` folder in its own per game subfolders.
|
||||
* To run the plugin on the server, place the files preserving the layout provided in ``\package\{game}``. Be aware that plugins get loaded either by corresponding ``.vdf`` files (automatic step) in the metamod folder, or by listing them in ``addons\metamod\metaplugins.ini`` file (manual step).
|
||||
|
||||
### Environment variables setup
|
||||
To quickly configure various projects, it's recommended to setup an environment variables to point to certain locations used for building:
|
||||
* ``MMSOURCE20``/``MMSOURCE_DEV`` should point to root of [metamod-source](https://www.metamodsource.net/downloads.php?branch=dev) of the version 2.0 and higher;
|
||||
* ``HL2SDKMANIFESTS`` should point to [hl2sdk-manifests](https://github.com/alliedmodders/hl2sdk-manifests) directory.
|
||||
* ``HL2SDKROOT`` should point to root folder where [hl2sdk](https://github.com/alliedmodders/hl2sdk) directories are in;
|
||||
* Alternatively ``HL2SDK{GAME}`` (e.g. ``HL2SDKCS2``) can be used to point to game specific [hl2sdk](https://github.com/alliedmodders/hl2sdk) directories, in which case a direct path to its root needs to be provided;
|
||||
> [!NOTE]
|
||||
> If you have ``HL2SDKROOT`` defined as well, it will take priority over game specific environment variables!
|
||||
|
||||
## Points of interest
|
||||
* To generate the VS solution of the plugin with the correct setup, use ``python3 ../configure {CONFIGURE_OPTIONS} --gen=vs``, where ``{CONFIGURE_OPTIONS}`` is your default configuring options that are used when building. As a result ``.vcxproj`` file would be created in the folder where the command was executed.
|
||||
* To update which ``.cpp`` files gets compiled in or to add new ones, look at ``AMBuilder`` script which has the ``sample_mm.cpp`` being built initially, you can add or edit this however you want to, running ``ambuild`` after editing this script would automatically catch up the changes, no need for the reconfiguration.
|
||||
* To change the name/version/author/etc that's displayed in the metamod-source menu, make sure to correctly overload and provide the wanted info to the metamod-source, like ``ISmmPlugin::GetAuthor``, ``ISmmPlugin::GetName`` and so on.
|
||||
* To generate the VS solution of the plugin with the correct setup, use ``python3 ../configure {CONFIGURE_OPTIONS} --gen=vs --vs-version=2022``, where ``{CONFIGURE_OPTIONS}`` is your default configuring options that are used when building. As a result ``.vcxproj`` files would be created in the folder where the command was executed separately for each sdk game provided.
|
||||
* To update which ``.cpp`` files gets compiled in or to add new ones, look at ``AMBuilder`` script which has the ``src/plugin.cpp`` being built initially, you can add or edit this however you want to, running ``ambuild`` after editing this script would automatically catch up the changes, no need for the reconfiguration step.
|
||||
* To add new ``.proto`` headers to the project, look at ``AMBuilder`` script which has ``os.path.join(sdk['path'], 'common', 'network_connection.proto')`` being built initially, you can add or edit this however you want to as with cpp files.
|
||||
* There are also additional arguments for the configuration step that aren't covered here, you can see them by running ``python3 ../configure -h`` from within the ``\build`` folder.
|
||||
* To add additional linking ``.libs``/defines/include directories, open ``AMBuildScript`` and at the top edit corresponding arrays.
|
||||
* Sometimes there could be problems with ``ambuild`` not catching up the changes in ``.h`` files, thus producing incorrect (outdated) binaries or even doesn't compile with the new changes. As there's [no full rebuild option](https://github.com/alliedmodders/ambuild/issues/145) to combat this, go to the ``/build`` folder and locate the folder named after the plugin name you've used, deleting that folder and building after should provide the clean build of the project and the described issues should be eliminated.
|
||||
* To add new files to the package output, like configs or any other, you can edit ``PackageScript`` at ``Add custom stuff here`` marker.
|
||||
|
||||
|
||||
## For more information on compiling and reading the plugin's source code, see:
|
||||
|
||||
@ -19,10 +19,6 @@ if ambuild_version.startswith('2.1'):
|
||||
sys.exit(1)
|
||||
|
||||
parser = run.BuildParser(sourcePath=sys.path[0], api='2.2')
|
||||
parser.options.add_argument('-n', '--plugin-name', type=str, dest='plugin_name', default=None,
|
||||
help='Plugin name')
|
||||
parser.options.add_argument('-a', '--plugin-alias', type=str, dest='plugin_alias', default=None,
|
||||
help='Plugin alias')
|
||||
parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
|
||||
help='Root search folder for HL2SDKs')
|
||||
parser.options.add_argument('--hl2sdk-manifests', type=str, dest='hl2sdk_manifests', default=None,
|
||||
|
||||
11
samples/s2_sample_mm/plugin-metadata.json
Normal file
11
samples/s2_sample_mm/plugin-metadata.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "sample_mm",
|
||||
"alias": "sample",
|
||||
"display_name": "Sample Plugin",
|
||||
"description": "Sample basic plugin",
|
||||
"author": "AlliedModders LLC",
|
||||
"url": "http://www.sourcemm.net/",
|
||||
"log_tag": "SAMPLE",
|
||||
"license": "Public Domain",
|
||||
"version": "1.0.0.{{git-shorthash}}"
|
||||
}
|
||||
@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sample_mm.h"
|
||||
#include "plugin.h"
|
||||
#include "iserver.h"
|
||||
|
||||
SH_DECL_HOOK3_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool, bool, bool);
|
||||
@ -27,7 +27,7 @@ SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *,
|
||||
|
||||
SH_DECL_HOOK2_void( IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CPlayerSlot, const CCommand & );
|
||||
|
||||
SamplePlugin g_SamplePlugin;
|
||||
MMSPlugin g_ThisPlugin;
|
||||
IServerGameDLL *server = NULL;
|
||||
IServerGameClients *gameclients = NULL;
|
||||
IVEngineServer *engine = NULL;
|
||||
@ -63,8 +63,8 @@ CON_COMMAND_F(sample_command, "Sample command", FCVAR_NONE)
|
||||
META_CONPRINTF( "Sample command called by %d. Command: %s\n", context.GetPlayerSlot(), args.GetCommandString() );
|
||||
}
|
||||
|
||||
PLUGIN_EXPOSE(SamplePlugin, g_SamplePlugin);
|
||||
bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||
PLUGIN_EXPOSE(MMSPlugin, g_ThisPlugin);
|
||||
bool MMSPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||
{
|
||||
PLUGIN_SAVEVARS();
|
||||
|
||||
@ -82,14 +82,14 @@ bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen,
|
||||
|
||||
META_CONPRINTF( "Starting plugin.\n" );
|
||||
|
||||
SH_ADD_HOOK(IServerGameDLL, GameFrame, server, SH_MEMBER(this, &SamplePlugin::Hook_GameFrame), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientActive, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientActive), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientDisconnect, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientDisconnect), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientPutInServer, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientPutInServer), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientSettingsChanged, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientSettingsChanged), false);
|
||||
SH_ADD_HOOK(IServerGameClients, OnClientConnected, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_OnClientConnected), false);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientConnect, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientConnect), false);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientCommand), false);
|
||||
SH_ADD_HOOK(IServerGameDLL, GameFrame, server, SH_MEMBER(this, &MMSPlugin::Hook_GameFrame), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientActive, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientActive), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientDisconnect, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientDisconnect), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientPutInServer, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientPutInServer), true);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientSettingsChanged, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientSettingsChanged), false);
|
||||
SH_ADD_HOOK(IServerGameClients, OnClientConnected, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_OnClientConnected), false);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientConnect, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientConnect), false);
|
||||
SH_ADD_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientCommand), false);
|
||||
|
||||
META_CONPRINTF( "All hooks started!\n" );
|
||||
|
||||
@ -173,65 +173,65 @@ bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SamplePlugin::Unload(char *error, size_t maxlen)
|
||||
bool MMSPlugin::Unload(char *error, size_t maxlen)
|
||||
{
|
||||
SH_REMOVE_HOOK(IServerGameDLL, GameFrame, server, SH_MEMBER(this, &SamplePlugin::Hook_GameFrame), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientActive, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientActive), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientDisconnect), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientPutInServer, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientPutInServer), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientSettingsChanged, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientSettingsChanged), false);
|
||||
SH_REMOVE_HOOK(IServerGameClients, OnClientConnected, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_OnClientConnected), false);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientConnect, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientConnect), false);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &SamplePlugin::Hook_ClientCommand), false);
|
||||
SH_REMOVE_HOOK(IServerGameDLL, GameFrame, server, SH_MEMBER(this, &MMSPlugin::Hook_GameFrame), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientActive, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientActive), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientDisconnect), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientPutInServer, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientPutInServer), true);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientSettingsChanged, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientSettingsChanged), false);
|
||||
SH_REMOVE_HOOK(IServerGameClients, OnClientConnected, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_OnClientConnected), false);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientConnect, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientConnect), false);
|
||||
SH_REMOVE_HOOK(IServerGameClients, ClientCommand, gameclients, SH_MEMBER(this, &MMSPlugin::Hook_ClientCommand), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SamplePlugin::AllPluginsLoaded()
|
||||
void MMSPlugin::AllPluginsLoaded()
|
||||
{
|
||||
/* This is where we'd do stuff that relies on the mod or other plugins
|
||||
* being initialized (for example, cvars added and events registered).
|
||||
*/
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_ClientActive( CPlayerSlot slot, bool bLoadGame, const char *pszName, uint64 xuid )
|
||||
void MMSPlugin::Hook_ClientActive( CPlayerSlot slot, bool bLoadGame, const char *pszName, uint64 xuid )
|
||||
{
|
||||
META_CONPRINTF( "Hook_ClientActive(%d, %d, \"%s\", %d)\n", slot, bLoadGame, pszName, xuid );
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_ClientCommand( CPlayerSlot slot, const CCommand &args )
|
||||
void MMSPlugin::Hook_ClientCommand( CPlayerSlot slot, const CCommand &args )
|
||||
{
|
||||
META_CONPRINTF( "Hook_ClientCommand(%d, \"%s\")\n", slot, args.GetCommandString() );
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_ClientSettingsChanged( CPlayerSlot slot )
|
||||
void MMSPlugin::Hook_ClientSettingsChanged( CPlayerSlot slot )
|
||||
{
|
||||
META_CONPRINTF( "Hook_ClientSettingsChanged(%d)\n", slot );
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_OnClientConnected( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, const char *pszAddress, bool bFakePlayer )
|
||||
void MMSPlugin::Hook_OnClientConnected( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, const char *pszAddress, bool bFakePlayer )
|
||||
{
|
||||
META_CONPRINTF( "Hook_OnClientConnected(%d, \"%s\", %d, \"%s\", \"%s\", %d)\n", slot, pszName, xuid, pszNetworkID, pszAddress, bFakePlayer );
|
||||
}
|
||||
|
||||
bool SamplePlugin::Hook_ClientConnect( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, bool unk1, CBufferString *pRejectReason )
|
||||
bool MMSPlugin::Hook_ClientConnect( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, bool unk1, CBufferString *pRejectReason )
|
||||
{
|
||||
META_CONPRINTF( "Hook_ClientConnect(%d, \"%s\", %d, \"%s\", %d, \"%s\")\n", slot, pszName, xuid, pszNetworkID, unk1, pRejectReason->Get() );
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_ClientPutInServer( CPlayerSlot slot, char const *pszName, int type, uint64 xuid )
|
||||
void MMSPlugin::Hook_ClientPutInServer( CPlayerSlot slot, char const *pszName, int type, uint64 xuid )
|
||||
{
|
||||
META_CONPRINTF( "Hook_ClientPutInServer(%d, \"%s\", %d, %d)\n", slot, pszName, type, xuid );
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_ClientDisconnect( CPlayerSlot slot, ENetworkDisconnectionReason reason, const char *pszName, uint64 xuid, const char *pszNetworkID )
|
||||
void MMSPlugin::Hook_ClientDisconnect( CPlayerSlot slot, ENetworkDisconnectionReason reason, const char *pszName, uint64 xuid, const char *pszNetworkID )
|
||||
{
|
||||
META_CONPRINTF( "Hook_ClientDisconnect(%d, %d, \"%s\", %d, \"%s\")\n", slot, reason, pszName, xuid, pszNetworkID );
|
||||
}
|
||||
|
||||
void SamplePlugin::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick )
|
||||
void MMSPlugin::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastTick )
|
||||
{
|
||||
/**
|
||||
* simulating:
|
||||
@ -241,7 +241,7 @@ void SamplePlugin::Hook_GameFrame( bool simulating, bool bFirstTick, bool bLastT
|
||||
*/
|
||||
}
|
||||
|
||||
void SamplePlugin::OnLevelInit( char const *pMapName,
|
||||
void MMSPlugin::OnLevelInit( char const *pMapName,
|
||||
char const *pMapEntities,
|
||||
char const *pOldLevel,
|
||||
char const *pLandmarkName,
|
||||
@ -251,57 +251,7 @@ void SamplePlugin::OnLevelInit( char const *pMapName,
|
||||
META_CONPRINTF("OnLevelInit(%s)\n", pMapName);
|
||||
}
|
||||
|
||||
void SamplePlugin::OnLevelShutdown()
|
||||
void MMSPlugin::OnLevelShutdown()
|
||||
{
|
||||
META_CONPRINTF("OnLevelShutdown()\n");
|
||||
}
|
||||
|
||||
bool SamplePlugin::Pause(char *error, size_t maxlen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SamplePlugin::Unpause(char *error, size_t maxlen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetLicense()
|
||||
{
|
||||
return "Public Domain";
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetVersion()
|
||||
{
|
||||
return "1.0.0.0";
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetDate()
|
||||
{
|
||||
return __DATE__;
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetLogTag()
|
||||
{
|
||||
return "SAMPLE";
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetAuthor()
|
||||
{
|
||||
return "AlliedModders LLC";
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetDescription()
|
||||
{
|
||||
return "Sample basic plugin";
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetName()
|
||||
{
|
||||
return "Sample Plugin";
|
||||
}
|
||||
|
||||
const char *SamplePlugin::GetURL()
|
||||
{
|
||||
return "http://www.sourcemm.net/";
|
||||
}
|
||||
@ -12,20 +12,20 @@
|
||||
* This sample plugin is public domain.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_
|
||||
#define _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_
|
||||
#ifndef _INCLUDE_METAMOD_SOURCE_PLUGIN_H_
|
||||
#define _INCLUDE_METAMOD_SOURCE_PLUGIN_H_
|
||||
|
||||
#include <ISmmPlugin.h>
|
||||
#include <igameevents.h>
|
||||
#include <sh_vector.h>
|
||||
#include "version_gen.h"
|
||||
|
||||
class SamplePlugin : public ISmmPlugin, public IMetamodListener
|
||||
|
||||
class MMSPlugin : public ISmmPlugin, public IMetamodListener
|
||||
{
|
||||
public:
|
||||
bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late);
|
||||
bool Unload(char *error, size_t maxlen);
|
||||
bool Pause(char *error, size_t maxlen);
|
||||
bool Unpause(char *error, size_t maxlen);
|
||||
void AllPluginsLoaded();
|
||||
public: //hooks
|
||||
void OnLevelInit( char const *pMapName,
|
||||
@ -44,18 +44,18 @@ public: //hooks
|
||||
bool Hook_ClientConnect( CPlayerSlot slot, const char *pszName, uint64 xuid, const char *pszNetworkID, bool unk1, CBufferString *pRejectReason );
|
||||
void Hook_ClientCommand( CPlayerSlot nSlot, const CCommand &_cmd );
|
||||
public:
|
||||
const char *GetAuthor();
|
||||
const char *GetName();
|
||||
const char *GetDescription();
|
||||
const char *GetURL();
|
||||
const char *GetLicense();
|
||||
const char *GetVersion();
|
||||
const char *GetDate();
|
||||
const char *GetLogTag();
|
||||
const char *GetAuthor() { return PLUGIN_AUTHOR; }
|
||||
const char *GetName() { return PLUGIN_DISPLAY_NAME; }
|
||||
const char *GetDescription() { return PLUGIN_DESCRIPTION; }
|
||||
const char *GetURL() { return PLUGIN_URL; }
|
||||
const char *GetLicense() { return PLUGIN_LICENSE; }
|
||||
const char *GetVersion() { return PLUGIN_FULL_VERSION; }
|
||||
const char *GetDate() { return __DATE__; }
|
||||
const char *GetLogTag() { return PLUGIN_LOGTAG; }
|
||||
};
|
||||
|
||||
extern SamplePlugin g_SamplePlugin;
|
||||
extern MMSPlugin g_ThisPlugin;
|
||||
|
||||
PLUGIN_GLOBALVARS();
|
||||
|
||||
#endif //_INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_
|
||||
#endif //_INCLUDE_METAMOD_SOURCE_PLUGIN_H_
|
||||
Loading…
Reference in New Issue
Block a user