Code:
? output.diff
? Source/common/default_Hooks.cpp
? Source/common/default_Hooks.h
Index: Source/common/rulesys.cpp
===================================================================
RCS file: /cvsroot/eqemulator/EQEmuCVS/Source/common/rulesys.cpp,v
retrieving revision 1.2.2.2
diff -u -b -B -r1.2.2.2 rulesys.cpp
--- Source/common/rulesys.cpp 31 Oct 2006 02:02:54 -0000 1.2.2.2
+++ Source/common/rulesys.cpp 19 Jan 2008 13:37:36 -0000
@@ -20,7 +20,10 @@
#include "logsys.h"
#include "database.h"
#include "MiscFunctions.h"
-
+#ifndef WIN32
+/* On Linux, include the headers for libdl for dynamic library loading */
+#include <dlfcn.h>
+#endif /* !WIN32 */
/*
FatherNitwit: Added new rules subsystem to allow game rules to be changed
@@ -73,7 +76,7 @@
"InvalidCategory"
};
-const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+1] = {
+const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+_HookRuleCount+1] = {
/* this is done in three steps so we can reliably get to them by index*/
#define RULE_INT(cat, rule, default_value) \
{ #cat ":" #rule, Category__##cat, IntRule, Int__##rule },
@@ -84,6 +87,9 @@
#define RULE_BOOL(cat, rule, default_value) \
{ #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule },
#include "ruletypes.h"
+ #define RULE_HOOK(cat, rule, default_value) \
+ { #cat ":" #rule, Category__##cat, HookRule, Hook__##rule },
+ #include "ruletypes.h"
{ "Invalid Rule", _CatCount, IntRule }
};
@@ -149,6 +155,56 @@
m_RuleRealValues[index] = atof(rule_value);
_log(RULES__CHANGE, "Set rule %s to value %.13f", rule_name, m_RuleRealValues[index]);
break;
+ case HookRule:
+ { char *fLibraryName = NULL, *fFunctionName = NULL;
+ Hook ThisHook = NULL;
+ const char *Colon = strchr(rule_value, ':');
+ if(Colon == NULL)
+ _log(RULES__ERROR, "Badly-formed hook value '%s' (rule '%s'). It must contain a colon (:). Ignoring this hook", rule_value, rule_name);
+ else
+ { fLibraryName = (char *) malloc(Colon - rule_value + 128 + 1); /* 128 = let's assume it is more than enough to append a file extension to the library if needed */
+ strncpy(fLibraryName, rule_value, Colon - rule_value); fLibraryName[Colon - rule_value] = '\0';
+ fFunctionName = (char *) malloc(strlen(rule_value) - (Colon - rule_value + 1) + 1);
+ strcpy(fFunctionName, Colon + 1);
+ }
+#ifdef WIN32
+ HMODULE ThisLibrary = NULL;
+ if(fLibraryName != NULL)
+ { strcat(fLibraryName, ".dll");
+ ThisLibrary = LoadLibrary(fLibraryName);
+ if(ThisLibrary == NULL)
+ _log(RULES__ERROR, "Cannot load library '%s' needed by hook '%s' (rule '%s'). Ignoring this hook", fLibraryName, rule_value, rule_name);
+ }
+
+ if(ThisLibrary != NULL)
+ { ThisHook = GetProcAddress(ThisLibrary, fFunctionName);
+ if(ThisHook == NULL)
+ _log(RULES__ERROR, "Cannot load library function '%s' needed by hook '%s' (rule '%s'). Ignoring this hook", fFunctionName, rule_value, rule_name);
+ }
+#else /* WIN32 */
+ void *ThisLibrary = NULL;
+ if(fLibraryName != NULL)
+ { strcat(fLibraryName, ".so");
+ ThisLibrary = dlopen(fLibraryName, RTLD_NOW | RTLD_GLOBAL);
+ if(ThisLibrary == NULL)
+ _log(RULES__ERROR, "Cannot load library '%s' needed by hook '%s' (rule '%s'). Ignoring this hook", fLibraryName, rule_value, rule_name);
+ }
+
+ if(ThisLibrary != NULL)
+ { ThisHook = dlsym(ThisLibrary, fFunctionName);
+ if(ThisHook == NULL)
+ _log(RULES__ERROR, "Cannot load library function '%s' needed by hook '%s' (rule '%s'). Ignoring this hook", fFunctionName, rule_value, rule_name);
+ }
+ /*_log(RULES__ERROR, "The rule hooks are not yet implemented on this platform. Ignoring hook '%s' for fule '%s'", rule_value, rule_name);*/
+#endif /* WIN32 */
+ if(ThisHook != NULL)
+ { m_RuleHookValues[index] = ThisHook;
+ _log(RULES__CHANGE, "Set rule %s to value %d", rule_name, (int) m_RuleHookValues[index]);
+ }
+ if(fLibraryName != NULL) { free(fLibraryName); fLibraryName = NULL; }
+ if(fFunctionName != NULL) { free(fFunctionName); fFunctionName = NULL; }
+ break;
+ }
case BoolRule:
bool val = false;
if(!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
@@ -172,6 +228,8 @@
m_RuleRealValues[ Real__##rule ] = default_value;
#define RULE_BOOL(cat, rule, default_value) \
m_RuleBoolValues[ Bool__##rule ] = default_value;
+ #define RULE_HOOK(cat, rule, default_value) \
+ m_RuleHookValues[ Hook__##rule ] = default_value;
#include "ruletypes.h"
}
@@ -202,6 +260,8 @@
return(s_RuleInfo[index+_IntRuleCount].name);
case BoolRule:
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
+ case HookRule:
+ return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount+_BoolRuleCount].name);
}
//should never happen
return("InvalidRule??");
@@ -236,6 +296,9 @@
for(r = 0; r < _BoolRuleCount; r++) {
_SaveRule(db, BoolRule, r);
}
+ for(r = 0; r < _HookRuleCount; r++) {
+ _SaveRule(db, HookRule, r);
+ }
}
@@ -280,7 +343,10 @@
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
char vstr[16];
- switch(type) {
+ if(type == HookRule)
+ _log(RULES__ERROR, "Impossible to save hook rule %s in the database. Hook rule saving is not supported", _GetRuleName(type, index));
+ else
+ { switch(type) {
case IntRule:
sprintf(vstr, "%d", m_RuleIntValues[index]);
break;
@@ -302,6 +368,7 @@
_log(RULES__ERROR, "Fauled to set rule in the database: %s: %s", query,errbuf);
}
safe_delete_array(query);
+ }
}
Index: Source/common/rulesys.h
===================================================================
RCS file: /cvsroot/eqemulator/EQEmuCVS/Source/common/rulesys.h,v
retrieving revision 1.2.2.2
diff -u -b -B -r1.2.2.2 rulesys.h
--- Source/common/rulesys.h 31 Oct 2006 02:02:54 -0000 1.2.2.2
+++ Source/common/rulesys.h 19 Jan 2008 10:07:13 -0000
@@ -35,6 +35,8 @@
rules->GetRealRule( RuleManager::Real__##rule )
#define RuleB(cat, rule) \
rules->GetBoolRule( RuleManager::Bool__##rule )
+#define RuleH(cat, rule) \
+ rules->GetHookRule( RuleManager::Hook__##rule )
#include <vector>
@@ -42,6 +44,7 @@
#include <map>
#include "types.h"
+#include "../common/default_Hooks.h"
class Database;
@@ -70,6 +73,13 @@
} BoolType;
typedef enum {
+ #define RULE_HOOK(cat, rule, default_value) \
+ Hook__##rule,
+ #include "ruletypes.h"
+ _HookRuleCount
+ } HookType;
+
+ typedef enum {
#define RULE_CATEGORY(catname) \
Category__##catname,
#include "ruletypes.h"
@@ -79,9 +89,10 @@
static const IntType InvalidInt = _IntRuleCount;
static const RealType InvalidReal = _RealRuleCount;
static const BoolType InvalidBool = _BoolRuleCount;
+ static const HookType InvalidHook = _HookRuleCount;
static const CategoryType InvalidCategory = _CatCount;
- static const uint32 _RulesCount = _IntRuleCount+_RealRuleCount+_BoolRuleCount;
+ static const uint32 _RulesCount = _IntRuleCount+_RealRuleCount+_BoolRuleCount+_HookRuleCount;
RuleManager();
@@ -89,11 +100,13 @@
inline int GetIntRule (IntType t) const { return(m_RuleIntValues[t] ); }
inline float GetRealRule(RealType t) const { return(m_RuleRealValues[t]); }
inline bool GetBoolRule(BoolType t) const { return(m_RuleBoolValues[t]); }
+ inline Hook GetHookRule(HookType t) const { return(m_RuleHookValues[t]); }
//management routines
static const char *GetRuleName(IntType t) { return(s_RuleInfo[t].name); }
static const char *GetRuleName(RealType t) { return(s_RuleInfo[t+_IntRuleCount].name); }
static const char *GetRuleName(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].name); }
+ static const char *GetRuleName(HookType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount+_BoolRuleCount].name); }
static uint32 CountRules() { return(_RulesCount); }
static CategoryType FindCategory(const char *catname);
bool ListRules(const char *catname, std::vector<const char *> &into);
@@ -117,11 +130,13 @@
int m_RuleIntValues [_IntRuleCount ];
float m_RuleRealValues[_RealRuleCount];
bool m_RuleBoolValues[_BoolRuleCount];
+ Hook m_RuleHookValues[_HookRuleCount];
typedef enum {
IntRule,
RealRule,
- BoolRule
+ BoolRule,
+ HookRule
} RuleType;
static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into);
Index: Source/common/ruletypes.h
===================================================================
RCS file: /cvsroot/eqemulator/EQEmuCVS/Source/common/ruletypes.h,v
retrieving revision 1.3.2.8
diff -u -b -B -r1.3.2.8 ruletypes.h
--- Source/common/ruletypes.h 21 Feb 2007 16:04:19 -0000 1.3.2.8
+++ Source/common/ruletypes.h 19 Jan 2008 12:42:10 -0000
@@ -13,6 +13,9 @@
#ifndef RULE_BOOL
#define RULE_BOOL(cat, rule, default_value)
#endif
+#ifndef RULE_HOOK
+#define RULE_HOOK(cat, rule, default_value)
+#endif
#ifndef RULE_CATEGORY_END
#define RULE_CATEGORY_END()
#endif
@@ -71,10 +74,16 @@
RULE_REAL ( Combat, ClientBaseCritChance, 0.0 ) //The base crit chance for all clients, this will stack with warrior's/zerker's crit chance.
RULE_CATEGORY_END()
+RULE_CATEGORY( CharacterCreation )
+RULE_HOOK ( CharacterCreation, ChangeCreationInfo, (Hook) default_CharacterCreation_ChangeCreationInfo )
+RULE_CATEGORY_END()
+
+
#undef RULE_CATEGORY
#undef RULE_INT
#undef RULE_REAL
#undef RULE_BOOL
+#undef RULE_HOOK
#undef RULE_CATEGORY_END