Dynamically T_Magic
#1

Hi guys!



Since i seen the t_magic system doesn't use the lod file, i was thinking about dynamically load the data from the db when is needed by using a gm command. I've tested many stuff without any result ... the last thing i tried was to reload everything in a temp struct and then just overwrite the original one. Someone have a better idea about how to handle this 

 

```C++
bool CMagicProtoList::ReloadFromDB() {
CDBCmd cmd1;
CDBCmd cmd2;
cmd1.Init(&gserver->m_dbdata);
cmd2.Init(&gserver->m_dbdata);

cmd1.SetQuery("SELECT * FROM t_magic ORDER BY a_index");
if (!cmd1.Open())
return false;

int new_count = cmd1.m_nrecords;
if (new_count) {
// Create a temporary array to hold the new CMagicProto objects
CMagicProto** temp_list = new CMagicProto * [new_count];

int i = 0;
while (cmd1.MoveNext()) {
int index;
char maxlevel;
char type;
char subtype;
char damagetype;
char hittype;
char attribute;
int psp;
int ptp;
int hsp;
int htp;
int bTogel;

cmd1.GetRec("a_index", index);
cmd1.GetRec("a_maxlevel", maxlevel);
cmd1.GetRec("a_type", type);
cmd1.GetRec("a_subtype", subtype);
cmd1.GetRec("a_damagetype", damagetype);
cmd1.GetRec("a_hittype", hittype);
cmd1.GetRec("a_attribute", attribute);
cmd1.GetRec("a_psp", psp);
cmd1.GetRec("a_ptp", ptp);
cmd1.GetRec("a_hsp", hsp);
cmd1.GetRec("a_htp", htp);
cmd1.GetRec("a_togle", bTogel);

std:Confusedtring select_magiclevel_query = boost:Confusedtr(boost::format(
"SELECT * FROM t_magiclevel WHERE a_index=%d ORDER BY a_level") % index);

cmd2.SetQuery(select_magiclevel_query);
if (!cmd2.Open()) {
for (int k = 0; k < i; ++k) {
delete temp_list[k];
}
delete[] temp_list;
return false;
}

CMagicLevelProto** levelproto = new CMagicLevelProto * [maxlevel];
memset(levelproto, 0, sizeof(*levelproto) * maxlevel);
int j = 0;
while (cmd2.MoveNext()) {
int power;
int hitrate;

cmd2.GetRec("a_power", power);
cmd2.GetRec("a_hitrate", hitrate);

levelproto[j] = new CMagicLevelProto(power, hitrate);

j++;
}

// Create CMagicProto object with provided constructor
temp_list[i] = new CMagicProto(index, maxlevel, type, subtype,
damagetype, hittype, attribute,
psp, ptp, hsp, htp, bTogel,
levelproto);

// Increment i
i++;
}

// No need to delete old CMagicProto objects here
// Just update m_list with the new data
if (m_list)
{
m_list = temp_list;
m_count = new_count;
}
}
else
LOG_ERROR("new_count is null");
return true;
}
```

 

#2

Just wanna add more information since i am dig in to it:





i've manage to make it works correctly but if you launch the command a few times, it sometimes report the error 3306 has been blocked. The system should still works as expected ? 

 

bool CMagicProtoList::ReloadFromDB() {
CDBCmd cmd1;
CDBCmd cmd2;
cmd1.Init(&gserver->m_dbdata);
cmd2.Init(&gserver->m_dbdata);

cmd1.SetQuery("SELECT * FROM t_magic ORDER BY a_index");
if (!cmd1.Open())
return false;

while (cmd1.MoveNext()) {
int index;
char maxlevel;
char type;
char subtype;
char damagetype;
char hittype;
char attribute;
int psp;
int ptp;
int hsp;
int htp;
int bTogel;

cmd1.GetRec("a_index", index);
cmd1.GetRec("a_maxlevel", maxlevel);
cmd1.GetRec("a_type", type);
cmd1.GetRec("a_subtype", subtype);
cmd1.GetRec("a_damagetype", damagetype);
cmd1.GetRec("a_hittype", hittype);
cmd1.GetRec("a_attribute", attribute);
cmd1.GetRec("a_psp", psp);
cmd1.GetRec("a_ptp", ptp);
cmd1.GetRec("a_hsp", hsp);
cmd1.GetRec("a_htp", htp);
cmd1.GetRec("a_togle", bTogel);

std:Confusedtring select_magiclevel_query = boost:Confusedtr(boost::format(
"SELECT * FROM t_magiclevel WHERE a_index=%d ORDER BY a_level") % index);

cmd2.SetQuery(select_magiclevel_query);
if (!cmd2.Open())
return false;

CMagicLevelProto** levelproto = new CMagicLevelProto * [maxlevel];
memset(levelproto, 0, sizeof(CMagicLevelProto*) * maxlevel);
int j = 0;
while (cmd2.MoveNext()) {
int power;
int hitrate;

cmd2.GetRec("a_power", power);
cmd2.GetRec("a_hitrate", hitrate);

levelproto[j] = new CMagicLevelProto(power, hitrate);
j++;
}

// Find the existing CMagicProto object in m_list by index
for (int k = 0; k < m_count; ++k) {
if (m_list[k]->m_index == index) {
// Update the m_levelproto with the new levelproto
//delete[] m_list[k]->m_levelproto; // Delete the old levelproto array (commented since may crash the reference, but may occure in memory leaks!)
m_list[k]->m_levelproto = levelproto; // Assign the new levelproto array
break;
}
}
}

return true;
}

 

