// SectorContentSQL.cpp #include "Net7.h" #ifndef USE_MYSQL_SECTOR #error "BUILD ERROR: USE_MYSQL_SECTOR IS NOW ESSENTIAL" #endif #pragma warning(disable:4786) #include "SectorContentParser.h" #include "XmlParser.h" #include "SectorData.h" #include "mysql/mysqlplus.h" #include "ObjectClass.h" #include "ObjectManager.h" #include "ServerManager.h" #include "ResourceClass.h" SectorContentParser::SectorContentParser() { m_SectorList.clear(); m_SystemList.clear(); g_SectorObjects.clear(); } SectorContentParser::~SectorContentParser() { // TODO: destroy everything } bool SectorContentParser::LoadSectorContent() { ParseSectorContent(NULL); return true; } bool SectorContentParser::ParseSectorContent(char *data) { long sector_count = 0; SectorData * current_sector = 0; Object *current_object = 0; char QueryString[1024]; if(!g_MySQL_User || !g_MySQL_Pass) { printf("You need to set a mysql user/pass in the net7.cfg\n"); return 0; } sql_connection_c connection( "net7", g_MySQL_Host, g_MySQL_User, g_MySQL_Pass); sql_query_c SectorTb( &connection ); sql_result_c result; sql_result_c object_result; sql_result_c *Sector_result = &result; LoadSystems(&connection); LoadAsteroidContentSelection(&connection); sprintf(QueryString, "SELECT * FROM `sectors`"); if ( !SectorTb.execute( QueryString ) ) { printf( "MySQL Login error/Database error: (User: %s Pass: %s)\n", g_MySQL_User, g_MySQL_Pass ); return 0; } SectorTb.store(Sector_result); if (!Sector_result->n_rows() || !Sector_result->n_fields()) { printf("Error loading rows/fields\n"); return 0; } printf("Loading Sectors from SQL (%d)", (int)Sector_result->n_rows()); sql_row_c SectorSQLData; bool new_sector; int i = 30; for(int x=0;xn_rows();x++) { Sector_result->fetch_row(&SectorSQLData); // Read in first row int sector_id = (int) SectorSQLData["sector_id"]; new_sector = false; //printf("Loading Sector Data for (%d) %s\n", (int) SectorSQLData["sector_id"], (char*) SectorSQLData["name"] ); printf("."); #ifdef DEV_QUICK_START if (i == 0) break; i--; #endif current_sector = m_SectorList[sector_id]; if (current_sector == 0) { current_sector = new SectorData; if (current_sector) { memset(current_sector, 0, sizeof(SectorData)); //instantiate a new ObjectManager current_sector->obj_manager = new ObjectManager; new_sector = true; } else { LogMessage("Unable to Allocate sector for %s\n", SectorSQLData["name"]); return false; } } m_SectorList[sector_id] = current_sector; current_sector->m_xmax = current_sector->m_xmin = 0.0f; current_sector->m_ymax = current_sector->m_ymin = 0.0f; current_sector->system_id = (int)SectorSQLData["system_id"]; current_sector->name = g_StringMgr->GetStr(SectorSQLData["name"]); current_sector->sector_id = sector_id; current_sector->num_objects = 0; AddSystemInfo(current_sector); current_sector->server_params.ZBandMin = (float)SectorSQLData["z_min"]; current_sector->server_params.ZBandMax = (float)SectorSQLData["z_max"]; current_sector->server_params.XMin = (float)SectorSQLData["x_min"]; current_sector->server_params.YMin = (float)SectorSQLData["y_min"]; current_sector->server_params.XMax = (float)SectorSQLData["x_max"]; current_sector->server_params.YMax = (float)SectorSQLData["y_max"]; current_sector->server_params.FogNear = (float)SectorSQLData["fog_near"]; current_sector->server_params.FogFar = (float)SectorSQLData["fog_far"]; current_sector->server_params.DebrisMode = (long)SectorSQLData["debris_mode"]; current_sector->server_params.LightBackdrop = (char)SectorSQLData["light_backdrop"]; current_sector->server_params.FogBackdrop = (int)SectorSQLData["fog_backdrop"]; current_sector->server_params.SwapBackdrop = (int)SectorSQLData["swap_backdrop"]; current_sector->server_params.BackdropFogNear = (float)SectorSQLData["backdrop_fog_near"]; current_sector->server_params.BackdropFogFar = (float)SectorSQLData["backdrop_fog_far"]; current_sector->server_params.MaxTilt = (float)SectorSQLData["max_tilt"]; current_sector->server_params.AutoLevel = (int)SectorSQLData["auto_level"]; current_sector->server_params.ImpulseRate = (float)SectorSQLData["impulse_rate"]; current_sector->server_params.DecayVelocity = (float)SectorSQLData["decay_velocity"]; current_sector->server_params.DecaySpin = (float)SectorSQLData["decay_spin"]; current_sector->server_params.BackdropBaseAsset = (short)SectorSQLData["backdrop_asset"]; strcpy(current_sector->greetings, SectorSQLData["greetings"]); current_sector->sector_type = (int)SectorSQLData["sector_type"]; if (current_sector->server_params.ZBandMax > 10000.0f) current_sector->server_params.ZBandMax = 10000.0f; if (current_sector->server_params.ZBandMin < -10000.0f) current_sector->server_params.ZBandMin = -10000.0f; if (new_sector) { g_ServerMgr->AddSector(current_sector->sector_id, current_sector->name, current_sector->system_name, 0); } //printf("XMax: %f YMax: %f ZMax: %f\n", current_sector->server_params.XMax, current_sector->server_params.YMax, current_sector->server_params.ZBandMax ); // Game Objects sql_query_c GameObjects( &connection ); sql_result_c *Object_result = &object_result; //TODO: just change the sectorID sprintf(QueryString, "SELECT * FROM `sector_objects` left join `sector_nav_points`" " on sector_objects.sector_object_id = sector_nav_points.sector_object_id" " left join `sector_objects_harvestable`" " on sector_objects.sector_object_id = sector_objects_harvestable.resource_id" " left join `sector_objects_planets`" " on sector_objects.sector_object_id = sector_objects_planets.planet_id" " left join `sector_objects_starbases`" " on sector_objects.sector_object_id = sector_objects_starbases.starbase_id" " left join `sector_objects_stargates`" " on sector_objects.sector_object_id = sector_objects_stargates.stargate_id" " left join `sector_objects_mob`" " on sector_objects.sector_object_id = sector_objects_mob.mob_id" " where sector_objects.sector_id='%ld'", current_sector->sector_id); if ( !GameObjects.execute( QueryString ) ) { printf( "MySQL Error (GameObjects)\n" ); return 0; } GameObjects.store(Object_result); sql_row_c ObjectData; for(int x=0;xn_rows();x++) { Object_result->fetch_row(&ObjectData); // Read in row long object_uid = (long)ObjectData["sector_object_id"]; char type = (char)ObjectData["type"]; bool new_object = false; current_object = g_SectorObjects[object_uid]; //create new object if needed if (current_object == 0) { new_object = true; switch (type) { case 11: current_object = current_sector->obj_manager->AddNewObject(OT_STARGATE); current_object->SetPositionType(POSITION_CONSTANT); break; case 12: current_object = current_sector->obj_manager->AddNewObject(OT_STATION); current_object->SetPositionType(POSITION_CONSTANT); break; case 3: current_object = current_sector->obj_manager->AddNewObject(OT_PLANET); current_object->SetPositionType(POSITION_PLANET); break; case 37: current_object = current_sector->obj_manager->AddNewObject(OT_DECO); current_object->SetPositionType(POSITION_CONSTANT); break; case 38: //see if this is a field or not if ((float)ObjectData["max_field_radius"] > 0.0f && (long) ObjectData["res_count"] > 0) { current_object = current_sector->obj_manager->AddNewObject(OT_FIELD, true); } else { current_object = current_sector->obj_manager->AddNewObject(OT_RESOURCE, true); } break; case 0: current_object = current_sector->obj_manager->AddNewObject(OT_MOBSPAWN); break; default: LogMessage("WARNING: Unexpected Object type %d, in sector [%d] assuming type of Deco.\n",type, current_sector->sector_id); current_object = current_sector->obj_manager->AddNewObject(OT_DECO); //assume this is a deco for now }; } else { if (current_object->CreateType() != type) { //LogMessage("Data Re-Load error - object type of %s has changed from %d to %d\n", current_object->Name(), current_object->ObjectType(), type); continue; } } if (!current_object) { printf("FATAL ERROR: ParseSectorContent unable to allocate memory for Object\n"); m_Success = false; return m_Success; } //generic properties current_object->SetCreateType(type); current_object->SetPosition((float)ObjectData["position_x"], (float)ObjectData["position_y"], (float)ObjectData["position_z"]); current_object->SetOrientation((float)ObjectData["orientation_u"], (float)ObjectData["orientation_v"], (float)ObjectData["orientation_w"], (float)ObjectData["orientation_z"]); current_object->SetName(ObjectData["name"]); current_object->SetNavType((long)ObjectData["nav_type"]); current_object->SetDatabaseUID(object_uid); g_SectorObjects[object_uid] = current_object; //NB g_SectorObjects is a std::map template //add this object to the global sector object list //we can reference this object by its database 'sector_id' //specific properties switch (current_object->ObjectType()) { case OT_FIELD: current_object->SetCreateType(37); //we want to display field centres to devs if (new_object) { current_object->SetLevel(ObjectData["level"]); current_object->SetFieldCount((int)ObjectData["res_count"]); current_object->SetFieldRadius((float)ObjectData["max_field_radius"]); current_object->SetFieldType((int)ObjectData["field"]); AddResourceTypes(current_object, (int)ObjectData["resource_id"], &connection); AddFieldOreIDs(current_object, (int)ObjectData["resource_id"], &connection); if (current_object->GetSectorManager()) { AddMOBTypes(current_object, (int)ObjectData["resource_id"], &connection); } current_object->PopulateField(false); } else if (current_object->FieldCount() == (int)ObjectData["res_count"]) //we can update the field spawn if count remains the same { current_object->SetLevel(ObjectData["level"]); current_object->SetFieldRadius((float)ObjectData["max_field_radius"]); current_object->SetFieldType((int)ObjectData["field"]); AddResourceTypes(current_object, (int)ObjectData["resource_id"], &connection); AddFieldOreIDs(current_object, (int)ObjectData["resource_id"], &connection); if (current_object->GetSectorManager()) { AddMOBTypes(current_object, (int)ObjectData["resource_id"], &connection); } current_object->PopulateField(false, true); } break; case OT_MOBSPAWN: if (new_object) { AddMOBTypes(current_object, (int)ObjectData["mob_id"], &connection); current_object->SetSpawnCount(ObjectData["mob_count"]); current_object->SetSpawnRadius(ObjectData["mob_spawn_radius"]); current_object->PopulateSpawn(false); } break; case OT_PLANET: current_object->SetTilt((float)ObjectData["tilt_angle"]); current_object->SetSpin((float)ObjectData["rotate_rate"]); //drop through case OT_DECO: if (current_object->NavType() > 0 && current_object->ObjectType() != OT_PLANET) { current_object->SetObjectType(OT_NAV); } //drop through default: current_object->SetScale(ObjectData["scale"]); current_object->SetHSV((float)ObjectData["h"], (float)ObjectData["s"], (float)ObjectData["v"]); current_object->SetLevel(ObjectData["level"]); //set level after HSV so resources get the correct colour current_object->SetSignature((float)ObjectData["signature"]); current_object->SetRadarRange((float)ObjectData["radar_range"]); current_object->SetBasset((short)ObjectData["base_asset_id"]); current_object->SetDestination((int)ObjectData["gate_to"]); if ((int)ObjectData["appears_in_radar"] > 0) //does object appear in radar? { current_object->SetAppearsInRadar(); } if (current_object->Signature() > 0.0f) //does object have navigation info (it does if there's a signature). { current_object->SetNavInfo(); } if ((int)ObjectData["is_huge"] > 0) { current_object->SetHuge(); } break; } current_sector->num_objects++; } LoadSectorOreAvailability(current_sector, &connection); } ///////////////////////// // PARSING IS COMPLETE ///////////////////////// printf("\n"); return (m_Success); } SectorData * SectorContentParser::GetSectorData(long sector_id) { return (m_SectorList[sector_id]); } SectorData * SectorContentParser::GetSectorData(char *sector_name) { long sector_id = 0; for( SectorDataMap::iterator sector = m_SectorList.begin(); sector != m_SectorList.end(); ++sector) { SectorData *this_sector = sector->second; if (this_sector && 0 == _stricmp(sector_name, this_sector->name)) { sector_id = this_sector->sector_id; } } return (m_SectorList[sector_id]); } char * SectorContentParser::_GetSectorName(long sector_id) { SectorData * data = m_SectorList[sector_id]; if (data) { return data->name; } else { return (0); } } char * SectorContentParser::_GetSystemName(long sector_id) { SectorData * data = m_SectorList[sector_id]; if (data) { return data->system_name; } else { return (0); } } void SectorContentParser::UpdateBoundaries(SectorData *sector, float *position) //find the boundaries for this sector { if (position[0] > sector->m_xmax) { sector->m_xmax = position[0]; } else if (position[0] < sector->m_xmin) { sector->m_xmin = position[0]; } if (position[1] > sector->m_ymax) { sector->m_ymax = position[1]; } else if (position[1] < sector->m_ymin) { sector->m_ymin = position[1]; } } void SectorContentParser::LoadSystems(sql_connection_c *connection) { sql_query_c Systems( connection ); sql_result_c result; char QueryString[128]; sprintf(QueryString, "SELECT * FROM `systems`"); if ( !Systems.execute( QueryString ) ) { printf( "MySQL Error (Reading systems database)\n"); return; } Systems.store(&result); SystemData *this_system = (0); sql_row_c system_entry; for(int x=0;xsystem_name = g_StringMgr->GetStr(system_entry["name"]); m_SystemList[system_id] = this_system; } } void SectorContentParser::AddSystemInfo(SectorData *sector) { SystemData *system = m_SystemList[sector->system_id]; if (system) { sector->system_name = system->system_name; } else { sector->system_name = sector->name; //system name not found, use the sector name } } void SectorContentParser::AddResourceTypes(Object *obj, long resource_id, sql_connection_c *connection) { sql_query_c Resource_types( connection ); sql_result_c result; char QueryString[128]; sprintf(QueryString, "SELECT * FROM `sector_objects_harvestable_restypes` WHERE `group_id` = '%ld'", resource_id); if ( !Resource_types.execute( QueryString ) ) { printf( "MySQL Error (Reading Resouce types for resource_id %ld)\n", resource_id ); return; } Resource_types.store(&result); obj->ResetResource(); sql_row_c resource; for(int x=0;x 0) { obj->AddResource(resource_basset); } } } void SectorContentParser::AddMOBTypes(Object *obj, long object_id, sql_connection_c *connection) { sql_query_c Mob_types( connection ); sql_result_c result; char QueryString[128]; sprintf(QueryString, "SELECT * FROM `mob_spawn_group` WHERE `spawn_group_id` = '%ld'", object_id); if ( !Mob_types.execute( QueryString ) ) { printf( "MySQL Error (Reading mob_spawn_group types for spawn_group_id %ld)\n", object_id ); return; } Mob_types.store(&result); sql_row_c mob_entry; for(int x=0;x 0) { obj->AddMOBID(mob_id); } } } void SectorContentParser::AddFieldOreIDs(Object *obj, long object_id, sql_connection_c *connection) { sql_query_c Ore_types( connection ); sql_result_c result; char QueryString[128]; //first blank out all existing entries in list obj->BlankItemIDs(); sprintf(QueryString, "SELECT * FROM `sector_objects_harvestable_oretypes` WHERE `resource_id` = '%ld'", object_id); if ( !Ore_types.execute( QueryString ) ) { printf( "MySQL Error (Reading sector_objects_harvestable_oretypes types for resource_id %ld)\n", object_id ); return; } Ore_types.store(&result); sql_row_c ore_entry; for(int x=0;xAddItemID(item_id, frequency); } } void SectorContentParser::LoadSectorOreAvailability(SectorData *sector, sql_connection_c *connection) { sql_query_c Ore_types( connection ); sql_result_c result; char QueryString[128]; u32 ore_index = 0; //first blank out all existing entries in list for( SectorOreList::iterator ore_itr = sector->OreList.begin(); ore_itr != sector->OreList.end(); ++ore_itr) { (*ore_itr)->frequency = 0.0f; (*ore_itr)->item_id = 0; } sector->ore_list_size = 0; sprintf(QueryString, "SELECT * FROM `base_ore_list` WHERE `sector_id` = '%ld'", sector->sector_id); if ( !Ore_types.execute( QueryString ) ) { printf( "MySQL Error (Reading base_ore_list types for sector %ld)\n", sector->sector_id ); return; } Ore_types.store(&result); sql_row_c ore_entry; for(int x=0;xOreList.size()) { ore_node = sector->OreList[ore_index]; } else { ore_node = new OreNode; sector->OreList.push_back(ore_node); } ore_node->frequency = frequency; ore_node->item_id = item_id; sector->ore_list_size++; ore_index++; } } long SectorContentParser::GetNextSectorID(long sector_id) { long next_sector_id = 0; bool found_next = false; if (sector_id == 0) { next_sector_id = (m_SectorList.begin())->second->sector_id; } else { for( SectorDataMap::iterator sector = m_SectorList.begin(); sector != m_SectorList.end(); ++sector) { SectorData *this_sector = sector->second; if (this_sector) { if (found_next == true) { next_sector_id = this_sector->sector_id; break; } if (this_sector->sector_id == sector_id) { found_next = true; } } } } return (next_sector_id); } void SectorContentParser::LoadAsteroidContentSelection(sql_connection_c *connection) { sql_query_c Ore_types( connection ); sql_result_c result; char QueryString[128]; u32 ore_index = 0; AsteroidSubcatVec *sub_cat_vec; for (int i = 1; i <= RESOURCE_TYPE_SIZE; i++) { sprintf(QueryString, "SELECT * FROM `asteroid_content_selection` WHERE `asteroid_type` = '%d'", i); if ( !Ore_types.execute( QueryString ) ) { printf( "MySQL Error (Reading asteroid_content_selection types for asteroid_type %d)\n", i ); return; } Ore_types.store(&result); //blank any current data here if (m_AsteroidContentList[i]) { m_AsteroidContentList[i]->clear(); sub_cat_vec = m_AsteroidContentList[i]; } else { sub_cat_vec = new AsteroidSubcatVec; m_AsteroidContentList[i] = sub_cat_vec; } sql_row_c resource; for(int x=0;xpush_back(subcat); //let STL handle allocation, this data should be fairly static anyway } } } AsteroidSubcatVec* SectorContentParser::GetAsteroidContentSelection(long asteroid_type) { AsteroidSubcatVec *sub_cat_vec = m_AsteroidContentList[asteroid_type]; return sub_cat_vec; }