Rocker8956
09-05-2008, 03:23 PM
Sorry if this is the wrong place to post this, I couldn't see a better place.
Please note the code below is not fully functional. It requires manual entries in the database and does not really do anything yet. I am posting this code incase someone else has a use for pieces of it, even though it is probably terrible code. I would also appreciate comments on what I should change, etc.
After messing around with zone instancing I have finally come to a road block.
Basically the problem I have run into is the current code seems to be setup to use the zone short name as the unique id. This causes a problem since that short_name can not be changed on a copied zone entry because the short name is also used to pull the map data (please correct me if I am wrong)
So anyhow, below is the code I have written so far. It basically only copies the zone information into a new zone table entry. When the server tries to load that new entry it crashes. The crash seems to be caused by two entries with the same short_name since in multiple places in the code the short name is used as the unique id instead of the zoneidnumber.
To get the code to semi function the instZflagNum and instZorgID must be manually filled along with the zone.insttype.
Character_.instZflagNum – pick any number higher then 1000
Zone.insttype – pick the zone you want to be instanced then set this to 1 or greater
Character_.instZflagNum – use the zoneidnumber of the zone you set insttype on.
Sorry my SQL and C++ are bad but here is an attempted diff. If someone is willing to write the true SQL commands for the below database changes I would be very grateful.
Required SQL
Zone table:
ADD insttype column: tinyint(1) unsigned zerofill NOT NULL default '0',
Change PRIMARY KEY to zoneidnumber
Change UNIQUE KEY to zoneidnumber
Character_ table:
ADD instZflagNum column int(10) unsigned NOT NULL default '0'
ADD instZOrgID column int(11) NOT NULL default '0'
Variables table
Insert into `variables`(`varname`,`value`,`information`,`ts`) values (curInstFlagNum','1000','Character:curInstFlagNum' ,'2008-09-05 04:46:47');
Rules_values table:
insert into `rule_values`(`ruleset_id`,`rule_name`,`rule_value `) values (0,'World:dfltInstZflag','1000')
Code changes (written on 7.0-1128 source)
Zonedb.h
Line 171 to Line 176
int8 GetInstType(int32 zoneid);
int32 GetCharInstFlagNum(int32 characterID);
int32 GetDfltInstZFlag();
int32 GetCharInstZOrgID(int32 characterID);
bool InstZoneLoaded(int32 target_zone_ID);
void LoadInstZone(int32 target_zone_ID, int32 InstFlagNum);
Zonedb.cpp
Line 1381 to line 1521 (basically append to the end of zonedb.cpp)
int8 ZoneDatabase::GetInstType(int32 zoneid) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT insttype FROM zone WHERE zoneidnumber=%i", zoneid), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int8 tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetInstType query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
int32 ZoneDatabase::GetCharInstFlagNum(int32 characterID){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZflagNum FROM character_ WHERE id=%i", characterID), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetCharInstFlag Numquery '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
int32 ZoneDatabase::GetDfltInstZFlag(){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT rule_value FROM rule_values WHERE rule_name = 'World:dfltInstZflag'"), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int32 tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetDfltInstZFlag query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
int32 ZoneDatabase::GetCharInstZOrgID(int32 characterID){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZOrgID FROM character_ WHERE id=%i", characterID), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int32 tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetInstType query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
bool ZoneDatabase::InstZoneLoaded(int32 charInstFlagNum){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT zoneidnumber FROM zone WHERE zoneidnumber=%i", charInstFlagNum), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
return true;
}
else if (mysql_num_rows(result) == 0) {
return false;
}
mysql_free_result(result);
}
else {
cerr << "Error in isInstZoneLoad query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
//Copies original zones information into a new zone entry replacing the old zoneidnumber with the instflagnum
void ZoneDatabase::LoadInstZone(int32 target_zone_ID, int32 InstFlagNum){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
int32 affected_rows = 0;
if (RunQuery(query, MakeAnyLenString(&query, "INSERT INTO zone (short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, zoneidnumber, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer) SELECT short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, %i, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer FROM zone WHERE zoneidnumber =%i", InstFlagNum, target_zone_ID), errbuf, 0, &affected_rows)){
safe_delete_array(query);
}
else {
cerr << "Error in LoadInstZone query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
zoning.cpp
Line 123 to line 157
//Prelim Instance zone code
int32 characterID = database.GetCharacterID(zc->char_name);
//Checks if the zone can be instanced, character has a instance flag, and
//that the character is not zoning into an instance that is already loaded
if((database.GetInstType(target_zone_id) == 1)&
(database.GetCharInstFlagNum(characterID) >= database.GetDfltInstZFlag())&
(target_zone_id != database.GetCharInstFlagNum(characterID)))
{
int32 charInstFlagNum = database.GetCharInstFlagNum(characterID);
int32 charInstZOrgID = database.GetCharInstZOrgID(characterID);
// Does character's instance flag match the zone he/she is trying to access
if(charInstZOrgID != target_zone_id)
{
Message(13, "No access flag to target instanced zone.");
SendZoneCancel(zc); // zoning.cpp line 130
return;
}
// Of instance flag matches then...
if(charInstZOrgID == target_zone_id)
{
//If instance zone is not in database then it is copied to database
if(!database.InstZoneLoaded(charInstFlagNum))
{
database.LoadInstZone(target_zone_id, charInstFlagNum);
target_zone_id = charInstFlagNum;
zc->zoneID = charInstFlagNum;
}
else
{
target_zone_id = charInstFlagNum;
zc->zoneID = charInstFlagNum;
}
}
}
Please note the code below is not fully functional. It requires manual entries in the database and does not really do anything yet. I am posting this code incase someone else has a use for pieces of it, even though it is probably terrible code. I would also appreciate comments on what I should change, etc.
After messing around with zone instancing I have finally come to a road block.
Basically the problem I have run into is the current code seems to be setup to use the zone short name as the unique id. This causes a problem since that short_name can not be changed on a copied zone entry because the short name is also used to pull the map data (please correct me if I am wrong)
So anyhow, below is the code I have written so far. It basically only copies the zone information into a new zone table entry. When the server tries to load that new entry it crashes. The crash seems to be caused by two entries with the same short_name since in multiple places in the code the short name is used as the unique id instead of the zoneidnumber.
To get the code to semi function the instZflagNum and instZorgID must be manually filled along with the zone.insttype.
Character_.instZflagNum – pick any number higher then 1000
Zone.insttype – pick the zone you want to be instanced then set this to 1 or greater
Character_.instZflagNum – use the zoneidnumber of the zone you set insttype on.
Sorry my SQL and C++ are bad but here is an attempted diff. If someone is willing to write the true SQL commands for the below database changes I would be very grateful.
Required SQL
Zone table:
ADD insttype column: tinyint(1) unsigned zerofill NOT NULL default '0',
Change PRIMARY KEY to zoneidnumber
Change UNIQUE KEY to zoneidnumber
Character_ table:
ADD instZflagNum column int(10) unsigned NOT NULL default '0'
ADD instZOrgID column int(11) NOT NULL default '0'
Variables table
Insert into `variables`(`varname`,`value`,`information`,`ts`) values (curInstFlagNum','1000','Character:curInstFlagNum' ,'2008-09-05 04:46:47');
Rules_values table:
insert into `rule_values`(`ruleset_id`,`rule_name`,`rule_value `) values (0,'World:dfltInstZflag','1000')
Code changes (written on 7.0-1128 source)
Zonedb.h
Line 171 to Line 176
int8 GetInstType(int32 zoneid);
int32 GetCharInstFlagNum(int32 characterID);
int32 GetDfltInstZFlag();
int32 GetCharInstZOrgID(int32 characterID);
bool InstZoneLoaded(int32 target_zone_ID);
void LoadInstZone(int32 target_zone_ID, int32 InstFlagNum);
Zonedb.cpp
Line 1381 to line 1521 (basically append to the end of zonedb.cpp)
int8 ZoneDatabase::GetInstType(int32 zoneid) {
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT insttype FROM zone WHERE zoneidnumber=%i", zoneid), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int8 tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetInstType query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
int32 ZoneDatabase::GetCharInstFlagNum(int32 characterID){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZflagNum FROM character_ WHERE id=%i", characterID), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetCharInstFlag Numquery '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
int32 ZoneDatabase::GetDfltInstZFlag(){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT rule_value FROM rule_values WHERE rule_name = 'World:dfltInstZflag'"), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int32 tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetDfltInstZFlag query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
int32 ZoneDatabase::GetCharInstZOrgID(int32 characterID){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT instZOrgID FROM character_ WHERE id=%i", characterID), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
row = mysql_fetch_row(result);
int32 tmp = atoi(row[0]);
mysql_free_result(result);
return tmp;
}
mysql_free_result(result);
}
else {
cerr << "Error in GetInstType query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
bool ZoneDatabase::InstZoneLoaded(int32 charInstFlagNum){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
if (RunQuery(query, MakeAnyLenString(&query, "SELECT zoneidnumber FROM zone WHERE zoneidnumber=%i", charInstFlagNum), errbuf, &result))
{
safe_delete_array(query);
if (mysql_num_rows(result) == 1) {
return true;
}
else if (mysql_num_rows(result) == 0) {
return false;
}
mysql_free_result(result);
}
else {
cerr << "Error in isInstZoneLoad query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
return 0;
}
//Copies original zones information into a new zone entry replacing the old zoneidnumber with the instflagnum
void ZoneDatabase::LoadInstZone(int32 target_zone_ID, int32 InstFlagNum){
char errbuf[MYSQL_ERRMSG_SIZE];
char *query = 0;
MYSQL_RES *result;
MYSQL_ROW row;
int32 affected_rows = 0;
if (RunQuery(query, MakeAnyLenString(&query, "INSERT INTO zone (short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, zoneidnumber, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer) SELECT short_name, file_name, long_name, safe_x, safe_y, safe_z, graveyard_id, min_level, min_status, %i, timezone, maxclients, weather, note, underworld, minclip, maxclip, fog_minclip, fog_maxclip, fog_blue, fog_red, fog_green, sky, ztype, zone_exp_multiplier, walkspeed, time_type, fog_red1, fog_green1, fog_blue1, fog_minclip1, fog_maxclip1, fog_red2, fog_green2, fog_blue2, fog_minclip2, fog_maxclip2, fog_red3, fog_green3, fog_blue3, fog_minclip3, fog_maxclip3, fog_red4, fog_green4, fog_blue4, fog_minclip4, fog_maxclip4, flag_needed, canbind, cancombat, canlevitate, castoutdoor, insttype, insttimer FROM zone WHERE zoneidnumber =%i", InstFlagNum, target_zone_ID), errbuf, 0, &affected_rows)){
safe_delete_array(query);
}
else {
cerr << "Error in LoadInstZone query '" << query << "' " << errbuf << endl;
safe_delete_array(query);
}
zoning.cpp
Line 123 to line 157
//Prelim Instance zone code
int32 characterID = database.GetCharacterID(zc->char_name);
//Checks if the zone can be instanced, character has a instance flag, and
//that the character is not zoning into an instance that is already loaded
if((database.GetInstType(target_zone_id) == 1)&
(database.GetCharInstFlagNum(characterID) >= database.GetDfltInstZFlag())&
(target_zone_id != database.GetCharInstFlagNum(characterID)))
{
int32 charInstFlagNum = database.GetCharInstFlagNum(characterID);
int32 charInstZOrgID = database.GetCharInstZOrgID(characterID);
// Does character's instance flag match the zone he/she is trying to access
if(charInstZOrgID != target_zone_id)
{
Message(13, "No access flag to target instanced zone.");
SendZoneCancel(zc); // zoning.cpp line 130
return;
}
// Of instance flag matches then...
if(charInstZOrgID == target_zone_id)
{
//If instance zone is not in database then it is copied to database
if(!database.InstZoneLoaded(charInstFlagNum))
{
database.LoadInstZone(target_zone_id, charInstFlagNum);
target_zone_id = charInstFlagNum;
zc->zoneID = charInstFlagNum;
}
else
{
target_zone_id = charInstFlagNum;
zc->zoneID = charInstFlagNum;
}
}
}