#3

found that there was the spamblock system which cause this issues, i blocked it on client side. the system seems to works fine. You can also uncomment the delete[] m_list[k]->m_levelproto; part, since it works fine and fix the memory leaks issue ... i may convert this topic to a release ... but i am too lazy and not sure about it, so let me know ^^ 

#4

Have a look at this, maybe it helps a bit:

bool CMagicProtoList::ReloadFromDB() {
CDBCmd cmd1;
CDBCmd cmd2;
cmd1.Init(&gserver->m_dbdata);
cmd2.Init(&gserver->m_dbdata);
cmd1.SetQuery("SELECT * FROM t_magic ORDER BY a_index");
if (!cmd1.Open())
return false;
int new_count = cmd1.m_nrecords;
if (new_count) {
// Create a temporary array to hold the new CMagicProto objects
CMagicProto** temp_list = new CMagicProto * [new_count];
memset(temp_list, 0, sizeof(CMagicProto*) * new_count);
int i = 0;
while (cmd1.MoveNext()) {
int index;
char maxlevel;
char type;
char subtype;
char damagetype;
char hittype;
char attribute;
int psp;
int ptp;
int hsp;
int htp;
int bTogel;
cmd1.GetRec("a_index", index);
cmd1.GetRec("a_maxlevel", maxlevel);
cmd1.GetRec("a_type", type);
cmd1.GetRec("a_subtype", subtype);
cmd1.GetRec("a_damagetype", damagetype);
cmd1.GetRec("a_hittype", hittype);
cmd1.GetRec("a_attribute", attribute);
cmd1.GetRec("a_psp", psp);
cmd1.GetRec("a_ptp", ptp);
cmd1.GetRec("a_hsp", hsp);
cmd1.GetRec("a_htp", htp);
cmd1.GetRec("a_togle", bTogel);
std:Confusedtring select_magiclevel_query = boost:Confusedtr(boost::format(
"SELECT * FROM t_magiclevel WHERE a_index=%d ORDER BY a_level") % index);
cmd2.SetQuery(select_magiclevel_query);
if (!cmd2.Open()) {
for (int k = 0; k < i; ++k) {
delete temp_list[k];
}
delete[] temp_list;
return false;
}
CMagicLevelProto** levelproto = new CMagicLevelProto * [maxlevel];
memset(levelproto, 0, sizeof(CMagicLevelProto*) * maxlevel);
int j = 0;
while (cmd2.MoveNext()) {
int power;
int hitrate;
cmd2.GetRec("a_power", power);
cmd2.GetRec("a_hitrate", hitrate);
levelproto[j] = new CMagicLevelProto(power, hitrate);
j++;
}
// Create CMagicProto object with provided constructor
temp_list[i] = new CMagicProto(index, maxlevel, type, subtype,
damagetype, hittype, attribute,
psp, ptp, hsp, htp, bTogel,
levelproto);
// Increment i
i++;
}
// No need to delete old CMagicProto objects here
// Just update m_list with the new data
if (m_list) {
for (int k = 0; k < m_count; ++k) {
delete m_list[k];
}
delete[] m_list;
}
m_list = temp_list;
m_count = new_count;
} else {
LOG_ERROR("new_count is null");
return false;
}
return true;
}

 

#5

Yeah, that was the first thing I tried, but it also crashed the game server since you essentially delete the main reference of the address in memory. I got an access violation, and then I realized I needed to update all the address that refer to the struct in memory ... at least i thought .... open to discussion on it, have you tried by yourself ? 

 

When you perform tthis action, the orginal address of the list is destroyed 

delete[] m_list;

 

and doing something like this is horrible

 

CMagicProtoList::~CMagicProtoList()
{
}



just end up reassigne the new value to the default structure was fine.

#6

I see, it is the main problem... the memory management. Not much to do there, you would need to do a specific memory management void. Good work there



Forum Jump:


Users browsing this thread: 2 Guest(s)