typedef struct world_location WORLD_LOCATION;
struct world_location
{
WORLD_LOCATION *next;
int *ruwid;
int *vnum;
char *type;
};
and in OBJ_DATA for instance,
…
WORLD_DATA *location;
int uwid;
…
struct npc {
…
int vnum;
struct area *areap;
int flags;
…
}
object *result = NPC_D->locate("/d/smurf_village/npc/*guard*");
foreach (object *ob in result) {
write("NPC " + ob->get_name() + " is in " + environment(ob)->get_name() + "\n";
}
struct npc *results = find_npc("/d/smurf_village/npc/*guard*");
struct npc *r = results;
while(r) {
send_to_char(ch, "NPC ");
send_to_char(ch, r->short_desc);
send_to_char(ch, " is in ");
send_to_char(ch, real_roomp(r->in_room)->name);
send_to_char(ch, "\n");
r++;
}
free(results);
r = results = NULL;
p_stmt = con->prepareStatement("SELECT level, keyword, text FROM helps WHERE keyword like ?");
p_stmt->setString(1, tainted_string);
void Character::do_help (std::string argument)
{
sqlite3_stmt *stmt = NULL;
if (argument.empty())
argument = "summary";
char *sql = sqlite3_mprintf("SELECT level, keyword, text FROM helps WHERE level <= %d", level);
if (sqlite3_prepare(g_db->database, sql, -1, &stmt, 0) != SQLITE_OK) {
bug_printf("Could not prepare statement: '%s' Error: %s", sql, sqlite3_errmsg(g_db->database));
sqlite3_free(sql);
return;
}
while (sqlite3_step(stmt) == SQLITE_ROW) {
int lvl = sqlite3_column_int( stmt, 0 );
std::string keyword = (const char*)sqlite3_column_text( stmt, 1 );
std::string text = (const char*)sqlite3_column_text( stmt, 2 );
if (is_name (argument, keyword)) {
if (lvl >= 0 && str_cmp (argument, "imotd")) {
send_to_char (keyword);
send_to_char ("\r\n");
}
send_to_char (text);
sqlite3_finalize(stmt);
sqlite3_free(sql);
return;
}
}
sqlite3_finalize(stmt);
sqlite3_free(sql);
send_to_char ("No help on that word.\r\n");
return;
}
…
f = sanitize_arg(argument);
// did we find any specials? if so, lets cancel the function and send a message about why..
if(f==1)
{
stc("#WPlease remove any special characters from your search string #0(#RE#rG#0:{4#W!@##$%^&*()_+':><,./?\|{{}[]=-`~#n#0)#W.#n\n\r",ch);
return;
}
// this is where we set the query string with our argument, and do our partial search as well in the form of %s = search %% = wildcard
// eg who or who whois or whois who or whois who whom or whois
//first lets check for the name
passed_arg = str_dup(check_help_arg(argument));
if(!stcmp(passed_arg[0], '\0')) //passed_arg set to null if 0 results - disallow certain bad word combos, drop table, insert / insert into
{
sprintf(buf, "#WNo help entry found for #0'#C%s#0'#W. The Immortals will be notified. You can also search for a category, like help all commands.#n\n", argument);
log_string(LOG_HELP,"Missing help for: %s",passed_arg);
stc(buf,ch);
return;
}
snprintf(query, sizeof(query) +1, "SELECT entry_num, level, category, keywords, text FROM bd_help WHERE keywords=\'%s\' OR keywords LIKE \'%s %%\' OR keywords LIKE \'%% %s\' OR keywords LIKE \'%% %s %%\' OR keywords LIKE \'%% %%%s %%\'OR keywords LIKE \'%% %s%% %%\' OR keywords LIKE \'%s%%\' LIMIT 10", passed_arg, passed_arg, passed_arg, passed_arg, passed_arg, passed_arg, passed_arg);
//sanitize and send the query off to SQL, then set the result set to res
mysql_safe_query(query);
res = mysql_store_result(&db);
while ((row = mysql_fetch_row(res))) // while row (data row from SQL) has a row result from res (result)…
{
int level;
level = atoi(row[1]);// lets do a late check to find level of helpfile to check if the requester can view!
if((ch->level < level) || (ch->trust < level))
{
sprintf(buf, "#WNo help entry found for '%s'#n\n", argument); //sorry bub, no way!
stc(buf,ch);
return;
}
if(e == 0) //are we at base initialization?
{
e = 1; //set our bit to 1 to mark our main result return
stc(" #0-#w=#W[#CB#croke#Cn #CD#cream#Cs #CH#cel#Cp #CS#cyste#Cm#W]#w=#0-#n\n\r",ch);
stc("#C+#0—————————————————————————#C+#n\n\r",ch);
sprintf(buf,"#WH#welp #WF#wile #WF#wound #R- #0[#RE#rntry#0: #R%d#0] [#CK#ceyword#0(#Cs#0): #W%s#0] [#CL#cevel#0: #C%d#0]#n\n\r", atoi(row[0]), row[3], level);
stc(buf,ch);
stc("#C+#0—————————————————————————#C+#n\n\r",ch);
sprintf(buf, "#W%s#n\n\r", row[4]);
stc(buf,ch);
stc("#C+#0—————————————————————————#C+#n\n\r",ch);
extra = TRUE;
}
else //this kicks in after the first loop - if there is one, so following found entries will show up as related helpfiles instead of dumping each helpfile that partially matches search string
{
if(extra == TRUE)
{
sprintf(buf, " #RT#rhe following were also found with partially matching keyword#W(#0s#W)#R:#n\n\r");
stc(buf,ch);
stc("#C+#0—————————————————————————#C+#n\n\r",ch);
extra = FALSE;
}
sprintf(buf, "#0(#GK#geyword #GM#gatch #0- #R%s #0)#R:#n", argument);
stc(buf, ch);
sprintf(buf,"#0[#RE#rntry#0: #R%d#0] [#CK#ceyword#0(#Cs#0): #W%s#0] [#CL#cevel#0: #C%d#0]#n\n\r", atoi(row[0]), row[3], level);
stc(buf,ch);
}
}
mysql_free_result(res); //free the result/memory
return; //done.
}
int query(char *qry) {
mysql_real_query(db, qry, strlen(qry));
if (*mysql_error(db)) {
log_printf("SQL Error: %s", mysql_error(db));
log(qry);
return 0;
}
return 1;
}
void query_printf (char *fmt, …) {
char buf[MAX_STRING_LENGTH];
va_list args;
va_start (args, fmt);
vsprintf (buf, fmt, args);
va_end (args);
query(buf);
}
void get_rows(char *qry, …) {
char buf[MAX_STRING_LENGTH];
va_list args;
va_start (args, qry);
vsprintf (buf, qry, args);
va_end (args);
query(buf);
result = mysql_store_result(db);
}
int get_field(char *field) {
MYSQL_FIELD *f;
if (!result)
return NOTHING;
mysql_field_seek(result, 0);
while ((f = mysql_fetch_field(result)))
if (!strcmp(field, f->name))
return mysql_field_tell(result)-1;
return -1;
}
char *get_first_field(MYSQL_RES *r, char *field) {
mysql_data_seek(r, 0);
row = mysql_fetch_row(r);
result = r;
return row[get_field(field)];
}
/* remember to do you own freeing */
MYSQL_ROW get_row(char *qry) {
query(qry);
result = mysql_store_result(db);
return mysql_fetch_row(result);
}
#define VAL_S(f) row[get_field(f)]
#define VAL_I(f) atoi(row[get_field(f)])
#define VAL_L(f) atol(row[get_field(f)])
#define VAL_F(f) atof(row[get_field(f)])
snprintf(query, sizeof(query) +1, "SELECT entry_num, level, category, keywords, text FROM bd_help WHERE keywords=\'%s\' OR keywords LIKE \'%s %%\' OR keywords LIKE \'%% %s\' OR keywords LIKE \'%% %s %%\' OR keywords LIKE \'%% %%%s %%\'OR keywords LIKE \'%% %s%% %%\' OR keywords LIKE \'%s%%\' LIMIT 10", passed_arg, passed_arg, passed_arg, passed_arg, passed_arg, passed_arg, passed_arg);
"SELECT entry_num, level, category, keywords, text FROM bd_help WHERE keywords LIKE \'%% %s%% %%\' OR keywords LIKE \'%s%%\' LIMIT 10"
void query_printf (char *fmt, …) {
char buf[MAX_STRING_LENGTH];
va_list args;
va_start (args, fmt);
vsprintf (buf, fmt, args);
va_end (args);
query(buf);
}
void query_printf (char *fmt, …) {
char buf[MAX_STRING_LENGTH];
va_list args;
va_start (args, fmt);
vsnprintf (buf, sizeof(buf), fmt, args);
va_end (args);
query(buf);
}
Help.all.where(:name.like => "commands';drop table players;")
Help.all.where(:name.like => "commands';drop table players;")
tainted_string = "commands';drop table players;"
Help.where("keywords LIKE '#{tainted_string}'") # subject to injection
Help.where("keywords LIKE ?", tainted_string) # not subject to injection
That makes perfect sense. I can tell you I am not remotely a DBA, clearly, and am just garnering the slight knowledge of how not to completely look like a fool, just mostly look like one. We all learn. At any rate, I think my internal war was/is with the (clearly in context to the systems herein) massive data structures and countless bits and bobs every tom dick and harry decided to tack on over the years. While I mentally would love to segregate a lot of that garbage out (beyond things that I am/will outright remove), having someone point out that, no that ledge isnt so shallow, was what I needed.
I am less concerned with the memory use, or size, specifically, and just more concerned with creating a backend system that actually makes sense from a data perspective. Clearly I am no World of Warcraft, and as you easily pointed out a visual medium allows for more subterfuge regarding loading and how to obfuscate any data call lag times. We obviously do not have that luxury in nearly any case.
I think I've run into shiny toy territory and need to be more objective in my scoping. While the DB is and will be perfect for a lot of things, and warehousing data, it will also often be a square peg to this or that problems round hole. As I learn more about this new toy I am confident I will see that line more easily, but for now should temper my enthusiasm with some cold realism.
Outside of that dose of reality, w.r.t. saving stateful information of 'objects' in memory, how often do you do that? I was contemplating setting up an event queue, actually I inserted one based off of Jobo's socketmud setup with some tweaks, regardless, I was contemplating a staggered event setup with varying intervals depending on importance of the data in question, for items that I retain and manipulate in memory. I suppose mostly the interval times would be dependent on how much of a potential data loss I would be willing to take..
Jees it seems like I am just asking obvious somewhat redundant questions going back to, use common sense and look at your own context. So apologies for that. I think this has helped me think through what my gut has been telling me about many things in relation to all of this, and the responses, even if it is akin to use common sense, are helpful in validating that.
So perhaps I should break with that and simply ask;
Were you to give someone who is relatively new to using a DBMS in this context, or any, advice what would it be?