diff --git a/core/GameConfigs.cpp b/core/GameConfigs.cpp index 0478d082..c58aaecb 100644 --- a/core/GameConfigs.cpp +++ b/core/GameConfigs.cpp @@ -762,11 +762,15 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength) bShouldBeReadingDefault = true; m_ParseState = PSTATE_NONE; + g_GameConfigs.AcquireLock(); + if ((err=textparsers->ParseSMCFile(m_CurFile, this, &state, error, maxlength)) != SMCError_Okay) { const char *msg; + g_GameConfigs.ReleaseLock(); + msg = textparsers->GetSMCErrorString(err); g_Logger.LogError("[SM] Error parsing gameconfig file \"%s\":", m_CurFile); @@ -787,6 +791,8 @@ bool CGameConfig::EnterFile(const char *file, char *error, size_t maxlength) return false; } + g_GameConfigs.ReleaseLock(); + return true; } @@ -854,6 +860,8 @@ GameConfigManager::~GameConfigManager() void GameConfigManager::OnSourceModStartup(bool late) { + m_FileLock = g_pThreader->MakeMutex(); + LoadGameConfigFile("core.games", &g_pGameConf, NULL, 0); strncopy(g_Game, g_SourceMod.GetGameFolderName(), sizeof(g_Game)); @@ -888,6 +896,7 @@ void GameConfigManager::OnSourceModAllInitialized() void GameConfigManager::OnSourceModAllShutdown() { CloseGameConfigFile(g_pGameConf); + m_FileLock->DestroyThis(); } bool GameConfigManager::LoadGameConfigFile(const char *file, IGameConfig **_pConfig, char *error, size_t maxlength) @@ -956,12 +965,12 @@ IGameConfig *GameConfigManager::ReadHandle(Handle_t hndl, IdentityToken_t *ident return conf; } -void GameConfigManager::AddUserConfigHook( const char *sectionname, ITextListener_SMC *listener ) +void GameConfigManager::AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener) { m_customHandlers.insert(sectionname, listener); } -void GameConfigManager::RemoveUserConfigHook( const char *sectionname, ITextListener_SMC *listener ) +void GameConfigManager::RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener) { ITextListener_SMC **pListener = m_customHandlers.retrieve(sectionname); @@ -979,3 +988,13 @@ void GameConfigManager::RemoveUserConfigHook( const char *sectionname, ITextList return; } + +void GameConfigManager::AcquireLock() +{ + m_FileLock->Lock(); +} + +void GameConfigManager::ReleaseLock() +{ + m_FileLock->Unlock(); +} diff --git a/core/GameConfigs.h b/core/GameConfigs.h index f49a8f17..9fc512f5 100644 --- a/core/GameConfigs.h +++ b/core/GameConfigs.h @@ -39,6 +39,7 @@ #include "sm_globals.h" #include "sm_memtable.h" #include "sm_trie_tpl.h" +#include "ThreadSupport.h" using namespace SourceMod; using namespace SourceHook; @@ -110,6 +111,8 @@ public: //IGameConfigManager HandleError *err); void AddUserConfigHook(const char *sectionname, ITextListener_SMC *listener); void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener); + void AcquireLock(); + void ReleaseLock(); public: //SMGlobalClass void OnSourceModStartup(bool late); void OnSourceModAllInitialized(); @@ -117,6 +120,7 @@ public: //SMGlobalClass private: List m_cfgs; Trie *m_pLookup; + IMutex *m_FileLock; public: KTrie m_customHandlers; }; diff --git a/core/frame_hooks.h b/core/frame_hooks.h index 23a6ad26..65331598 100644 --- a/core/frame_hooks.h +++ b/core/frame_hooks.h @@ -32,10 +32,15 @@ #ifndef _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ #define _INCLUDE_SOURCEMOD_FRAME_HOOKS_H_ -typedef void (*FRAMEACTION)(void *data); +#include + +using namespace SourceMod; struct FrameAction { + FrameAction(FRAMEACTION a, void *d) : data(d), action(a) + { + } void *data; FRAMEACTION action; }; diff --git a/core/msvc9/sourcemod_mm.vcproj b/core/msvc9/sourcemod_mm.vcproj index 2a2648a6..4721e3f3 100644 --- a/core/msvc9/sourcemod_mm.vcproj +++ b/core/msvc9/sourcemod_mm.vcproj @@ -1491,6 +1491,10 @@ RelativePath="..\TextParsers.h" > + + diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index 31874ebe..633b3ade 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -48,6 +48,7 @@ #include "GameConfigs.h" #include "DebugReporter.h" #include "Profiler.h" +#include "frame_hooks.h" SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false); @@ -379,7 +380,7 @@ void SourceModBase::DoGlobalPluginLoads() g_Extensions.TryAutoload(); /* Fire the extensions ready message */ - g_SMAPI->MetaFactory(SOURCEMOD_NOTICE_EXTENSIONS, NULL, NULL); + g_SMAPI->MetaFactory(SOURCEMOD_NOTICE_EXTENSIONS, NULL, NULL); /* Load any game extension */ const char *game_ext; @@ -690,6 +691,11 @@ size_t SourceModBase::FormatArgs(char *buffer, return UTIL_FormatArgs(buffer, maxlength, fmt, ap); } +void SourceModBase::AddFrameAction(FRAMEACTION fn, void *data) +{ + ::AddFrameAction(FrameAction(fn, data)); +} + SMGlobalClass *SMGlobalClass::head = NULL; SMGlobalClass::SMGlobalClass() diff --git a/core/sourcemod.h b/core/sourcemod.h index 2dcc292f..a436b42e 100644 --- a/core/sourcemod.h +++ b/core/sourcemod.h @@ -131,6 +131,7 @@ public: // ISourceMod void ProcessGameFrameHooks(bool simulating); size_t Format(char *buffer, size_t maxlength, const char *fmt, ...); size_t FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap); + void AddFrameAction(FRAMEACTION fn, void *data); private: CStack m_freepacks; char m_SMBaseDir[PLATFORM_MAX_PATH]; diff --git a/extensions/updater/Makefile b/extensions/updater/Makefile new file mode 100644 index 00000000..c4adab46 --- /dev/null +++ b/extensions/updater/Makefile @@ -0,0 +1,150 @@ +# (C)2004-2008 SourceMod Development Team +# Makefile written by David "BAILOPAN" Anderson + +SMSDK = ../.. +SRCDS_BASE = ~/srcds +HL2SDK_ORIG = ../../../hl2sdk +HL2SDK_OB = ../../../hl2sdk-ob +HL2SDK_L4D = ../../../hl2sdk-l4d +MMSOURCE17 = ../../../mmsource-1.7 + +##################################### +### EDIT BELOW FOR OTHER PROJECTS ### +##################################### + +PROJECT = updater + +#Uncomment for Metamod: Source enabled extension +#USEMETA = true + +OBJECTS = \ + sdk/smsdk_ext.cpp \ + extension.cpp \ + MemoryDownloader.cpp \ + md5.cpp \ + Updater.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 + +override ENGSET = false +ifeq "$(ENGINE)" "original" + HL2SDK = $(HL2SDK_ORIG) + HL2PUB = $(HL2SDK)/public + HL2LIB = $(HL2SDK)/linux_sdk + CFLAGS += -DSOURCE_ENGINE=2 + METAMOD = $(MMSOURCE17)/core-legacy + INCLUDE += -I$(HL2SDK)/public/dlls + SRCDS = $(SRCDS_BASE) + override ENGSET = true +endif +ifeq "$(ENGINE)" "orangebox" + HL2SDK = $(HL2SDK_OB) + HL2PUB = $(HL2SDK)/public + HL2LIB = $(HL2SDK)/lib/linux + CFLAGS += -DSOURCE_ENGINE=3 + METAMOD = $(MMSOURCE17)/core + INCLUDE += -I$(HL2SDK)/public/game/server + SRCDS = $(SRCDS_BASE)/orangebox + override ENGSET = true +endif +ifeq "$(ENGINE)" "left4dead" + HL2SDK = $(HL2SDK_L4D) + HL2PUB = $(HL2SDK)/public + HL2LIB = $(HL2SDK)/lib/linux + CFLAGS += -DSOURCE_ENGINE=4 + METAMOD = $(MMSOURCE17)/core + INCLUDE += -I$(HL2SDK)/public/game/server + SRCDS = $(SRCDS_BASE)/l4d + override ENGSET = true +endif + +ifeq "$(USEMETA)" "true" + LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so + + LINK += $(LINK_HL2) + + INCLUDE += -I. -I.. -Isdk -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \ + -I$(METAMOD) -I$(METAMOD)/sourcehook -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn + CFLAGS += -DSE_EPISODEONE=2 -DSE_ORANGEBOX=3 -DSE_LEFT4DEAD=4 +else + INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn \ + -I$(SMSDK)/public/extensions +endif + +LINK += -m32 -lm -ldl + +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-switch \ + -Wno-unused -mfpmath=sse -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -m32 +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 + +ifeq "$(USEMETA)" "true" + BIN_DIR := $(BIN_DIR).$(ENGINE) +endif + +OS := $(shell uname -s) +ifeq "$(OS)" "Darwin" + LINK += -dynamiclib + BINARY = $(PROJECT).ext.dylib +else + LINK += -static-libgcc -shared + BINARY = $(PROJECT).ext.so +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) + +$(BIN_DIR)/%.o: %.cpp + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +all: check + mkdir -p $(BIN_DIR)/sdk + if [ "$(USEMETA)" = "true" ]; then \ + ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so; \ + ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so; \ + fi + $(MAKE) -f Makefile extension + +check: + if [ "$(USEMETA)" = "true" ] && [ "$(ENGSET)" = "false" ]; then \ + echo "You must supply ENGINE=left4dead or ENGINE=orangebox or ENGINE=original"; \ + exit 1; \ + fi + +extension: check $(OBJ_LINUX) + $(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -o $(BIN_DIR)/$(BINARY) + +debug: + $(MAKE) -f Makefile all DEBUG=true + +default: all + +clean: check + rm -rf $(BIN_DIR)/*.o + rm -rf $(BIN_DIR)/sdk/*.o + rm -rf $(BIN_DIR)/$(BINARY) diff --git a/extensions/updater/MemoryDownloader.cpp b/extensions/updater/MemoryDownloader.cpp new file mode 100644 index 00000000..af5b4705 --- /dev/null +++ b/extensions/updater/MemoryDownloader.cpp @@ -0,0 +1,85 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Updater Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#include +#include +#include +#include "MemoryDownloader.h" + +using namespace SourceMod; + +MemoryDownloader::MemoryDownloader() : buffer(NULL), bufsize(0), bufpos(0) +{ +} + +MemoryDownloader::~MemoryDownloader() +{ + free(buffer); +} + +DownloadWriteStatus MemoryDownloader::OnDownloadWrite(IWebTransfer *session, + void *userdata, + void *ptr, + size_t size, + size_t nmemb) +{ + size_t total = size * nmemb; + + if (bufpos + total > bufsize) + { + size_t rem = (bufpos + total) - bufsize; + bufsize += rem + (rem / 2); + buffer = (char *)realloc(buffer, bufsize); + } + + assert(bufpos + total <= bufsize); + + memcpy(&buffer[bufpos], ptr, total); + bufpos += total; + + return DownloadWrite_Okay; +} + +void MemoryDownloader::Reset() +{ + bufpos = 0; +} + +char *MemoryDownloader::GetBuffer() +{ + return buffer; +} + +size_t MemoryDownloader::GetSize() +{ + return bufpos; +} + diff --git a/extensions/updater/MemoryDownloader.h b/extensions/updater/MemoryDownloader.h new file mode 100644 index 00000000..7ac64e0f --- /dev/null +++ b/extensions/updater/MemoryDownloader.h @@ -0,0 +1,62 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Updater Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_UPDATER_MEMORY_DOWNLOADER_H_ +#define _INCLUDE_SOURCEMOD_UPDATER_MEMORY_DOWNLOADER_H_ + +#include + +namespace SourceMod +{ + class MemoryDownloader : public ITransferHandler + { + public: + MemoryDownloader(); + ~MemoryDownloader(); + public: + DownloadWriteStatus OnDownloadWrite(IWebTransfer *session, + void *userdata, + void *ptr, + size_t size, + size_t nmemb); + public: + void Reset(); + char *GetBuffer(); + size_t GetSize(); + private: + char *buffer; + size_t bufsize; + size_t bufpos; + }; +} + +#endif /* _INCLUDE_SOURCEMOD_UPDATER_MEMORY_DOWNLOADER_H_ */ + diff --git a/extensions/updater/Updater.cpp b/extensions/updater/Updater.cpp new file mode 100644 index 00000000..5df16414 --- /dev/null +++ b/extensions/updater/Updater.cpp @@ -0,0 +1,383 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Updater Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#include +#include "extension.h" +#include "Updater.h" +#include "md5.h" + +#define UPDATE_URL "http://www.sourcemod.net/update/" + +#define USTATE_NONE 0 +#define USTATE_FOLDERS 1 +#define USTATE_CHANGED 2 +#define USTATE_CHANGE_FILE 3 + +using namespace SourceMod; + +UpdateReader::UpdateReader() +{ +} + +UpdateReader::~UpdateReader() +{ +} + +void UpdateReader::ReadSMC_ParseStart() +{ + ignoreLevel = 0; + ustate = USTATE_NONE; +} + +SMCResult UpdateReader::ReadSMC_NewSection(const SMCStates *states, const char *name) +{ + if (ignoreLevel) + { + ignoreLevel++; + return SMCResult_Continue; + } + + switch (ustate) + { + case USTATE_NONE: + { + if (strcmp(name, "Folders") == 0) + { + ustate = USTATE_FOLDERS; + } + else if (strcmp(name, "Changed") == 0) + { + ustate = USTATE_CHANGED; + } + else + { + ignoreLevel++; + } + break; + } + case USTATE_FOLDERS: + case USTATE_CHANGE_FILE: + { + ignoreLevel++; + break; + } + case USTATE_CHANGED: + { + curfile.assign(name); + url.clear(); + checksum[0] = '\0'; + ustate = USTATE_CHANGE_FILE; + break; + } + } + + return SMCResult_Continue; +} + +SMCResult UpdateReader::ReadSMC_KeyValue(const SMCStates *states, + const char *key, + const char *value) +{ + if (ignoreLevel) + { + return SMCResult_Continue; + } + + switch (ustate) + { + case USTATE_CHANGE_FILE: + { + if (strcmp(key, "md5sum") == 0) + { + if (strlen(value) != 32) + { + return SMCResult_Continue; + } + strcpy(checksum, value); + } + else if (strcmp(key, "location") == 0) + { + url.assign(UPDATE_URL); + url.append(value); + } + break; + } + case USTATE_FOLDERS: + { + HandleFolder(value); + break; + } + } + + return SMCResult_Continue; +} + +SMCResult UpdateReader::ReadSMC_LeavingSection(const SMCStates *states) +{ + if (ignoreLevel) + { + ignoreLevel--; + return SMCResult_Continue; + } + + switch (ustate) + { + case USTATE_FOLDERS: + case USTATE_CHANGED: + { + ustate = USTATE_NONE; + break; + } + case USTATE_CHANGE_FILE: + { + if (url.size() != 0 && checksum[0] != '\0') + { + HandleFile(); + } + else + { + AddUpdateError("Incomplete file definition in update manifest"); + } + ustate = USTATE_CHANGED; + break; + } + } + + return SMCResult_Continue; +} + +void UpdateReader::HandleFile() +{ + MD5 md5; + char real_checksum[33]; + + mdl.Reset(); + + if (!xfer->Download(url.c_str(), &mdl, NULL)) + { + AddUpdateError("Could not download \"%s\"", url.c_str()); + AddUpdateError("Error: %s", xfer->LastErrorMessage()); + return; + } + + md5.update((unsigned char *)mdl.GetBuffer(), mdl.GetSize()); + md5.finalize(); + md5.hex_digest(real_checksum); + + if (strcasecmp(checksum, real_checksum) != 0) + { + AddUpdateError("Checksums for file \"%s\" do not match:", curfile.c_str()); + AddUpdateError("Expected: %s Real: %s", checksum, real_checksum); + return; + } + + char path[PLATFORM_MAX_PATH]; + smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", curfile.c_str()); + + gameconfs->AcquireLock(); + + FILE *fp = fopen(path, "wt"); + if (fp == NULL) + { + gameconfs->ReleaseLock(); + AddUpdateError("Could not open %s for writing", path); + return; + } + + fwrite(mdl.GetBuffer(), 1, mdl.GetSize(), fp); + fclose(fp); + + gameconfs->ReleaseLock(); + + AddUpdateMessage("Successfully updated gamedata file \"%s\"", curfile.c_str()); +} + +void UpdateReader::HandleFolder(const char *folder) +{ + char path[PLATFORM_MAX_PATH]; + + smutils->BuildPath(Path_SM, path, sizeof(path), "gamedata/%s", folder); + if (libsys->IsPathDirectory(path)) + { + return; + } + + if (!libsys->CreateFolder(path)) + { + AddUpdateError("Could not create folder: %s", path); + } + else + { + AddUpdateMessage("Created folder \"%s\" from updater", folder); + } +} + +static bool md5_file(const char *file, char checksum[33]) +{ + MD5 md5; + FILE *fp; + long length; + void *fdata; + + if ((fp = fopen(file, "rt")) == NULL) + { + return false; + } + + fseek(fp, 0, SEEK_END); + length = ftell(fp); + fseek(fp, 0, SEEK_SET); + fdata = malloc(length); + if (fread(fdata, 1, length, fp) != size_t(length)) + { + free(fdata); + fclose(fp); + return false; + } + fclose(fp); + + md5.update((unsigned char*)fdata, length); + md5.finalize(); + md5.hex_digest(checksum); + + free(fdata); + + return true; +} + +/* Path should be sourcemod relative, not gamedata relative */ +static bool add_file(IWebForm *form, const char *file, unsigned int &num_files) +{ + char path[PLATFORM_MAX_PATH]; + + smutils->BuildPath(Path_SM, path, sizeof(path), "%s", file); + + char checksum[33]; + if (!md5_file(path, checksum)) + { + return false; + } + + char name[32]; + smutils->Format(name, sizeof(name), "file_%d_name", num_files); + form->AddString(name, file); + smutils->Format(name, sizeof(name), "file_%d_md5", num_files); + form->AddString(name, checksum); + + num_files++; + + return true; +} + +static void add_folders(IWebForm *form, const char *root, unsigned int &num_files) +{ + IDirectory *dir; + char path[PLATFORM_MAX_PATH]; + char name[PLATFORM_MAX_PATH]; + + smutils->BuildPath(Path_SM, path, sizeof(path), "%s", root); + dir = libsys->OpenDirectory(path); + if (dir == NULL) + { + AddUpdateError("Could not open folder: %s", path); + return; + } + + while (dir->MoreFiles()) + { + if (strcmp(dir->GetEntryName(), ".") == 0 || + strcmp(dir->GetEntryName(), "..") == 0) + { + dir->NextEntry(); + continue; + } + smutils->Format(name, sizeof(name), "%s/%s", root, dir->GetEntryName()); + if (dir->IsEntryDirectory()) + { + add_folders(form, name, num_files); + } + else if (dir->IsEntryFile()) + { + add_file(form, name, num_files); + } + dir->NextEntry(); + } + + libsys->CloseDirectory(dir); +} + +void UpdateReader::PerformUpdate() +{ + IWebForm *form; + MemoryDownloader master; + SMCStates states = {0, 0}; + + form = webternet->CreateForm(); + xfer = webternet->CreateSession(); + xfer->SetFailOnHTTPError(true); + + const char *root_url = UPDATE_URL "gamedata.php"; + + form->AddString("version", SVN_FULL_VERSION); + form->AddString("build", SM_BUILD_UNIQUEID); + + unsigned int num_files = 0; + add_folders(form, "gamedata", num_files); + + char temp[24]; + smutils->Format(temp, sizeof(temp), "%d", num_files); + form->AddString("files", temp); + + if (!xfer->PostAndDownload(root_url, form, &master, NULL)) + { + AddUpdateError("Could not download \"%s\"", root_url); + AddUpdateError("Error: %s", xfer->LastErrorMessage()); + goto cleanup; + } + + SMCError error; + char errbuf[256]; + error = textparsers->ParseSMCStream(master.GetBuffer(), + master.GetSize(), + this, + &states, + errbuf, + sizeof(errbuf)); + if (error != SMCError_Okay) + { + AddUpdateError("Parse error in update manifest: %s", errbuf); + goto cleanup; + } + +cleanup: + delete xfer; + delete form; +} diff --git a/extensions/updater/Updater.h b/extensions/updater/Updater.h new file mode 100644 index 00000000..0412f6cd --- /dev/null +++ b/extensions/updater/Updater.h @@ -0,0 +1,70 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Updater Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_UPDATER_H_ +#define _INCLUDE_SOURCEMOD_UPDATER_H_ + +#include +#include +#include +#include "MemoryDownloader.h" + +namespace SourceMod +{ + class UpdateReader : + public ITextListener_SMC + { + public: + UpdateReader(); + ~UpdateReader(); + public: /* ITextListener_SMC */ + void ReadSMC_ParseStart(); + SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name); + SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value); + SMCResult ReadSMC_LeavingSection(const SMCStates *states); + public: + void PerformUpdate(); + private: + void HandleFile(); + void HandleFolder(const char *folder); + private: + IWebTransfer *xfer; + MemoryDownloader mdl; + unsigned int ustate; + unsigned int ignoreLevel; + SourceHook::String curfile; + SourceHook::String url; + char checksum[33]; + }; +} + +#endif /* _INCLUDE_SOURCEMOD_UPDATER_H_ */ + diff --git a/extensions/updater/extension.cpp b/extensions/updater/extension.cpp new file mode 100644 index 00000000..7c2da506 --- /dev/null +++ b/extensions/updater/extension.cpp @@ -0,0 +1,182 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Updater Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#include +#include +#include +#include +#include "extension.h" +#include "Updater.h" +#include +#include + +using namespace SourceHook; + +SmUpdater g_Updater; /**< Global singleton for extension's main interface */ +SMEXT_LINK(&g_Updater); + +IWebternet *webternet; +static List update_errors; +static List update_messages; +static IThreadHandle *update_thread; + +bool SmUpdater::SDK_OnLoad(char *error, size_t maxlength, bool late) +{ + sharesys->AddDependency(myself, "webternet.ext", true, true); + + SM_GET_IFACE(WEBTERNET, webternet); + + ThreadParams params; + params.flags = Thread_Default; + params.prio = ThreadPrio_Low; + update_thread = threader->MakeThread(this, ¶ms); + + if (update_thread == NULL) + { + smutils->Format(error, maxlength, "Could not create thread"); + return false; + } + + return true; +} + +void SmUpdater::SDK_OnUnload() +{ + /* An interface drop might have killed this thread. + * But if the handle is still there, we have to wait. + */ + if (update_thread != NULL) + { + update_thread->WaitForThread(); + update_thread->DestroyThis(); + } + + /* Clear message tables */ + List::iterator iter; + while (iter != update_errors.end()) + { + iter = update_errors.erase(iter); + } + while (iter != update_messages.end()) + { + iter = update_messages.erase(iter); + } +} + +bool SmUpdater::QueryInterfaceDrop(SourceMod::SMInterface *pInterface) +{ + if (pInterface == webternet) + { + return false; + } + + return true; +} + +void SmUpdater::NotifyInterfaceDrop(SMInterface *pInterface) +{ + if (pInterface == webternet) + { + /* Can't be in the thread if we're losing this extension. */ + update_thread->WaitForThread(); + update_thread->DestroyThis(); + update_thread = NULL; + } +} + +static void LogAllMessages(void *data) +{ + String *str; + List::iterator iter; + + if (update_errors.size()) + { + smutils->LogError(myself, "--- BEGIN ERRORS FROM AUTOMATIC UPDATER ---"); + + for (iter = update_errors.begin(); + iter != update_errors.end(); + iter++) + { + str = (*iter); + smutils->LogError(myself, "%s", str->c_str()); + } + + smutils->LogError(myself, "--- END ERRORS FROM AUTOMATIC UPDATER ---"); + } + + for (iter = update_messages.begin(); + iter != update_messages.end(); + iter++) + { + str = (*iter); + smutils->LogMessage(myself, "%s", str->c_str()); + } +} + +void SmUpdater::RunThread(IThreadHandle *pHandle) +{ + UpdateReader ur; + + ur.PerformUpdate(); + + if (update_errors.size() || update_messages.size()) + { + smutils->AddFrameAction(LogAllMessages, NULL); + } +} + +void SmUpdater::OnTerminate(IThreadHandle *pHandle, bool cancel) +{ +} + +void AddUpdateMessage(const char *fmt, ...) +{ + va_list ap; + char buffer[2048]; + + va_start(ap, fmt); + smutils->FormatArgs(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + update_messages.push_back(new String(buffer)); +} + +void AddUpdateError(const char *fmt, ...) +{ + va_list ap; + char buffer[2048]; + + va_start(ap, fmt); + smutils->FormatArgs(buffer, sizeof(buffer), fmt, ap); + va_end(ap); + + update_errors.push_back(new String(buffer)); +} diff --git a/extensions/updater/extension.h b/extensions/updater/extension.h new file mode 100644 index 00000000..3029c994 --- /dev/null +++ b/extensions/updater/extension.h @@ -0,0 +1,87 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Updater Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ + +/** + * @file extension.h + * @brief Sample extension code header. + */ + +#include "smsdk_ext.h" +#include + +/** + * @brief Sample implementation of the SDK Extension. + * Note: Uncomment one of the pre-defined virtual functions in order to use it. + */ +class SmUpdater : + public SDKExtension, + public IThread +{ +public: /* SDKExtension */ + bool SDK_OnLoad(char *error, size_t maxlength, bool late); + void SDK_OnUnload(); +public: /* IExtension */ + bool QueryInterfaceDrop(SMInterface *pInterface); + void NotifyInterfaceDrop(SMInterface *pInterface); +public: /* IThread */ + void RunThread(IThreadHandle *pHandle); + void OnTerminate(IThreadHandle *pHandle, bool cancel); + + /** + * @brief This is called once all known extensions have been loaded. + * Note: It is is a good idea to add natives here, if any are provided. + */ + //virtual void SDK_OnAllLoaded(); + + /** + * @brief Called when the pause state is changed. + */ + //virtual void SDK_OnPauseChange(bool paused); + + /** + * @brief this is called when Core wants to know if your extension is working. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @return True if working, false otherwise. + */ + //virtual bool QueryRunning(char *error, size_t maxlength); +}; + +extern void AddUpdateMessage(const char *fmt, ...); +extern void AddUpdateError(const char *fmt, ...); + +extern IWebternet *webternet; + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/updater/md5.cpp b/extensions/updater/md5.cpp new file mode 100644 index 00000000..8738c6df --- /dev/null +++ b/extensions/updater/md5.cpp @@ -0,0 +1,476 @@ +// MD5.CC - source code for the C++/object oriented translation and +// modification of MD5. + +// Translation and modification (c) 1995 by Mordechai T. Abzug + +// This translation/ modification is provided "as is," without express or +// implied warranty of any kind. + +// The translator/ modifier does not claim (1) that MD5 will do what you think +// it does; (2) that this translation/ modification is accurate; or (3) that +// this software is "merchantible." (Language for this disclaimer partially +// copied from the disclaimer below). + +/* based on: + + MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + MDDRIVER.C - test driver for MD2, MD4 and MD5 + + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + + */ + +#include "md5.h" + +#include +#include + +// MD5 simple initialization method + +MD5::MD5(){ + + init(); + +} + + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block, and updating the +// context. + +void MD5::update (uint1 *input, uint4 input_length) { + + uint4 input_index, buffer_index; + uint4 buffer_space; // how much space is left in buffer + + if (finalized){ // so we can't update! + /*cerr << "MD5::update: Can't update a finalized digest!" << endl;*/ + return; + } + + // Compute number of bytes mod 64 + buffer_index = (unsigned int)((count[0] >> 3) & 0x3F); + + // Update number of bits + if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) ) + count[1]++; + + count[1] += ((uint4)input_length >> 29); + + + buffer_space = 64 - buffer_index; // how much space is left in buffer + + // Transform as many times as possible. + if (input_length >= buffer_space) { // ie. we have enough to fill the buffer + // fill the rest of the buffer and transform + memcpy (buffer + buffer_index, input, buffer_space); + transform (buffer); + + // now, transform each 64-byte piece of the input, bypassing the buffer + for (input_index = buffer_space; input_index + 63 < input_length; + input_index += 64) + transform (input+input_index); + + buffer_index = 0; // so we can buffer remaining + } + else + input_index=0; // so we can buffer the whole input + + + // and here we do the buffering: + memcpy(buffer+buffer_index, input+input_index, input_length-input_index); +} + + + +// MD5 update for files. +// Like above, except that it works on files (and uses above as a primitive.) + +void MD5::update(FILE *file){ + + unsigned char buffer[1024]; + int len; + + while ((len=fread(buffer, 1, 1024, file))) + update(buffer, len); + + fclose (file); + +} + + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. + + +void MD5::finalize (){ + + unsigned char bits[8]; + unsigned int index, padLen; + static uint1 PADDING[64]={ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (finalized){ + /* cerr << "MD5::finalize: Already finalized this digest!" << endl;*/ + return; + } + + // Save number of bits + encode (bits, count, 8); + + // Pad out to 56 mod 64. + index = (uint4) ((count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + update (PADDING, padLen); + + // Append length (before padding) + update (bits, 8); + + // Store state in digest + encode (digest, state, 16); + + // Zeroize sensitive information + memset (buffer, 0, sizeof(*buffer)); + + finalized=1; + +} + + + + +MD5::MD5(FILE *file){ + + init(); // must be called be all constructors + update(file); + finalize (); +} + +unsigned char *MD5::raw_digest(){ + + uint1 *s = new uint1[16]; + + if (!finalized){ +/* cerr << "MD5::raw_digest: Can't get digest if you haven't "<< + "finalized the digest!" <> 8) & 0xff); + output[j+2] = (uint1) ((input[i] >> 16) & 0xff); + output[j+3] = (uint1) ((input[i] >> 24) & 0xff); + } +} + + + + +// Decodes input (unsigned char) into output (UINT4). Assumes len is +// a multiple of 4. +void MD5::decode (uint4 *output, uint1 *input, uint4 len){ + + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + + + + + +// Note: Replace "for loop" with standard memcpy if possible. +void MD5::memcpy (uint1 *output, uint1 *input, uint4 len){ + + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + + + +// Note: Replace "for loop" with standard memset if possible. +void MD5::memset (uint1 *output, uint1 value, uint4 len){ + + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = value; +} + + + +// ROTATE_LEFT rotates x left n bits. + +inline unsigned int MD5::rotate_left (uint4 x, uint4 n){ + return (x << n) | (x >> (32-n)) ; +} + + + + +// F, G, H and I are basic MD5 functions. + +inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){ + return (x & y) | (~x & z); +} + +inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){ + return (x & z) | (y & ~z); +} + +inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){ + return x ^ y ^ z; +} + +inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){ + return y ^ (x | ~z); +} + + + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. + + +inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += F(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += G(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += H(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} + +inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac){ + a += I(b, c, d) + x + ac; + a = rotate_left (a, s) +b; +} diff --git a/extensions/updater/md5.h b/extensions/updater/md5.h new file mode 100644 index 00000000..3f6979d9 --- /dev/null +++ b/extensions/updater/md5.h @@ -0,0 +1,106 @@ +// MD5.CC - source code for the C++/object oriented translation and +// modification of MD5. + +// Translation and modification (c) 1995 by Mordechai T. Abzug + +// This translation/ modification is provided "as is," without express or +// implied warranty of any kind. + +// The translator/ modifier does not claim (1) that MD5 will do what you think +// it does; (2) that this translation/ modification is accurate; or (3) that +// this software is "merchantible." (Language for this disclaimer partially +// copied from the disclaimer below). + +/* based on: + + MD5.H - header file for MD5C.C + MDDRIVER.C - test driver for MD2, MD4 and MD5 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +*/ + +#include +//#include +//#include + +class MD5 { + +public: +// methods for controlled operation: + MD5 (); // simple initializer + void update (unsigned char *input, unsigned int input_length); + void update (FILE *file); + void finalize (); + +// constructors for special circumstances. All these constructors finalize +// the MD5 context. + MD5 (unsigned char *string); // digest string, finalize + MD5 (FILE *file); // digest file, close, finalize + +// methods to acquire finalized result + unsigned char *raw_digest (); // digest as a 16-byte binary array + unsigned char *raw_digest(unsigned char buffer[16]); + char * hex_digest (); // digest as a 33-byte ascii-hex string + char * hex_digest (char buffer[33]); //same as above, passing buffer + + + +private: + +// first, some types: + typedef unsigned int uint4; // assumes integer is 4 words long + typedef unsigned short int uint2; // assumes short integer is 2 words long + typedef unsigned char uint1; // assumes char is 1 word long + +// next, the private data: + uint4 state[4]; + uint4 count[2]; // number of *bits*, mod 2^64 + uint1 buffer[64]; // input buffer + uint1 digest[16]; + uint1 finalized; + +// last, the private methods, mostly static: + void init (); // called by all constructors + void transform (uint1 *buffer); // does the real update work. Note + // that length is implied to be 64. + + static void encode (uint1 *dest, uint4 *src, uint4 length); + static void decode (uint4 *dest, uint1 *src, uint4 length); + static void memcpy (uint1 *dest, uint1 *src, uint4 length); + static void memset (uint1 *start, uint1 val, uint4 length); + + static inline uint4 rotate_left (uint4 x, uint4 n); + static inline uint4 F (uint4 x, uint4 y, uint4 z); + static inline uint4 G (uint4 x, uint4 y, uint4 z); + static inline uint4 H (uint4 x, uint4 y, uint4 z); + static inline uint4 I (uint4 x, uint4 y, uint4 z); + static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, + uint4 s, uint4 ac); + +}; diff --git a/extensions/updater/msvc9/updater.sln b/extensions/updater/msvc9/updater.sln new file mode 100644 index 00000000..2e499e47 --- /dev/null +++ b/extensions/updater/msvc9/updater.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "updater", "updater.vcproj", "{B3E797CF-4E77-4C9D-B8A8-7589B6902206}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.Build.0 = Debug|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.ActiveCfg = Release|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/extensions/updater/msvc9/updater.vcproj b/extensions/updater/msvc9/updater.vcproj new file mode 100644 index 00000000..6f021b15 --- /dev/null +++ b/extensions/updater/msvc9/updater.vcproj @@ -0,0 +1,916 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/updater/sdk/smsdk_config.h b/extensions/updater/sdk/smsdk_config.h new file mode 100644 index 00000000..0e29316a --- /dev/null +++ b/extensions/updater/sdk/smsdk_config.h @@ -0,0 +1,83 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Sample Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#include "svn_version.h" + +/** + * @file smsdk_config.h + * @brief Contains macros for configuring basic extension information. + */ + +/* Basic information exposed publicly */ +#define SMEXT_CONF_NAME "Automatic Updater" +#define SMEXT_CONF_DESCRIPTION "Updates SourceMod gamedata files" +#define SMEXT_CONF_VERSION SVN_FULL_VERSION +#define SMEXT_CONF_AUTHOR "AlliedModders LLC" +#define SMEXT_CONF_URL "http://www.sourcemod.net/" +#define SMEXT_CONF_LOGTAG "UPDATER" +#define SMEXT_CONF_LICENSE "GPL" +#define SMEXT_CONF_DATESTRING __DATE__ + +/** + * @brief Exposes plugin's main interface. + */ +#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name; + +/** + * @brief Sets whether or not this plugin required Metamod. + * NOTE: Uncomment to enable, comment to disable. + */ +//#define SMEXT_CONF_METAMOD + +/** Enable interfaces you want to use here by uncommenting lines */ +//#define SMEXT_ENABLE_FORWARDSYS +//#define SMEXT_ENABLE_HANDLESYS +//#define SMEXT_ENABLE_PLAYERHELPERS +//#define SMEXT_ENABLE_DBMANAGER +#define SMEXT_ENABLE_GAMECONF +//#define SMEXT_ENABLE_MEMUTILS +//#define SMEXT_ENABLE_GAMEHELPERS +//#define SMEXT_ENABLE_TIMERSYS +#define SMEXT_ENABLE_THREADER +#define SMEXT_ENABLE_LIBSYS +//#define SMEXT_ENABLE_MENUS +//#define SMEXT_ENABLE_ADTFACTORY +//#define SMEXT_ENABLE_PLUGINSYS +//#define SMEXT_ENABLE_ADMINSYS +#define SMEXT_ENABLE_TEXTPARSERS +//#define SMEXT_ENABLE_USERMSGS +//#define SMEXT_ENABLE_TRANSLATOR +//#define SMEXT_ENABLE_NINVOKE + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ + diff --git a/extensions/updater/sdk/smsdk_ext.cpp b/extensions/updater/sdk/smsdk_ext.cpp new file mode 100644 index 00000000..f31352d9 --- /dev/null +++ b/extensions/updater/sdk/smsdk_ext.cpp @@ -0,0 +1,465 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Base Extension Code + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#include +#include +#include "smsdk_ext.h" + +/** + * @file smsdk_ext.cpp + * @brief Contains wrappers for making Extensions easier to write. + */ + +IExtension *myself = NULL; /**< Ourself */ +IShareSys *g_pShareSys = NULL; /**< Share system */ +IShareSys *sharesys = NULL; /**< Share system */ +ISourceMod *g_pSM = NULL; /**< SourceMod helpers */ +ISourceMod *smutils = NULL; /**< SourceMod helpers */ + +#if defined SMEXT_ENABLE_FORWARDSYS +IForwardManager *g_pForwards = NULL; /**< Forward system */ +IForwardManager *forwards = NULL; /**< Forward system */ +#endif +#if defined SMEXT_ENABLE_HANDLESYS +IHandleSys *g_pHandleSys = NULL; /**< Handle system */ +IHandleSys *handlesys = NULL; /**< Handle system */ +#endif +#if defined SMEXT_ENABLE_PLAYERHELPERS +IPlayerManager *playerhelpers = NULL; /**< Player helpers */ +#endif //SMEXT_ENABLE_PLAYERHELPERS +#if defined SMEXT_ENABLE_DBMANAGER +IDBManager *dbi = NULL; /**< DB Manager */ +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMECONF +IGameConfigManager *gameconfs = NULL; /**< Game config manager */ +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_MEMUTILS +IMemoryUtils *memutils = NULL; +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMEHELPERS +IGameHelpers *gamehelpers = NULL; +#endif +#if defined SMEXT_ENABLE_TIMERSYS +ITimerSystem *timersys = NULL; +#endif +#if defined SMEXT_ENABLE_ADTFACTORY +IADTFactory *adtfactory = NULL; +#endif +#if defined SMEXT_ENABLE_THREADER +IThreader *threader = NULL; +#endif +#if defined SMEXT_ENABLE_LIBSYS +ILibrarySys *libsys = NULL; +#endif +#if defined SMEXT_ENABLE_PLUGINSYS +SourceMod::IPluginManager *plsys; +#endif +#if defined SMEXT_ENABLE_MENUS +IMenuManager *menus = NULL; +#endif +#if defined SMEXT_ENABLE_ADMINSYS +IAdminSystem *adminsys = NULL; +#endif +#if defined SMEXT_ENABLE_TEXTPARSERS +ITextParsers *textparsers = NULL; +#endif +#if defined SMEXT_ENABLE_USERMSGS +IUserMessages *usermsgs = NULL; +#endif +#if defined SMEXT_ENABLE_TRANSLATOR +ITranslator *translator = NULL; +#endif +#if defined SMEXT_ENABLE_NINVOKE +INativeInterface *ninvoke = NULL; +#endif + +/** Exports the main interface */ +PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI() +{ + return g_pExtensionIface; +} + +SDKExtension::SDKExtension() +{ +#if defined SMEXT_CONF_METAMOD + m_SourceMMLoaded = false; + m_WeAreUnloaded = false; + m_WeGotPauseChange = false; +#endif +} + +bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late) +{ + g_pShareSys = sharesys = sys; + myself = me; + +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; + + if (!m_SourceMMLoaded) + { + if (error) + { + snprintf(error, maxlength, "Metamod attach failed"); + } + return false; + } +#endif + SM_GET_IFACE(SOURCEMOD, g_pSM); + smutils = g_pSM; +#if defined SMEXT_ENABLE_HANDLESYS + SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys); + handlesys = g_pHandleSys; +#endif +#if defined SMEXT_ENABLE_FORWARDSYS + SM_GET_IFACE(FORWARDMANAGER, g_pForwards); + forwards = g_pForwards; +#endif +#if defined SMEXT_ENABLE_PLAYERHELPERS + SM_GET_IFACE(PLAYERMANAGER, playerhelpers); +#endif +#if defined SMEXT_ENABLE_DBMANAGER + SM_GET_IFACE(DBI, dbi); +#endif +#if defined SMEXT_ENABLE_GAMECONF + SM_GET_IFACE(GAMECONFIG, gameconfs); +#endif +#if defined SMEXT_ENABLE_MEMUTILS + SM_GET_IFACE(MEMORYUTILS, memutils); +#endif +#if defined SMEXT_ENABLE_GAMEHELPERS + SM_GET_IFACE(GAMEHELPERS, gamehelpers); +#endif +#if defined SMEXT_ENABLE_TIMERSYS + SM_GET_IFACE(TIMERSYS, timersys); +#endif +#if defined SMEXT_ENABLE_ADTFACTORY + SM_GET_IFACE(ADTFACTORY, adtfactory); +#endif +#if defined SMEXT_ENABLE_THREADER + SM_GET_IFACE(THREADER, threader); +#endif +#if defined SMEXT_ENABLE_LIBSYS + SM_GET_IFACE(LIBRARYSYS, libsys); +#endif +#if defined SMEXT_ENABLE_PLUGINSYS + SM_GET_IFACE(PLUGINSYSTEM, plsys); +#endif +#if defined SMEXT_ENABLE_MENUS + SM_GET_IFACE(MENUMANAGER, menus); +#endif +#if defined SMEXT_ENABLE_ADMINSYS + SM_GET_IFACE(ADMINSYS, adminsys); +#endif +#if defined SMEXT_ENABLE_TEXTPARSERS + SM_GET_IFACE(TEXTPARSERS, textparsers); +#endif +#if defined SMEXT_ENABLE_USERMSGS + SM_GET_IFACE(USERMSGS, usermsgs); +#endif +#if defined SMEXT_ENABLE_TRANSLATOR + SM_GET_IFACE(TRANSLATOR, translator); +#endif + + if (SDK_OnLoad(error, maxlength, late)) + { +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; +#endif + return true; + } + + return false; +} + +bool SDKExtension::IsMetamodExtension() +{ +#if defined SMEXT_CONF_METAMOD + return true; +#else + return false; +#endif +} + +void SDKExtension::OnExtensionPauseChange(bool state) +{ +#if defined SMEXT_CONF_METAMOD + m_WeGotPauseChange = true; +#endif + SDK_OnPauseChange(state); +} + +void SDKExtension::OnExtensionsAllLoaded() +{ + SDK_OnAllLoaded(); +} + +void SDKExtension::OnExtensionUnload() +{ +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; +#endif + SDK_OnUnload(); +} + +const char *SDKExtension::GetExtensionAuthor() +{ + return SMEXT_CONF_AUTHOR; +} + +const char *SDKExtension::GetExtensionDateString() +{ + return SMEXT_CONF_DATESTRING; +} + +const char *SDKExtension::GetExtensionDescription() +{ + return SMEXT_CONF_DESCRIPTION; +} + +const char *SDKExtension::GetExtensionVerString() +{ + return SMEXT_CONF_VERSION; +} + +const char *SDKExtension::GetExtensionName() +{ + return SMEXT_CONF_NAME; +} + +const char *SDKExtension::GetExtensionTag() +{ + return SMEXT_CONF_LOGTAG; +} + +const char *SDKExtension::GetExtensionURL() +{ + return SMEXT_CONF_URL; +} + +bool SDKExtension::SDK_OnLoad(char *error, size_t maxlength, bool late) +{ + return true; +} + +void SDKExtension::SDK_OnUnload() +{ +} + +void SDKExtension::SDK_OnPauseChange(bool paused) +{ +} + +void SDKExtension::SDK_OnAllLoaded() +{ +} + +#if defined SMEXT_CONF_METAMOD + +PluginId g_PLID = 0; /**< Metamod plugin ID */ +ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */ +SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */ +ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */ + +IVEngineServer *engine = NULL; /**< IVEngineServer pointer */ +IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */ + +/** Exposes the extension to Metamod */ +SMM_API void *PL_EXPOSURE(const char *name, int *code) +{ +#if defined METAMOD_PLAPI_VERSION + if (name && !strcmp(name, METAMOD_PLAPI_NAME)) +#else + if (name && !strcmp(name, PLAPI_NAME)) +#endif + { + if (code) + { + *code = IFACE_OK; + } + return static_cast(g_pExtensionIface); + } + + if (code) + { + *code = IFACE_FAILED; + } + + return NULL; +} + +bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) +{ + PLUGIN_SAVEVARS(); + +#if !defined METAMOD_PLAPI_VERSION + GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); + GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); +#else + GET_V_IFACE_ANY(GetServerFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); + GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); +#endif + + m_SourceMMLoaded = true; + + return SDK_OnMetamodLoad(ismm, error, maxlen, late); +} + +bool SDKExtension::Unload(char *error, size_t maxlen) +{ + if (!m_WeAreUnloaded) + { + if (error) + { + snprintf(error, maxlen, "This extension must be unloaded by SourceMod."); + } + return false; + } + + return SDK_OnMetamodUnload(error, maxlen); +} + +bool SDKExtension::Pause(char *error, size_t maxlen) +{ + if (!m_WeGotPauseChange) + { + if (error) + { + snprintf(error, maxlen, "This extension must be paused by SourceMod."); + } + return false; + } + + m_WeGotPauseChange = false; + + return SDK_OnMetamodPauseChange(true, error, maxlen); +} + +bool SDKExtension::Unpause(char *error, size_t maxlen) +{ + if (!m_WeGotPauseChange) + { + if (error) + { + snprintf(error, maxlen, "This extension must be unpaused by SourceMod."); + } + return false; + } + + m_WeGotPauseChange = false; + + return SDK_OnMetamodPauseChange(false, error, maxlen); +} + +const char *SDKExtension::GetAuthor() +{ + return GetExtensionAuthor(); +} + +const char *SDKExtension::GetDate() +{ + return GetExtensionDateString(); +} + +const char *SDKExtension::GetDescription() +{ + return GetExtensionDescription(); +} + +const char *SDKExtension::GetLicense() +{ + return SMEXT_CONF_LICENSE; +} + +const char *SDKExtension::GetLogTag() +{ + return GetExtensionTag(); +} + +const char *SDKExtension::GetName() +{ + return GetExtensionName(); +} + +const char *SDKExtension::GetURL() +{ + return GetExtensionURL(); +} + +const char *SDKExtension::GetVersion() +{ + return GetExtensionVerString(); +} + +bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late) +{ + return true; +} + +bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t maxlength) +{ + return true; +} + +bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength) +{ + return true; +} + +#endif + +/* 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 + diff --git a/extensions/updater/sdk/smsdk_ext.h b/extensions/updater/sdk/smsdk_ext.h new file mode 100644 index 00000000..61861866 --- /dev/null +++ b/extensions/updater/sdk/smsdk_ext.h @@ -0,0 +1,339 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Base Extension Code + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ + +/** + * @file smsdk_ext.h + * @brief Contains wrappers for making Extensions easier to write. + */ + +#include "smsdk_config.h" +#include +#include +#include +#include +#include +#if defined SMEXT_ENABLE_FORWARDSYS +#include +#endif //SMEXT_ENABLE_FORWARDSYS +#if defined SMEXT_ENABLE_PLAYERHELPERS +#include +#endif //SMEXT_ENABLE_PlAYERHELPERS +#if defined SMEXT_ENABLE_DBMANAGER +#include +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMECONF +#include +#endif +#if defined SMEXT_ENABLE_MEMUTILS +#include +#endif +#if defined SMEXT_ENABLE_GAMEHELPERS +#include +#endif +#if defined SMEXT_ENABLE_TIMERSYS +#include +#endif +#if defined SMEXT_ENABLE_ADTFACTORY +#include +#endif +#if defined SMEXT_ENABLE_THREADER +#include +#endif +#if defined SMEXT_ENABLE_LIBSYS +#include +#endif +#if defined SMEXT_ENABLE_PLUGINSYS +#include +#endif +#if defined SMEXT_ENABLE_MENUS +#include +#endif +#if defined SMEXT_ENABLE_ADMINSYS +#include +#endif +#if defined SMEXT_ENABLE_TEXTPARSERS +#include +#endif +#if defined SMEXT_ENABLE_USERMSGS +#include +#endif +#if defined SMEXT_ENABLE_TRANSLATOR +#include +#endif +#if defined SMEXT_ENABLE_NINVOKE +#include +#endif + +#if defined SMEXT_CONF_METAMOD +#include +#include +#endif + +using namespace SourceMod; +using namespace SourcePawn; + +class SDKExtension : +#if defined SMEXT_CONF_METAMOD + public ISmmPlugin, +#endif + public IExtensionInterface +{ +public: + /** Constructor */ + SDKExtension(); +public: + /** + * @brief This is called after the initial loading sequence has been processed. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @param late Whether or not the module was loaded after map load. + * @return True to succeed loading, false to fail. + */ + virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); + + /** + * @brief This is called right before the extension is unloaded. + */ + virtual void SDK_OnUnload(); + + /** + * @brief This is called once all known extensions have been loaded. + */ + virtual void SDK_OnAllLoaded(); + + /** + * @brief Called when the pause state is changed. + */ + virtual void SDK_OnPauseChange(bool paused); + +#if defined SMEXT_CONF_METAMOD + /** + * @brief Called when Metamod is attached, before the extension version is called. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @param late Whether or not Metamod considers this a late load. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late); + + /** + * @brief Called when Metamod is detaching, after the extension version is called. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); + + /** + * @brief Called when Metamod's pause state is changing. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param paused Pause state being set. + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); +#endif + +public: //IExtensionInterface + virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late); + virtual void OnExtensionUnload(); + virtual void OnExtensionsAllLoaded(); + + /** Returns whether or not this is a Metamod-based extension */ + virtual bool IsMetamodExtension(); + + /** + * @brief Called when the pause state changes. + * + * @param state True if being paused, false if being unpaused. + */ + virtual void OnExtensionPauseChange(bool state); + + /** Returns name */ + virtual const char *GetExtensionName(); + /** Returns URL */ + virtual const char *GetExtensionURL(); + /** Returns log tag */ + virtual const char *GetExtensionTag(); + /** Returns author */ + virtual const char *GetExtensionAuthor(); + /** Returns version string */ + virtual const char *GetExtensionVerString(); + /** Returns description string */ + virtual const char *GetExtensionDescription(); + /** Returns date string */ + virtual const char *GetExtensionDateString(); +#if defined SMEXT_CONF_METAMOD +public: //ISmmPlugin + /** Called when the extension is attached to Metamod. */ + virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late); + /** Returns the author to MM */ + virtual const char *GetAuthor(); + /** Returns the name to MM */ + virtual const char *GetName(); + /** Returns the description to MM */ + virtual const char *GetDescription(); + /** Returns the URL to MM */ + virtual const char *GetURL(); + /** Returns the license to MM */ + virtual const char *GetLicense(); + /** Returns the version string to MM */ + virtual const char *GetVersion(); + /** Returns the date string to MM */ + virtual const char *GetDate(); + /** Returns the logtag to MM */ + virtual const char *GetLogTag(); + /** Called on unload */ + virtual bool Unload(char *error, size_t maxlength); + /** Called on pause */ + virtual bool Pause(char *error, size_t maxlength); + /** Called on unpause */ + virtual bool Unpause(char *error, size_t maxlength); +private: + bool m_SourceMMLoaded; + bool m_WeAreUnloaded; + bool m_WeGotPauseChange; +#endif +}; + +extern SDKExtension *g_pExtensionIface; +extern IExtension *myself; + +extern IShareSys *g_pShareSys; +extern IShareSys *sharesys; /* Note: Newer name */ +extern ISourceMod *g_pSM; +extern ISourceMod *smutils; /* Note: Newer name */ + +/* Optional interfaces are below */ +#if defined SMEXT_ENABLE_FORWARDSYS +extern IForwardManager *g_pForwards; +extern IForwardManager *forwards; /* Note: Newer name */ +#endif //SMEXT_ENABLE_FORWARDSYS +#if defined SMEXT_ENABLE_HANDLESYS +extern IHandleSys *g_pHandleSys; +extern IHandleSys *handlesys; /* Note: Newer name */ +#endif //SMEXT_ENABLE_HANDLESYS +#if defined SMEXT_ENABLE_PLAYERHELPERS +extern IPlayerManager *playerhelpers; +#endif //SMEXT_ENABLE_PLAYERHELPERS +#if defined SMEXT_ENABLE_DBMANAGER +extern IDBManager *dbi; +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMECONF +extern IGameConfigManager *gameconfs; +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_MEMUTILS +extern IMemoryUtils *memutils; +#endif +#if defined SMEXT_ENABLE_GAMEHELPERS +extern IGameHelpers *gamehelpers; +#endif +#if defined SMEXT_ENABLE_TIMERSYS +extern ITimerSystem *timersys; +#endif +#if defined SMEXT_ENABLE_ADTFACTORY +extern IADTFactory *adtfactory; +#endif +#if defined SMEXT_ENABLE_THREADER +extern IThreader *threader; +#endif +#if defined SMEXT_ENABLE_LIBSYS +extern ILibrarySys *libsys; +#endif +#if defined SMEXT_ENABLE_PLUGINSYS +extern SourceMod::IPluginManager *plsys; +#endif +#if defined SMEXT_ENABLE_MENUS +extern IMenuManager *menus; +#endif +#if defined SMEXT_ENABLE_ADMINSYS +extern IAdminSystem *adminsys; +#endif +#if defined SMEXT_ENABLE_USERMSGS +extern IUserMessages *usermsgs; +#endif +#if defined SMEXT_ENABLE_TRANSLATOR +extern ITranslator *translator; +#endif +#if defined SMEXT_ENABLE_NINVOKE +extern INativeInterface *ninvoke; +#endif + +#if defined SMEXT_CONF_METAMOD +PLUGIN_GLOBALVARS(); +extern IVEngineServer *engine; +extern IServerGameDLL *gamedll; +#endif + +/** Creates a SourceMod interface macro pair */ +#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION +/** Automates retrieving SourceMod interfaces */ +#define SM_GET_IFACE(prefix, addr) \ + if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) \ + { \ + if (error != NULL && maxlength) \ + { \ + size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \ + if (len >= maxlength) \ + { \ + error[maxlength - 1] = '\0'; \ + } \ + } \ + return false; \ + } +/** Automates retrieving SourceMod interfaces when needed outside of SDK_OnLoad() */ +#define SM_GET_LATE_IFACE(prefix, addr) \ + g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr) +/** Validates a SourceMod interface pointer */ +#define SM_CHECK_IFACE(prefix, addr) \ + if (!addr) \ + { \ + if (error != NULL && maxlength) \ + { \ + size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \ + if (len >= maxlength) \ + { \ + error[maxlength - 1] = '\0'; \ + } \ + } \ + return false; \ + } + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ diff --git a/extensions/updater/svn_version.h b/extensions/updater/svn_version.h new file mode 100644 index 00000000..7d566f25 --- /dev/null +++ b/extensions/updater/svn_version.h @@ -0,0 +1,44 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod GeoIP Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +/** + * Autogenerated by build scripts + */ + +#ifndef _INCLUDE_UPDATER_VERSION_H_ +#define _INCLUDE_UPDATER_VERSION_H_ + +#define SM_BUILD_STRING "-dev" +#define SM_BUILD_UNIQUEID "2488:f7f1bbcc85e4" SM_BUILD_STRING +#define SVN_FULL_VERSION "1.2.0" SM_BUILD_STRING +#define SVN_FILE_VERSION 1,2,0,0 + +#endif //_INCLUDE_UPDATER_VERSION_H_ diff --git a/extensions/updater/svn_version.tpl b/extensions/updater/svn_version.tpl new file mode 100644 index 00000000..b7c5b638 --- /dev/null +++ b/extensions/updater/svn_version.tpl @@ -0,0 +1,44 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod GeoIP Extension + * 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 . + * + * 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 . + * + * Version: $Id$ + */ + +/** + * Autogenerated by build scripts + */ + +#ifndef _INCLUDE_UPDATER_VERSION_H_ +#define _INCLUDE_UPDATER_VERSION_H_ + +#define SM_BUILD_STRING "$BUILD_STRING$" +#define SM_BUILD_UNIQUEID "$BUILD_ID$" SM_BUILD_STRING +#define SVN_FULL_VERSION "$PMAJOR$.$PMINOR$.$PREVISION$" SM_BUILD_STRING +#define SVN_FILE_VERSION $PMAJOR$,$PMINOR$,$PREVISION$,0 + +#endif //_INCLUDE_UPDATER_VERSION_H_ diff --git a/extensions/updater/version.rc b/extensions/updater/version.rc new file mode 100644 index 00000000..4be4367d --- /dev/null +++ b/extensions/updater/version.rc @@ -0,0 +1,104 @@ +// Microsoft Visual C++ generated resource script. +// +//#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +#include "svn_version.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION SVN_FILE_VERSION + PRODUCTVERSION SVN_FILE_VERSION + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "Automatic Updater" + VALUE "FileDescription", "SourceMod Automatic Updater" + VALUE "FileVersion", SVN_FILE_VERSION + VALUE "InternalName", "SourceMod Updater Extension" + VALUE "LegalCopyright", "Copyright (c) 2004-2009, AlliedModders LLC" + VALUE "OriginalFilename", "updater.ext.dll" + VALUE "ProductName", "SourceMod Updater Extension" + VALUE "ProductVersion", SVN_FULL_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/public/IGameConfigs.h b/public/IGameConfigs.h index cb52ae2a..e9c63e88 100644 --- a/public/IGameConfigs.h +++ b/public/IGameConfigs.h @@ -42,7 +42,7 @@ */ #define SMINTERFACE_GAMECONFIG_NAME "IGameConfigManager" -#define SMINTERFACE_GAMECONFIG_VERSION 4 +#define SMINTERFACE_GAMECONFIG_VERSION 5 class SendProp; @@ -161,6 +161,16 @@ namespace SourceMod * @noreturn */ virtual void RemoveUserConfigHook(const char *sectionname, ITextListener_SMC *listener) =0; + + /** + * @brief Acquires a file reading lock on the gamedata system. + */ + virtual void AcquireLock() = 0; + + /** + * @brief Releases the file reading lock. + */ + virtual void ReleaseLock() = 0; }; } diff --git a/public/ISourceMod.h b/public/ISourceMod.h index 4daf7745..09d4bedf 100644 --- a/public/ISourceMod.h +++ b/public/ISourceMod.h @@ -43,7 +43,7 @@ #include #define SMINTERFACE_SOURCEMOD_NAME "ISourceMod" -#define SMINTERFACE_SOURCEMOD_VERSION 8 +#define SMINTERFACE_SOURCEMOD_VERSION 9 /** * @brief Forward declaration of the KeyValues class. @@ -70,6 +70,13 @@ namespace SourceMod */ typedef void (*GAME_FRAME_HOOK)(bool simulating); + /** + * @brief Function type for FrameAction callbacks. + * + * @param data User data pointer. + */ + typedef void (*FRAMEACTION)(void *data); + /** * @brief Contains miscellaneous helper functions. */ @@ -270,6 +277,16 @@ namespace SourceMod * @return Number of bytes (not including null terminator) written. */ virtual size_t FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap) = 0; + + /** + * @brief Adds an action to be executed on the next available frame. + * + * This function is thread safe. + * + * @param fn Function to execute. + * @param data Data to pass to function. + */ + virtual void AddFrameAction(FRAMEACTION fn, void *data) = 0; }; }