PyDict *Character::CharGetInfo() { //TODO: verify that we are a char? if( !LoadContents( m_factory ) ) { codelog(ITEM__ERROR, "%s (%u): Failed to load contents for CharGetInfo", m_itemName.c_str(), m_itemID); return NULL; } PyDict *result = new PyDict; Rsp_CommonGetInfo_Entry entry; if(!Populate(entry)) return NULL; result->SetItem(new PyInt(m_itemID), new PyObject("util.KeyVal", entry.Encode())); //now encode skills... std::vector<InventoryItemRef> skills; //find all the skills contained within ourself. FindByFlag( flagSkill, skills ); FindByFlag( flagSkillInTraining, skills ); //encode an entry for each one. std::vector<InventoryItemRef>::iterator cur, end; cur = skills.begin(); end = skills.end(); for(; cur != end; cur++) { if(!(*cur)->Populate(entry)) { codelog(ITEM__ERROR, "%s (%u): Failed to load skill item %u for CharGetInfo", m_itemName.c_str(), itemID(), (*cur)->itemID()); } else { result->SetItem(new PyInt((*cur)->itemID()), new PyObject("util.KeyVal", entry.Encode())); } } return result; }
PyDict *Ship::ShipGetState() { if( !LoadContents( m_factory ) ) { codelog( ITEM__ERROR, "%s (%u): Failed to load contents for ShipGetInfo", itemName().c_str(), itemID() ); return NULL; } PyDict *result = new PyDict; result->SetItem(new PyInt(itemID()), GetItemStatusRow()); /* std::vector<InventoryItemRef> equipped; std::vector<InventoryItemRef> integrated; FindByFlagRange( flagLowSlot0, flagFixedSlot, equipped ); FindByFlagRange( flagRigSlot0, flagRigSlot7, integrated ); equipped.insert(equipped.end(), integrated.begin(), integrated.end() ); std::vector<InventoryItemRef>::iterator cur, end; cur = equipped.begin(); end = equipped.end(); for(; cur != end; cur++) { result->SetItem(new PyInt((*cur)->itemID()), (*cur)->GetItemStatusRow()); } */ return result; }
void MiningLaser::checkAsteroidDepleted(uint32 remainingOreUnits) { if (remainingOreUnits == 0) { // Asteroid is empty now, so remove it m_targetEntity->Bubble()->Remove(m_targetEntity); m_targetEntity->Item()->Delete(); // Send client asteroid depleted message. PyDict *dict = new PyDict(); dict->SetItem(new PyString("asteroidname"), new PyString("")); PyTuple *tuple = new PyTuple(2); tuple->SetItem(0, new PyInt(MOD_ACTIVATED)); //???? what is this really? tuple->SetItem(1, new PyInt(m_item->typeID())); dict->SetItem(new PyString("modulename"), tuple); PyTuple *error = new PyTuple(2); error->SetItem(0, new PyString("MiningDronesDeactivatedAsteroidEmpty")); error->SetItem(1, dict); m_error = error; } }
PyDict *Ship::ShipGetInfo() { if( !LoadContents( m_factory ) ) { codelog( ITEM__ERROR, "%s (%u): Failed to load contents for ShipGetInfo", itemName().c_str(), itemID() ); return NULL; } PyDict *result = new PyDict; Rsp_CommonGetInfo_Entry entry; //first populate the ship. if( !Populate( entry ) ) return NULL; //print already done. result->SetItem(new PyInt( itemID()), new PyObject("util.KeyVal", entry.Encode())); //now encode contents... std::vector<InventoryItemRef> equipped; std::vector<InventoryItemRef> integrated; //find all the equipped items and rigs FindByFlagRange( flagLowSlot0, flagFixedSlot, equipped ); FindByFlagRange( flagRigSlot0, flagRigSlot7, integrated ); //append them into one list equipped.insert(equipped.end(), integrated.begin(), integrated.end() ); //encode an entry for each one. std::vector<InventoryItemRef>::iterator cur, end; cur = equipped.begin(); end = equipped.end(); for(; cur != end; cur++) { if( !(*cur)->Populate( entry ) ) { codelog( ITEM__ERROR, "%s (%u): Failed to load item %u for ShipGetInfo", itemName().c_str(), itemID(), (*cur)->itemID() ); } else result->SetItem(new PyInt((*cur)->itemID()), new PyObject("util.KeyVal", entry.Encode())); } return result; }
PyDict *Ship::ShipGetState() { if( !LoadContents() ) { codelog( ITEM__ERROR, "%s (%u): Failed to load contents for ShipGetInfo", itemName().c_str(), itemID() ); return NULL; } // Create new dictionary for "shipState": PyDict *result = new PyDict; // Create entry in "shipState" dictionary for Ship itself: result->SetItem(new PyInt(itemID()), GetItemStatusRow()); // Create entries in "shipState" dictionary for ALL modules, rigs, and subsystems present on ship: std::vector<InventoryItemRef> moduleList; m_ModuleManager->GetModuleListOfRefs( &moduleList ); for(int i=0; i<moduleList.size(); i++) result->SetItem(new PyInt(moduleList.at(i)->itemID()), moduleList.at(i)->GetItemStatusRow()); return result; }
PyRep* FactionWarMgrDB::GetFacWarSystems() { sLog.Debug( "FactionWarMgrDB", "Called GetFacWarSystems stub." ); //fill some crap PyDict* result = new PyDict; PyDict* dict; dict = new PyDict; dict->SetItemString( "occupierID", new PyInt( 500002 ) ); dict->SetItemString( "factionID", new PyInt( 500002 ) ); result->SetItem( new PyInt( 30002097 ), dict ); return result; }
PyDict *DBResultToPackedRowDict( DBQueryResult &result, uint32 key_index ) { DBRowDescriptor *header = new DBRowDescriptor( result ); PyDict *res = new PyDict(); DBResultRow row; for( uint32 i = 0; result.GetRow( row ); i++ ) { res->SetItem( DBColumnToPyRep(row, key_index), CreatePackedRow( row, header ) ); PyIncRef( header ); } PyDecRef( header ); return res; }
PyDict *DBResultToIntRowDict(DBQueryResult &result, uint32 key_index, const char *type) { PyDict *res = new PyDict(); //add a line entry for each result row: DBResultRow row; while(result.GetRow(row)) { //this could be more efficient by not building the column list each time, but cloning it instead. PyObject *r = DBRowToRow(row, type); int32 k = row.GetInt(key_index); if(k == 0) continue; //likely a non-integer key res->SetItem(new PyInt(k), r); } return res; }
PyObject *DBResultToIndexRowset(DBQueryResult &result, uint32 key_index) { uint32 cc = result.ColumnCount(); //start building the IndexRowset PyDict *args = new PyDict(); PyObject *res = new PyObject( new PyString( "util.IndexRowset" ), args ); if(cc == 0 || cc < key_index) return res; //list off the column names: PyList *header = new PyList(cc); args->SetItemString("header", header); for(uint32 i = 0; i < cc; i++) header->SetItemString(i, result.ColumnName(i)); //RowClass: args->SetItemString("RowClass", new PyToken("util.Row")); //idName: args->SetItemString("idName", new PyString( result.ColumnName(key_index) )); //items: PyDict *items = new PyDict(); args->SetItemString("items", items); //add a line entry for each result row: DBResultRow row; while(result.GetRow(row)) { PyRep *key = DBColumnToPyRep(row, key_index); PyList *line = new PyList(cc); for(uint32 i = 0; i < cc; i++) line->SetItem(i, DBColumnToPyRep(row, i)); items->SetItem(key, line); } return res; }
PyRep* MailDB::GetLabels(int characterID) const { DBQueryResult res; if (!sDatabase.RunQuery(res, "SELECT bit, name, color, ownerId FROM mailLabel WHERE ownerID = %u", characterID)) return NULL; PyDict* ret = new PyDict(); DBResultRow row; while (res.GetRow(row)) { MailLabel label; label.id = (int)pow((float)2, row.GetInt(0)); label.name = row.GetText(1); label.color = row.GetInt(2); ret->SetItem(new PyInt(label.id), label.Encode()); } return ret; }
PyDict *DBResultToIntIntDict(DBQueryResult &result) { PyDict *res = new PyDict(); //add a line entry for each result row: DBResultRow row; while(result.GetRow(row)) { if(row.IsNull(0)) continue; //no working with NULL keys... int32 k = row.GetInt(0); if(k == 0) continue; //likely a non-integer key int32 v; if(row.IsNull(1)) v = 0; //we can deal with assuming NULL == 0 else v = row.GetInt(1); res->SetItem( new PyInt(k), new PyInt(v) ); } return res; }
PyRep *SearchDB::Query(std::string match, std::vector<int> *searchID) { DBQueryResult res; DBResultRow row; std::string id; uint32 i,size; std::string equal = ""; std::string matchEsc = ""; // Find out if search is exact or not and remove the trailing '*' std::size_t found=match.find('*'); if (found!=std::string::npos) { match.erase (std::remove(match.begin(), match.end(), '*'), match.end()); equal = " RLIKE "; } else { equal = " = "; } // Escape the searchString sDatabase.DoEscapeString(matchEsc, match.c_str()); // The client wants a dict in return // [searchID][Results] PyDict *dict = new PyDict(); size = searchID->size(); for(i=0; i<size; i++){ switch(searchID->at(i)) { case 1: //searchResultAgent = 1 sDatabase.RunQuery(res, "SELECT" " itemID AS agentID" " FROM entity" " WHERE itemName %s '%s' " " AND itemID BETWEEN 2999999 AND 4000000 " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 2: //searchResultCharacter = 2 sDatabase.RunQuery(res, "SELECT" " itemID" " FROM entity" " WHERE itemName %s '%s' " " AND itemId >= %u" " AND ownerID = 1",equal.c_str(), matchEsc.c_str(),EVEMU_MINIMUM_ID ); break; case 3: //searchResultCorporation = 3 sDatabase.RunQuery(res, "SELECT" " corporationID" " FROM corporation" " WHERE corporationName %s '%s' " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 4: //searchResultAlliance = 4 sDatabase.RunQuery(res, "SELECT allianceID" " FROM alliance_ShortNames" " WHERE shortName %s '%s'" " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 5: //searchResultFaction = 5 sDatabase.RunQuery(res, "SELECT factionID" " FROM chrFactions" " WHERE factionName %S '%s' " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 6: //searchResultConstellation = 6 sDatabase.RunQuery(res, "SELECT" " constellationID" " FROM mapConstellations" " WHERE constellationName %s '%s' " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 7: //searchResultSolarSystem = 7 sDatabase.RunQuery(res, "SELECT " " solarSystemID" " FROM mapSolarSystems" " WHERE solarSystemName %s '%s' " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 8: //searchResultRegion = 8 sDatabase.RunQuery(res, "SELECT " " regionID" " FROM mapRegions" " WHERE regionName %s '%s' " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 9: //searchResultStation = 9 sDatabase.RunQuery(res, "SELECT " " stationID" " FROM staStations " " WHERE stationName %s '%s' " " LIMIT 0, 10", equal.c_str(), matchEsc.c_str() ); break; case 10: //searchResultInventoryType = 10 sDatabase.RunQuery(res, "SELECT" " typeID" " FROM entity" " WHERE itemName %s '%s'", equal.c_str(), matchEsc.c_str() ); break; } dict->SetItem(new PyInt(searchID->at(i)),DBResultToIntIntDict(res)); res.Reset(); } return dict; }
//this is a crap load of work... there HAS to be a better way to do this.. PyObject *MarketDB::GetMarketGroups() { DBQueryResult res; //returns cached object marketProxy.GetMarketGroups //marketGroupID, parentGroupID, marketGroupName, description, graphicID, hasTypes, types //this is going to be a real pain... another "nested" query thing... // I really wanna know how they do this crap with their MS SQL server.. // I hope its not as much of a nightmare as it is for us.... //first we need to query out all the types because we need them to // fill in the 'types' subquery for each row of the result std::map< int, std::set<uint32> > types; //maps marketGroupID -> typeID if(!sDatabase.RunQuery(res, "SELECT" " marketGroupID,typeID" " FROM invTypes" " WHERE marketGroupID IS NOT NULL" " ORDER BY marketGroupID")) { codelog(MARKET__ERROR, "Error in query: %s", res.error.c_str()); return NULL; } DBResultRow row; while(res.GetRow(row)) types[row.GetUInt(0)].insert(row.GetUInt(1)); if(!sDatabase.RunQuery(res, "SELECT" " marketGroupID, parentGroupID" " FROM invMarketGroups")) { codelog(MARKET__ERROR, "Error in query: %s", res.error.c_str()); return NULL; } std::map<int, int> parentChild; //maps child -> parent std::map<int, std::set<int> > childParent; //maps parent -> all children. while(res.GetRow(row)) { //figure out the parent ID, mapping NULL to -1 for our map. int marketGroupID = row.GetUInt(0); int parentGroupID = row.IsNull(1) ? -1 : row.GetUInt(1); parentChild[marketGroupID] = parentGroupID; childParent[parentGroupID].insert(marketGroupID); } //now we need to propigate all of the items up the tree (a parent group's items list contains ALL items of its children.) _PropigateItems(types, parentChild, childParent, -1); //now we get to do the other query. if(!sDatabase.RunQuery(res, "SELECT" " marketGroupID, parentGroupID, marketGroupName, description, graphicID, hasTypes" " FROM invMarketGroups")) { codelog(MARKET__ERROR, "Error in query: %s", res.error.c_str()); return NULL; } //doing this the long (non XML) way to avoid the extra copies due to the huge volume of data here. PyDict *args = new PyDict(); PyDict *parentSets = new PyDict(); PyList *header = new PyList(); header->AddItemString("marketGroupID"); header->AddItemString("parentGroupID"); header->AddItemString("marketGroupName"); header->AddItemString("description"); header->AddItemString("graphicID"); header->AddItemString("hasTypes"); header->AddItemString("types"); //this column really contains an entire list. header->AddItemString("dataID"); args->SetItemString("header", header); args->SetItemString("idName", new PyString("parentGroupID")); args->SetItemString("RowClass", new PyToken("util.Row")); args->SetItemString("idName2", new PyNone); args->SetItemString("items", parentSets); //now fill in items. // we have to satisfy this structure... which uses parentGroupID as the // main dict key, each dict entry is then a list of MarketGroup_Entrys // which have that parentGroupID //marketGroupID, parentGroupID, marketGroupName, description, graphicID, hasTypes, types std::map< int, std::set<uint32> >::const_iterator tt; MarketGroup_Entry entry; PyList* list; PyList* parents = new PyList(); while( res.GetRow(row) ) { entry.marketGroupID = row.GetUInt( 0 ); //figure out the parent ID, mapping NULL to -1 for our map. entry.parentGroupID = ( row.IsNull( 1 ) ? -1 : row.GetUInt( 1 ) ); entry.marketGroupName = row.GetText( 2 ); entry.description = row.GetText( 3 ); entry.graphicID = ( row.IsNull( 4 ) ? -1 : row.GetUInt( 4 ) ); entry.hasTypes = row.GetUInt( 5 ); // Insert all types entry.types.clear(); tt = types.find( entry.marketGroupID ); if( tt != types.end() ) entry.types.insert( entry.types.begin(), tt->second.begin(), tt->second.end() ); if(entry.parentGroupID == -1) list = parents; else list = static_cast<PyList*> (parentSets->GetItem(new PyInt( entry.parentGroupID ))); if(list == NULL) list = new PyList(); list->AddItem(entry.Encode()); PySafeIncRef(list); if(entry.parentGroupID != -1) parentSets->SetItem(new PyInt(entry.parentGroupID), list); } parentSets->SetItem(new PyNone, parents); return new PyObject( "util.FilterRowset", args ); }
bool MiningLaser::endCycle(bool continuing) { // Check to see if our target is still in this bubble or has left or been destroyed: if( m_ship->GetOperator()->GetSystemEntity()->Bubble()->GetEntity(m_targetID) == nullptr ) { // Target has left our bubble or been destroyed, deactivate this module: return false; } if (m_ship->GetOperator()->GetSystemEntity()->targets.getTarget(m_targetID, true) == nullptr) { // Target no longer targeted. return false; } // Check range double maxRange = m_item->GetAttribute(AttrMaxRange).get_float(); double targetRange = m_targetEntity->DistanceTo2(m_ship->GetOperator()->GetSystemEntity()); targetRange = std::sqrt(targetRange); targetRange -= m_targetEntity->GetRadius(); if (targetRange > maxRange) { // We must have drifted out of range. // TO-DO: send proper out or range response. SysLog::Error("MiningLaser::Activate()", "ERROR: mining laser target moved out of range!"); return false; } // Retrieve ore from target Asteroid and put into flagCargoHold InventoryItemRef asteroidRef = m_targetEntity->Item(); uint32 remainingOreUnits = asteroidRef->GetAttribute(AttrQuantity).get_int(); double oreUnitVolume = asteroidRef->GetAttribute(AttrVolume).get_float(); // Calculate how many units of ore to pull from the asteroid on this cycle: // Get base mining amount. double oreUnitsToPull = m_item->GetAttribute(AttrMiningAmount).get_float() / oreUnitVolume; // Do we have a crystal? if( m_chargeRef ) { // Yes, apply yield multiplier. if (m_chargeRef->HasAttribute(AttrSpecialisationAsteroidYieldMultiplier)) { // TO-DO: check for correct type of crystal. oreUnitsToPull *= m_chargeRef->GetAttribute(AttrSpecialisationAsteroidYieldMultiplier).get_float(); } // TO-DO: do crystal damage. } // Get percent cycle complete. double cycleTime = getTotalCycleTimeMS(); double percent = 1.0; // Assume full cycle if timer disabled. if(cycleTime != -1) { double usedTime = getElapsedCycleTimeMS(); percent = usedTime / cycleTime; // Limit to range 0.0 - 1.0. percent = std::min(1.0, std::max(0.0, percent)); if(percent == 0.0) { percent = 1.0; } } // Round down to next lowest integer value. oreUnitsToPull = floor(oreUnitsToPull * percent); // Limit to units remaining in asteroid. oreUnitsToPull = std::min(oreUnitsToPull, (double) remainingOreUnits); // Find what cargo hold to use. EVEItemFlags cargoFlag = flagCargoHold; // Check for specialized cargo hold. if (m_ship->HasAttribute(AttrSpecialOreHoldCapacity)) { // We have a specialized ore hold all or goes here. cargoFlag = flagSpecializedOreHold; } // Get cargo hold and remaining capacity. double remainingCargoVolume = m_ship->GetRemainingVolumeByFlag(cargoFlag); // Do we have enough room for the whole stack? if (remainingCargoVolume < (floor((oreUnitsToPull * oreUnitVolume) * 100.0)/100.0)) { // No, Do we have room for at least one unit? if (remainingCargoVolume < oreUnitVolume) { // No, Send cargo full message. PyDict *dict = new PyDict(); PyTuple *tuple = new PyTuple(2); tuple->SetItem(0, new PyInt(MOD_ACTIVATED)); //???? what is this really? tuple->SetItem(1, new PyInt(m_item->typeID())); dict->SetItem(new PyString("modulename"), tuple); PyTuple *error = new PyTuple(2); error->SetItem(0, new PyString("MiningDronesDeactivatedCargoHoldNowFull")); error->SetItem(1, dict); m_error = error; return false; } // Yes, reduce the stack size. oreUnitsToPull = floor(remainingCargoVolume / oreUnitVolume); } // Are we actually pulling anything? if (oreUnitsToPull <= 0.0) { // No, hmmm... thats bad! // TO-DO: send client miner deactivated because hold full message. SysLog::Warning("MiningLaser::DoCycle()", "Somehow MiningLaser could not extract ore from current target asteroid '%s' (id %u)", m_targetEntity->Item()->itemName().c_str(), m_targetEntity->GetID()); checkAsteroidDepleted(remainingOreUnits); return false; } // Check for an existing ore item in the cargo. InventoryItemRef existing = m_ship->GetByTypeFlag(asteroidRef->typeID(), cargoFlag); if (existing.get() != nullptr) { // We have an existing ore sample, add to it. m_ship->AlterCargoQty(existing, oreUnitsToPull); } else { // No existing ore sample, create one. ItemData idata( asteroidRef->typeID(), m_ship->ownerID(), 0, //temp location cargoFlag, oreUnitsToPull ); InventoryItemRef ore = ItemFactory::SpawnItem(idata); if (ore) { m_ship->AddItem(cargoFlag, ore); } else { SysLog::Error("MiningLaser::DoCycle()", "ERROR: Could not create ore stack for '%s' ship (id %u)!", m_ship->itemName().c_str(), m_ship->itemID()); return false; } } // Finally, reduce the amount of ore in the asteroid by how much we took out: remainingOreUnits -= oreUnitsToPull; asteroidRef->SetAttribute(AttrQuantity, remainingOreUnits); // Check to see is ship is full or asteroid depleted. remainingCargoVolume = m_ship->GetRemainingVolumeByFlag(cargoFlag); if ((remainingCargoVolume < oreUnitVolume) || remainingOreUnits == 0) { // Asteroid is empty OR cargo hold is entirely full, either way, DEACTIVATE module immediately! checkAsteroidDepleted(remainingOreUnits); return false; } return true; }