void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, parameterlist& params) { User* who = ServerInstance->FindUUID(prefix); std::string direction; if (!who) { TreeServer* ServerSource = Utils->FindServer(prefix); if (prefix.empty()) ServerSource = MyRoot; if (ServerSource) { who = ServerSource->ServerUser; } else { /* It is important that we don't close the link here, unknown prefix can occur * due to various race conditions such as the KILL message for a user somehow * crossing the users QUIT further upstream from the server. Thanks jilles! */ if ((prefix.length() == UIDGenerator::UUID_LENGTH) && (isdigit(prefix[0])) && ((command == "FMODE") || (command == "MODE") || (command == "KICK") || (command == "TOPIC") || (command == "KILL") || (command == "ADDLINE") || (command == "DELLINE"))) { /* Special case, we cannot drop these commands as they've been committed already on a * part of the network by the time we receive them, so in this scenario pretend the * command came from a server to avoid desync. */ who = ServerInstance->FindUUID(prefix.substr(0, 3)); if (!who) who = this->MyRoot->ServerUser; } else { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Command '%s' from unknown prefix '%s'! Dropping entire command.", command.c_str(), prefix.c_str()); return; } } } // Make sure prefix is still good direction = who->server; prefix = who->uuid; /* * Check for fake direction here, and drop any instances that are found. * What is fake direction? Imagine the following server setup: * 0AA <-> 0AB <-> 0AC * Fake direction would be 0AC sending a message to 0AB claiming to be from * 0AA, or something similar. Basically, a message taking a path that *cannot* * be correct. * * When would this be seen? * Well, hopefully never. It could be caused by race conditions, bugs, or * "miscreant" servers, though, so let's check anyway. -- w * * We also check here for totally invalid prefixes (prefixes that are neither * a valid SID or a valid UUID, so that invalid UUID or SID never makes it * to the higher level functions. -- B */ TreeServer* route_back_again = Utils->BestRouteTo(direction); if ((!route_back_again) || (route_back_again->GetSocket() != this)) { if (route_back_again) ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Protocol violation: Fake direction '%s' from connection '%s'", prefix.c_str(),linkID.c_str()); return; } // Translate commands coming from servers using an older protocol if (proto_version < ProtocolVersion) { if (!PreProcessOldProtocolMessage(who, command, params)) return; } ServerCommand* scmd = Utils->Creator->CmdManager.GetHandler(command); CommandBase* cmdbase = scmd; Command* cmd; if (!scmd) { // Not a special server-to-server command cmd = ServerInstance->Parser->GetHandler(command); if (!cmd) { irc::stringjoiner pmlist(params); ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Unrecognised S2S command :%s %s %s", who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); SendError("Unrecognised command '" + command + "' -- possibly loaded mismatched modules"); return; } cmdbase = cmd; } if (params.size() < cmdbase->min_params) { irc::stringjoiner pmlist(params); ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Insufficient parameters for S2S command :%s %s %s", who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); SendError("Insufficient parameters for command '" + command + "'"); return; } if ((!params.empty()) && (params.back().empty()) && (!cmdbase->allow_empty_last_param)) { // the last param is empty and the command handler doesn't allow that, check if there will be enough params if we drop the last if (params.size()-1 < cmdbase->min_params) return; params.pop_back(); } CmdResult res; if (scmd) res = scmd->Handle(who, params); else res = cmd->Handle(params, who); if (res == CMD_INVALID) { irc::stringjoiner pmlist(params); ServerInstance->Logs->Log(MODNAME, LOG_SPARSE, "Error handling S2S command :%s %s %s", who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str()); SendError("Error handling '" + command + "' -- possibly loaded mismatched modules"); } else if (res == CMD_SUCCESS) Utils->RouteCommand(route_back_again, cmdbase, params, who); }
void CTransportCAI::UnloadLandFlood(Command& c) { //land, then release all units at once CTransportUnit* transport = static_cast<CTransportUnit*>(owner); if (inCommand) { if (!owner->script->IsBusy()) { FinishCommand(); } } else { const std::list<CTransportUnit::TransportedUnit>& transList = transport->GetTransportedUnits(); if (transList.empty()) { FinishCommand(); return; } //check units are all carried CUnit* unit = NULL; if (c.params.size() < 4) { unit = transList.front().unit; } else { const int unitID = (int)c.params[3]; std::list<CTransportUnit::TransportedUnit>::const_iterator it; for (it = transList.begin(); it != transList.end(); ++it) { CUnit* carried = it->unit; if (unitID == carried->id) { unit = carried; break; } } if (unit == NULL) { FinishCommand(); return; } } // move to position float3 pos = c.GetPos(0); if (isFirstIteration) { if (goalPos.SqDistance2D(pos) > 400) { SetGoal(startingDropPos, owner->pos); } } if (startingDropPos.SqDistance2D(owner->pos) < Square(owner->unitDef->loadingRadius * 0.9f)) { // create aircraft movetype instance CHoverAirMoveType* am = dynamic_cast<CHoverAirMoveType*>(owner->moveType); if (am != NULL) { // lower to ground startingDropPos.y = ground->GetHeightAboveWater(startingDropPos.x,startingDropPos.z); const float3 wantedPos = startingDropPos + UpVector * unit->model->height; SetGoal(wantedPos, owner->pos); am->SetWantedAltitude(1); am->maxDrift = 1; am->dontLand = false; // when on our way down start animations for unloading gear if (isFirstIteration) { owner->script->StartUnload(); } isFirstIteration = false; // once at ground if (owner->pos.y - ground->GetHeightAboveWater(wantedPos.x,wantedPos.z) < 8) { // nail it to the ground before it tries jumping up, only to land again... am->SetState(am->AIRCRAFT_LANDED); // call this so that other animations such as opening doors may be started owner->script->TransportDrop(transList.front().unit, pos); transport->DetachUnitFromAir(unit,pos); FinishCommand(); if (transport->GetTransportedUnits().empty()) { am->dontLand = false; owner->script->EndTransport(); am->UpdateLanded(); } } } else { // land transports inCommand = true; isFirstIteration = false; StopMove(); owner->script->TransportDrop(transList.front().unit, pos); transport->DetachUnitFromAir(unit, pos); FinishCommand(); if (transport->GetTransportedUnits().empty()) { owner->script->EndTransport(); } } } } }
void CSelectedUnits::GiveCommand(Command c, bool fromUser) { GML_RECMUTEX_LOCK(grpsel); // GiveCommand // logOutput.Print("Command given %i",c.id); if ((gu->spectating && !gs->godMode) || selectedUnits.empty()) { return; } const int& cmd_id = c.GetID(); if (fromUser) { // add some statistics playerHandler->Player(gu->myPlayerNum)->currentStats.numCommands++; if (selectedGroup != -1) { playerHandler->Player(gu->myPlayerNum)->currentStats.unitCommands += grouphandlers[gu->myTeam]->groups[selectedGroup]->units.size(); } else { playerHandler->Player(gu->myPlayerNum)->currentStats.unitCommands += selectedUnits.size(); } } if (cmd_id == CMD_GROUPCLEAR) { for (CUnitSet::iterator ui = selectedUnits.begin(); ui != selectedUnits.end(); ++ui) { if ((*ui)->group) { (*ui)->SetGroup(0); possibleCommandsChanged = true; } } return; } else if (cmd_id == CMD_GROUPSELECT) { SelectGroup((*selectedUnits.begin())->group->id); return; } else if (cmd_id == CMD_GROUPADD) { CGroup* group = NULL; for (CUnitSet::iterator ui = selectedUnits.begin(); ui != selectedUnits.end(); ++ui) { if ((*ui)->group) { group = (*ui)->group; possibleCommandsChanged = true; break; } } if (group) { for (CUnitSet::iterator ui = selectedUnits.begin(); ui != selectedUnits.end(); ++ui) { if (!(*ui)->group) { (*ui)->SetGroup(group); } } SelectGroup(group->id); } return; } else if (cmd_id == CMD_TIMEWAIT) { waitCommandsAI.AddTimeWait(c); return; } else if (cmd_id == CMD_DEATHWAIT) { waitCommandsAI.AddDeathWait(c); return; } else if (cmd_id == CMD_SQUADWAIT) { waitCommandsAI.AddSquadWait(c); return; } else if (cmd_id == CMD_GATHERWAIT) { waitCommandsAI.AddGatherWait(c); return; } SendCommand(c); #if (PLAY_SOUNDS == 1) if (!selectedUnits.empty()) { CUnitSet::const_iterator ui = selectedUnits.begin(); const int soundIdx = (*ui)->unitDef->sounds.ok.getRandomIdx(); if (soundIdx >= 0) { Channels::UnitReply.PlaySample( (*ui)->unitDef->sounds.ok.getID(soundIdx), (*ui), (*ui)->unitDef->sounds.ok.getVolume(soundIdx)); } } #endif }
void CCommandAI::GiveAllowedCommand(const Command& c, bool fromSynced) { if (ExecuteStateCommand(c)) return; switch (c.GetID()) { case CMD_SELFD: { if (owner->unitDef->canSelfD) { if (!(c.options & SHIFT_KEY) || commandQue.empty()) { if (owner->selfDCountdown != 0) { owner->selfDCountdown = 0; } else { owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1; } } else if (commandQue.back().GetID() == CMD_SELFD) { commandQue.pop_back(); } else { commandQue.push_back(c); } } return; } case CMD_SET_WANTED_MAX_SPEED: { if (CanSetMaxSpeed() && (commandQue.empty() || (commandQue.back().GetID() != CMD_SET_WANTED_MAX_SPEED))) { // bail early, do not check for overlaps or queue cancelling commandQue.push_back(c); if (commandQue.size()==1 && !owner->beingBuilt) { SlowUpdate(); } } return; } case CMD_WAIT: { GiveWaitCommand(c); return; } case CMD_INSERT: { ExecuteInsert(c, fromSynced); return; } case CMD_REMOVE: { ExecuteRemove(c); return; } } // flush the queue for immediate commands // NOTE: CMD_STOP can be a queued order (!) if (!(c.options & SHIFT_KEY)) { waitCommandsAI.ClearUnitQueue(owner, commandQue); ClearTargetLock((commandQue.empty())? Command(CMD_STOP): commandQue.front()); ClearCommandDependencies(); SetOrderTarget(NULL); // if c is an attack command, the actual order-target // gets set via ExecuteAttack (called from SlowUpdate // at the end of this function) commandQue.clear(); assert(commandQue.empty()); inCommand = false; } AddCommandDependency(c); if (c.GetID() == CMD_PATROL) { CCommandQueue::iterator ci = commandQue.begin(); for (; ci != commandQue.end() && ci->GetID() != CMD_PATROL; ++ci) { // just increment } if (ci == commandQue.end()) { if (commandQue.empty()) { Command c2(CMD_PATROL, c.options, owner->pos); commandQue.push_back(c2); } else { do { --ci; if (ci->params.size() >= 3) { Command c2(CMD_PATROL, c.options); c2.params = ci->params; commandQue.push_back(c2); break; } else if (ci == commandQue.begin()) { Command c2(CMD_PATROL, c.options, owner->pos); commandQue.push_back(c2); break; } } while (ci != commandQue.begin()); } } } // cancel duplicated commands bool first; if (CancelCommands(c, commandQue, first) > 0) { if (first) { Command stopCommand(CMD_STOP); commandQue.push_front(stopCommand); SlowUpdate(); } return; } // do not allow overlapping commands if (!GetOverlapQueued(c).empty()) { return; } if (c.GetID() == CMD_ATTACK) { // avoid weaponless units moving to 0 distance when given attack order if (owner->weapons.empty() && (!owner->unitDef->canKamikaze)) { Command c2(CMD_STOP); commandQue.push_back(c2); return; } } commandQue.push_back(c); if (commandQue.size() == 1 && !owner->beingBuilt && !owner->IsStunned()) { SlowUpdate(); } }
void CTransportCAI::ExecuteLoadUnits(Command& c) { CTransportUnit* transport = reinterpret_cast<CTransportUnit*>(owner); if (c.params.size() == 1) { // load single unit CUnit* unit = unitHandler->GetUnit(c.params[0]); if (!unit) { FinishCommand(); return; } if (c.options & INTERNAL_ORDER) { if (unit->commandAI->commandQue.empty()) { if (!LoadStillValid(unit)) { FinishCommand(); return; } } else { Command& currentUnitCommand = unit->commandAI->commandQue[0]; if ((currentUnitCommand.GetID() == CMD_LOAD_ONTO) && (currentUnitCommand.params.size() == 1) && (int(currentUnitCommand.params[0]) == owner->id)) { if ((unit->moveType->progressState == AMoveType::Failed) && (owner->moveType->progressState == AMoveType::Failed)) { unit->commandAI->FinishCommand(); FinishCommand(); return; } } else if (!LoadStillValid(unit)) { FinishCommand(); return; } } } if (inCommand) { if (!owner->script->IsBusy()) { FinishCommand(); } return; } if (unit && CanTransport(unit) && UpdateTargetLostTimer(int(c.params[0]))) { SetTransportee(unit); const float sqDist = unit->pos.SqDistance2D(owner->pos); const bool inLoadingRadius = (sqDist <= Square(owner->unitDef->loadingRadius)); CHoverAirMoveType* am = dynamic_cast<CHoverAirMoveType*>(owner->moveType); // subtracting 1 square to account for pathfinder/groundmovetype inaccuracy if (goalPos.SqDistance2D(unit->pos) > Square(owner->unitDef->loadingRadius - SQUARE_SIZE) || (!inLoadingRadius && (!owner->isMoving || (am && am->aircraftState != AAirMoveType::AIRCRAFT_FLYING)))) { SetGoal(unit->pos, owner->pos, std::min(64.0f, owner->unitDef->loadingRadius)); } if (inLoadingRadius) { if (am) { // handle air transports differently float3 wantedPos = unit->pos; wantedPos.y = static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeight(wantedPos, unit); SetGoal(wantedPos, owner->pos); am->loadingUnits = true; am->ForceHeading(static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeading(unit)); am->SetWantedAltitude(wantedPos.y - ground->GetHeightAboveWater(wantedPos.x, wantedPos.z)); am->maxDrift = 1; if ((owner->pos.SqDistance(wantedPos) < Square(AIRTRANSPORT_DOCKING_RADIUS)) && (abs(owner->heading-unit->heading) < AIRTRANSPORT_DOCKING_ANGLE) && (owner->updir.dot(UpVector) > 0.995f)) { am->loadingUnits = false; am->dontLand = true; owner->script->BeginTransport(unit); SetTransportee(NULL); transport->AttachUnit(unit, owner->script->QueryTransport(unit)); am->SetWantedAltitude(0); FinishCommand(); return; } } else { inCommand = true; StopMove(); owner->script->TransportPickup(unit); } } else if (owner->moveType->progressState == AMoveType::Failed && sqDist < (200 * 200)) { // if we're pretty close already but CGroundMoveType fails because it considers // the goal clogged (with the future passenger...), just try to move to the // point halfway between the transport and the passenger. SetGoal((unit->pos + owner->pos) * 0.5f, owner->pos); } } else { FinishCommand(); } } else if (c.params.size() == 4) { // area-load if (lastCall == gs->frameNum) { // avoid infinite loops return; } lastCall = gs->frameNum; const float3 pos = c.GetPos(0); const float radius = c.params[3]; CUnit* unit = FindUnitToTransport(pos, radius); if (unit && CanTransport(unit)) { Command c2(CMD_LOAD_UNITS, c.options|INTERNAL_ORDER, unit->id); commandQue.push_front(c2); inCommand = false; SlowUpdate(); return; } else { FinishCommand(); return; } } isFirstIteration = true; startingDropPos = float3(-1.0f, -1.0f, -1.0f); }
void CoasterChannel::checkHeartbeat() { // TODO: this can be sent after shutdown Command* cmd = new HeartBeatCommand(); cmd->send(this, &heartbeatCB); }
bool CCommandAI::ExecuteStateCommand(const Command& c) { switch (c.GetID()) { case CMD_FIRE_STATE: { owner->fireState = (int)c.params[0]; SetCommandDescParam0(c); selectedUnitsHandler.PossibleCommandChange(owner); return true; } case CMD_MOVE_STATE: { owner->moveState = (int)c.params[0]; SetCommandDescParam0(c); selectedUnitsHandler.PossibleCommandChange(owner); return true; } case CMD_REPEAT: { if (c.params[0] == 1) { repeatOrders = true; } else if(c.params[0] == 0) { repeatOrders = false; } else { // cause some code parts need it to be either 0 or 1, // we can not accept any other values as valid return false; } SetCommandDescParam0(c); selectedUnitsHandler.PossibleCommandChange(owner); return true; } case CMD_TRAJECTORY: { owner->useHighTrajectory = !!c.params[0]; SetCommandDescParam0(c); selectedUnitsHandler.PossibleCommandChange(owner); return true; } case CMD_ONOFF: { if (c.params[0] == 1) { owner->Activate(); } else if (c.params[0] == 0) { owner->Deactivate(); } else { // cause some code parts need it to be either 0 or 1, // we can not accept any other values as valid return false; } SetCommandDescParam0(c); selectedUnitsHandler.PossibleCommandChange(owner); return true; } case CMD_CLOAK: { if (c.params[0] == 1) { owner->wantCloak = true; } else if(c.params[0] == 0) { owner->wantCloak = false; owner->curCloakTimeout = gs->frameNum + owner->cloakTimeout; } else { // cause some code parts need it to be either 0 or 1, // we can not accept any other values as valid return false; } SetCommandDescParam0(c); selectedUnitsHandler.PossibleCommandChange(owner); return true; } case CMD_STOCKPILE: { int change = 1; if (c.options & RIGHT_MOUSE_KEY) { change *= -1; } if (c.options & SHIFT_KEY) { change *= 5; } if (c.options & CONTROL_KEY) { change *= 20; } stockpileWeapon->numStockpileQued += change; if (stockpileWeapon->numStockpileQued < 0) { stockpileWeapon->numStockpileQued = 0; } UpdateStockpileIcon(); return true; } } // this is a custom lua command, calling CommandFallback // and ignoring the result as this can't stay in the queue if (nonQueingCommands.find(c.GetID()) != nonQueingCommands.end()) { eventHandler.CommandFallback(owner, c); return true; } return false; }
void CSelectedUnitsHandlerAI::SelectAttack(const Command& cmd, int player) { std::vector<int> targets; if (cmd.params.size() == 4) { SelectCircleUnits(cmd.GetPos(0), cmd.params[3], player, targets); } else { SelectRectangleUnits(cmd.GetPos(0), cmd.GetPos(3), player, targets); } if (targets.empty()) return; const bool queueing = !!(cmd.options & SHIFT_KEY); const std::vector<int>& selected = selectedUnitsHandler.netSelected[player]; const unsigned int targetsCount = targets.size(); const unsigned int selectedCount = selected.size(); if (selectedCount == 0) return; Command attackCmd(CMD_ATTACK, cmd.options, 0.0f); // delete the attack commands and bail for CONTROL_KEY if (cmd.options & CONTROL_KEY) { attackCmd.options |= SHIFT_KEY; for (unsigned int s = 0; s < selectedCount; s++) { const CUnit* unit = unitHandler->units[ selected[s] ]; if (unit == NULL) continue; CCommandAI* commandAI = unitHandler->units[selected[s]]->commandAI; for (unsigned int t = 0; t < targetsCount; t++) { attackCmd.params[0] = targets[t]; if (commandAI->WillCancelQueued(attackCmd)) { commandAI->GiveCommand(attackCmd, false); } } } return; } // get the group center float3 midPos; unsigned int realCount = 0; for (unsigned int s = 0; s < selectedCount; s++) { CUnit* unit = unitHandler->units[selected[s]]; if (unit == NULL) continue; if (queueing) { midPos += LastQueuePosition(unit); } else { midPos += unit->midPos; } realCount++; } if (realCount == 0) return; midPos /= realCount; // sort the targets std::vector<DistInfo> distVec; for (unsigned int t = 0; t < targetsCount; t++) { const CUnit* unit = unitHandler->units[ targets[t] ]; const float3 unitPos = queueing ? LastQueuePosition(unit) : float3(unit->midPos); DistInfo di; di.unitID = targets[t]; di.dist = (unitPos - midPos).SqLength2D(); distVec.push_back(di); } sort(distVec.begin(), distVec.end()); // give the commands for (unsigned int s = 0; s < selectedCount; s++) { if (!queueing) { // clear it for the first command attackCmd.options &= ~SHIFT_KEY; } CUnit* unit = unitHandler->units[selected[s]]; if (unit == NULL) continue; CCommandAI* commandAI = unit->commandAI; for (unsigned t = 0; t < targetsCount; t++) { attackCmd.params[0] = distVec[t].unitID; if (!queueing || !commandAI->WillCancelQueued(attackCmd)) { commandAI->GiveCommand(attackCmd, false); AddUnitSetMaxSpeedCommand(unit, attackCmd.options); // following commands are always queued attackCmd.options |= SHIFT_KEY; } } } }
void CSelectedUnitsHandlerAI::GiveCommandNet(Command &c, int player) { const std::vector<int>& netSelected = selectedUnitsHandler.netSelected[player]; std::vector<int>::const_iterator ui; const int nbrOfSelectedUnits = netSelected.size(); const int cmd_id = c.GetID(); if (nbrOfSelectedUnits < 1) { // no units to command } else if ((cmd_id == CMD_ATTACK) && ( (c.GetParamsCount() == 6) || ((c.GetParamsCount() == 4) && (c.GetParam(3) > 0.001f)) )) { SelectAttack(c, player); } else if (nbrOfSelectedUnits == 1) { // a single unit selected CUnit* unit = unitHandler->units[*netSelected.begin()]; if (unit) { unit->commandAI->GiveCommand(c, true); if (MayRequireSetMaxSpeedCommand(c)) { AddUnitSetMaxSpeedCommand(unit, c.options); } if (cmd_id == CMD_WAIT) { if (player == gu->myPlayerNum) { waitCommandsAI.AcknowledgeCommand(c); } } } } // User Move Front Command: // // CTRL: Group Front/Speed command // // User Move Command: // // ALT: Group Front command // ALT+CTRL: Group Front/Speed command // CTRL: Group Locked/Speed command (maintain relative positions) // // User Patrol and Fight Commands: // // CTRL: Group Locked/Speed command (maintain relative positions) // ALT+CTRL: Group Locked command (maintain relative positions) // else if (((cmd_id == CMD_MOVE) || (cmd_id == CMD_FIGHT)) && (c.GetParamsCount() == 6)) { CalculateGroupData(player, !!(c.options & SHIFT_KEY)); MakeFrontMove(&c, player); const bool groupSpeed = !!(c.options & CONTROL_KEY); for(ui = netSelected.begin(); ui != netSelected.end(); ++ui) { CUnit* unit = unitHandler->units[*ui]; if (unit) { if (groupSpeed) { AddGroupSetMaxSpeedCommand(unit, c.options); } else { AddUnitSetMaxSpeedCommand(unit, c.options); } } } } else if ((cmd_id == CMD_MOVE) && (c.options & ALT_KEY)) { CalculateGroupData(player, !!(c.options & SHIFT_KEY)); // use the vector from the middle of group to new pos as forward dir const float3 pos(c.GetParam(0), c.GetParam(1), c.GetParam(2)); float3 frontdir = pos - centerCoor; frontdir.y = 0.0f; frontdir.ANormalize(); const float3 sideDir = frontdir.cross(UpVector); // calculate so that the units form in an aproximate square float length = 100.0f + (math::sqrt((float)nbrOfSelectedUnits) * 32.0f); // push back some extra params so it confer with a front move c.PushPos(pos + (sideDir * length)); MakeFrontMove(&c, player); const bool groupSpeed = !!(c.options & CONTROL_KEY); for(ui = netSelected.begin(); ui != netSelected.end(); ++ui) { CUnit* unit = unitHandler->units[*ui]; if (unit) { if (groupSpeed) { AddGroupSetMaxSpeedCommand(unit, c.options); } else { AddUnitSetMaxSpeedCommand(unit, c.options); } } } } else if ((c.options & CONTROL_KEY) && ((cmd_id == CMD_MOVE) || (cmd_id == CMD_PATROL) || (cmd_id == CMD_FIGHT))) { CalculateGroupData(player, !!(c.options & SHIFT_KEY)); const bool groupSpeed = !(c.options & ALT_KEY); for (ui = netSelected.begin(); ui != netSelected.end(); ++ui) { CUnit* unit = unitHandler->units[*ui]; if (unit) { // Modifying the destination relative to the center of the group Command uc = c; float3 midPos; if (c.options & SHIFT_KEY) { midPos = LastQueuePosition(unit); } else { midPos = unit->midPos; } uc.params[CMDPARAM_MOVE_X] += midPos.x - centerCoor.x; uc.params[CMDPARAM_MOVE_Y] += midPos.y - centerCoor.y; uc.params[CMDPARAM_MOVE_Z] += midPos.z - centerCoor.z; unit->commandAI->GiveCommand(uc, false); if (groupSpeed) { AddGroupSetMaxSpeedCommand(unit, c.options); } else { AddUnitSetMaxSpeedCommand(unit, c.options); } } } } else { for (ui = netSelected.begin(); ui != netSelected.end(); ++ui) { CUnit* unit = unitHandler->units[*ui]; if (unit) { // appending a CMD_SET_WANTED_MAX_SPEED command to // every command is a little bit wasteful, n'est pas? unit->commandAI->GiveCommand(c, false); if (MayRequireSetMaxSpeedCommand(c)) { AddUnitSetMaxSpeedCommand(unit, c.options); } } } if (cmd_id == CMD_WAIT) { if (player == gu->myPlayerNum) { waitCommandsAI.AcknowledgeCommand(c); } } } }
CommandResult Actions::echo(const Command &cmd) { return {true, cmd.argument()}; }
// Only override the ones you need; the default action is to return false. bool MapOutfitterPanel::KeyDown(SDL_Keycode key, Uint16 mod, const Command &command) { if(command.Has(Command::MAP) || key == 'd' || key == SDLK_ESCAPE || (key == 'w' && (mod & (KMOD_CTRL | KMOD_GUI)))) GetUI()->Pop(this); else if(key == 's') { GetUI()->Pop(this); GetUI()->Push(new MapShipyardPanel(*this)); } else if(key == 'i') { GetUI()->Pop(this); GetUI()->Push(new MissionPanel(*this)); } else if(key == 'p') { GetUI()->Pop(this); GetUI()->Push(new MapDetailPanel(*this)); } else if((key == SDLK_DOWN || key == SDLK_UP) && !zones.empty()) { // First, find the currently selected item, if any auto it = zones.begin(); if(!selected) { if(key == SDLK_DOWN) it = --zones.end(); } else { for( ; it != zones.end() - 1; ++it) if(it->Value() == selected) break; } if(key == SDLK_DOWN) { ++it; if(it == zones.end()) it = zones.begin(); } else { if(it == zones.begin()) it = zones.end(); --it; } double top = (it->Center() - it->Size()).Y(); double bottom = (it->Center() + it->Size()).Y(); if(bottom > Screen::Bottom()) scroll += Screen::Bottom() - bottom; if(top < Screen::Top()) scroll += Screen::Top() - top; selected = it->Value(); } else if(key == SDLK_PAGEUP || key == SDLK_PAGEDOWN) { scroll += (Screen::Height() - 100) * ((key == SDLK_PAGEUP) - (key == SDLK_PAGEDOWN)); scroll = min(0, max(-maxScroll, scroll)); } else return false; return true; }
void* ThreadPool::Process(void* arg) { ThreadProcess threadprocess; Command command; while (true) { pthread_mutex_lock(&command_mutex_); // 如果线程需要退出,则此时退出 if (1 == thread_id_map_[pthread_self()]) { pthread_mutex_unlock(&command_mutex_); printf("thread %u will exit\n", pthread_self()); pthread_exit(NULL); } // 当线程不需要退出且没有需要处理的任务时,需要缩容的则缩容,不需要的则等待信号 if (0 == command_.size() && !bshutdown_) { if(icurr_thread_num_ > THREAD_NUM) { DeleteThread(); if (1 == thread_id_map_[pthread_self()]) { pthread_mutex_unlock(&command_mutex_); printf("thread %u will exit\n", pthread_self()); pthread_exit(NULL); } } pthread_cond_wait(&command_cond_,&command_mutex_); } // 线程池需要关闭,关闭已有的锁,线程退出 if(bshutdown_) { pthread_mutex_unlock (&command_mutex_); printf ("thread %u will exit\n", pthread_self ()); pthread_exit (NULL); } // 如果线程池的最大线程数不等于初始线程数,则表明需要扩容 if(icurr_thread_num_ < command_.size())) { AddThread(); } // 从容器中取出待办任务 std::vector<Command>::iterator iter = command_.begin(); command.set_arg(iter->get_arg()); command.set_cmd(iter->get_cmd()); command_.erase(iter); pthread_mutex_unlock(&command_mutex_); // 开始业务处理 switch(command.get_cmd()) { case 0: threadprocess.Process0(command.get_arg()); break; case 1: threadprocess.Process1(command.get_arg()); break; case 2: threadprocess.Process2(command.get_arg()); break; default: break; } } return NULL; // 完全为了消除警告(eclipse编写的代码,警告很烦人) }
ExecResult operator() (ARGS&& ...args) { com_.bind (std::forward<ARGS> (args)...); return com_(); }
/** Checks for an already occupied shortcut. */ void DlgCustomKeyboardImp::on_editShortcut_textChanged(const QString& sc) { assignedTreeWidget->clear(); QTreeWidgetItem* item = commandTreeWidget->currentItem(); if (!item) return; QVariant data = item->data(1, Qt::UserRole); QByteArray name = data.toByteArray(); // command name CommandManager & cCmdMgr = Application::Instance->commandManager(); Command* cmd = cCmdMgr.getCommandByName(name.constData()); if (cmd && !cmd->getAction()) { buttonAssign->setEnabled(false); // command not in use return; } buttonAssign->setEnabled(true); QKeySequence ks(sc); if (!ks.isEmpty()) { int countAmbiguous = 0; QString ambiguousCommand; QString ambiguousMenu; CommandManager & cCmdMgr = Application::Instance->commandManager(); std::vector<Command*> cmds = cCmdMgr.getAllCommands(); for (std::vector<Command*>::iterator it = cmds.begin(); it != cmds.end(); ++it) { QList<QAction*> acts; if ((*it)->getAction()) { // A command may have several QAction's. So, check all of them if one of them matches (See bug #0002160) QList<QAction*> acts = (*it)->getAction()->findChildren<QAction*>(); for (QList<QAction*>::iterator jt = acts.begin(); jt != acts.end(); ++jt) { if ((*jt)->shortcut() == ks) { ++countAmbiguous; ambiguousCommand = QString::fromLatin1((*it)->getName()); // store the last one ambiguousMenu = qApp->translate((*it)->className(), (*it)->getMenuText()); QTreeWidgetItem* item = new QTreeWidgetItem(assignedTreeWidget); item->setText(1, qApp->translate((*it)->className(), (*it)->getMenuText())); item->setToolTip(1, qApp->translate((*it)->className(), (*it)->getToolTipText())); item->setData(1, Qt::UserRole, QByteArray((*it)->getName())); item->setSizeHint(0, QSize(32, 32)); if ((*it)->getPixmap()) item->setIcon(0, BitmapFactory().iconFromTheme((*it)->getPixmap())); break; } } } } if (countAmbiguous > 0) assignedTreeWidget->resizeColumnToContents(0); if (countAmbiguous > 1) { QMessageBox::warning(this, tr("Multiple defined shortcut"), tr("The shortcut '%1' is defined more than once. This could result into unexpected behaviour.").arg(sc) ); editShortcut->setFocus(); buttonAssign->setEnabled(false); } else if (countAmbiguous == 1 && ambiguousCommand != QLatin1String(name)) { QMessageBox::warning(this, tr("Already defined shortcut"), tr("The shortcut '%1' is already assigned to '%2'.\n\nPlease define another shortcut.").arg(sc).arg(ambiguousMenu) ); editShortcut->setFocus(); buttonAssign->setEnabled(false); } else { if (cmd && cmd->getAction() && cmd->getAction()->shortcut() == ks) buttonAssign->setEnabled(false); } } else { if (cmd && cmd->getAction() && cmd->getAction()->shortcut().isEmpty()) buttonAssign->setEnabled(false); // both key sequences are empty } }
int ClusterCommand::execute(){ try { if (abort == true) { if (calledHelp) { return 0; } return 2; } //phylip file given and cutoff not given - use cluster.classic because it uses less memory and is faster if ((format == "phylip") && (cutoff > 10.0)) { m->mothurOutEndLine(); m->mothurOut("You are using a phylip file and no cutoff. I will run cluster.classic to save memory and time."); m->mothurOutEndLine(); //run unique.seqs for deconvolute results string inputString = "phylip=" + distfile; if (namefile != "") { inputString += ", name=" + namefile; } else if (countfile != "") { inputString += ", count=" + countfile; } inputString += ", precision=" + toString(precision); inputString += ", method=" + method; if (hard) { inputString += ", hard=T"; } else { inputString += ", hard=F"; } if (sim) { inputString += ", sim=T"; } else { inputString += ", sim=F"; } m->mothurOutEndLine(); m->mothurOut("/------------------------------------------------------------/"); m->mothurOutEndLine(); m->mothurOut("Running command: cluster.classic(" + inputString + ")"); m->mothurOutEndLine(); Command* clusterClassicCommand = new ClusterDoturCommand(inputString); clusterClassicCommand->execute(); delete clusterClassicCommand; m->mothurOut("/------------------------------------------------------------/"); m->mothurOutEndLine(); return 0; } ReadMatrix* read; if (format == "column") { read = new ReadColumnMatrix(columnfile, sim); } //sim indicates whether its a similarity matrix else if (format == "phylip") { read = new ReadPhylipMatrix(phylipfile, sim); } read->setCutoff(cutoff); NameAssignment* nameMap = NULL; CountTable* ct = NULL; map<string, int> counts; if(namefile != ""){ nameMap = new NameAssignment(namefile); nameMap->readMap(); read->read(nameMap); }else if (countfile != "") { ct = new CountTable(); ct->readTable(countfile, false, false); read->read(ct); counts = ct->getNameMap(); }else { read->read(nameMap); } list = read->getListVector(); matrix = read->getDMatrix(); if(countfile != "") { rabund = new RAbundVector(); createRabund(ct, list, rabund); //creates an rabund that includes the counts for the unique list delete ct; }else { rabund = new RAbundVector(list->getRAbundVector()); } delete read; if (m->control_pressed) { //clean up delete list; delete matrix; delete rabund; if(countfile == ""){rabundFile.close(); sabundFile.close(); m->mothurRemove((fileroot+ tag + ".rabund")); m->mothurRemove((fileroot+ tag + ".sabund")); } listFile.close(); m->mothurRemove((fileroot+ tag + ".list")); outputTypes.clear(); return 0; } //create cluster if (method == "furthest") { cluster = new CompleteLinkage(rabund, list, matrix, cutoff, method, adjust); } else if(method == "nearest"){ cluster = new SingleLinkage(rabund, list, matrix, cutoff, method, adjust); } else if(method == "average"){ cluster = new AverageLinkage(rabund, list, matrix, cutoff, method, adjust); } else if(method == "weighted"){ cluster = new WeightedLinkage(rabund, list, matrix, cutoff, method, adjust); } tag = cluster->getTag(); if (outputDir == "") { outputDir += m->hasPath(distfile); } fileroot = outputDir + m->getRootName(m->getSimpleName(distfile)); map<string, string> variables; variables["[filename]"] = fileroot; variables["[clustertag]"] = tag; string sabundFileName = getOutputFileName("sabund", variables); string rabundFileName = getOutputFileName("rabund", variables); if (countfile != "") { variables["[tag2]"] = "unique_list"; } string listFileName = getOutputFileName("list", variables); if (countfile == "") { m->openOutputFile(sabundFileName, sabundFile); m->openOutputFile(rabundFileName, rabundFile); outputNames.push_back(sabundFileName); outputTypes["sabund"].push_back(sabundFileName); outputNames.push_back(rabundFileName); outputTypes["rabund"].push_back(rabundFileName); } m->openOutputFile(listFileName, listFile); outputNames.push_back(listFileName); outputTypes["list"].push_back(listFileName); list->printHeaders(listFile); time_t estart = time(NULL); float previousDist = 0.00000; float rndPreviousDist = 0.00000; oldRAbund = *rabund; oldList = *list; print_start = true; start = time(NULL); loops = 0; double saveCutoff = cutoff; while (matrix->getSmallDist() < cutoff && matrix->getNNodes() > 0){ if (m->control_pressed) { //clean up delete list; delete matrix; delete rabund; delete cluster; if(countfile == "") {rabundFile.close(); sabundFile.close(); m->mothurRemove((fileroot+ tag + ".rabund")); m->mothurRemove((fileroot+ tag + ".sabund")); } listFile.close(); m->mothurRemove((fileroot+ tag + ".list")); outputTypes.clear(); return 0; } if (print_start && m->isTrue(timing)) { m->mothurOut("Clustering (" + tag + ") dist " + toString(matrix->getSmallDist()) + "/" + toString(m->roundDist(matrix->getSmallDist(), precision)) + "\t(precision: " + toString(precision) + ", Nodes: " + toString(matrix->getNNodes()) + ")"); cout.flush(); print_start = false; } loops++; cluster->update(cutoff); float dist = matrix->getSmallDist(); float rndDist; if (hard) { rndDist = m->ceilDist(dist, precision); }else{ rndDist = m->roundDist(dist, precision); } if(previousDist <= 0.0000 && dist != previousDist){ printData("unique", counts); } else if(rndDist != rndPreviousDist){ printData(toString(rndPreviousDist, length-1), counts); } previousDist = dist; rndPreviousDist = rndDist; oldRAbund = *rabund; oldList = *list; } if (print_start && m->isTrue(timing)) { m->mothurOut("Clustering (" + tag + ") for distance " + toString(previousDist) + "/" + toString(rndPreviousDist) + "\t(precision: " + toString(precision) + ", Nodes: " + toString(matrix->getNNodes()) + ")"); cout.flush(); print_start = false; } if(previousDist <= 0.0000){ printData("unique", counts); } else if(rndPreviousDist<cutoff){ printData(toString(rndPreviousDist, length-1), counts); } delete matrix; delete list; delete rabund; delete cluster; if (countfile == "") { sabundFile.close(); rabundFile.close(); } listFile.close(); if (saveCutoff != cutoff) { if (hard) { saveCutoff = m->ceilDist(saveCutoff, precision); } else { saveCutoff = m->roundDist(saveCutoff, precision); } m->mothurOut("changed cutoff to " + toString(cutoff)); m->mothurOutEndLine(); } //set list file as new current listfile string current = ""; itTypes = outputTypes.find("list"); if (itTypes != outputTypes.end()) { if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setListFile(current); } } //set rabund file as new current rabundfile itTypes = outputTypes.find("rabund"); if (itTypes != outputTypes.end()) { if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setRabundFile(current); } } //set sabund file as new current sabundfile itTypes = outputTypes.find("sabund"); if (itTypes != outputTypes.end()) { if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setSabundFile(current); } } m->mothurOutEndLine(); m->mothurOut("Output File Names: "); m->mothurOutEndLine(); for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); } m->mothurOutEndLine(); //if (m->isTrue(timing)) { m->mothurOut("It took " + toString(time(NULL) - estart) + " seconds to cluster"); m->mothurOutEndLine(); //} return 0; } catch(exception& e) { m->errorOut(e, "ClusterCommand", "execute"); exit(1); } }
void NNCommand2(Connection *conn) { char *ptr; char *cmd; char *buf; Command *scan; int len; conn->co_Func = NNCommand2; conn->co_State = "waitcmd"; /* * we have to be careful in regards to recursive operation, nor do * we want one descriptor to hog the process. We can't set RFds * because the next command may already be entirely loaded into an * MBuf so setting RFds may not unblock us. Instead, we set WFds * which basically forces a wakeup at some point in the future. */ if (conn->co_FCounter) { FD_SET(conn->co_Desc->d_Fd, &WFds); /* * if the other side closed the connection, select() is * not going to wake up for write(!) so set RFds too. */ if (conn->co_TMBuf.mh_WError) FD_SET(conn->co_Desc->d_Fd, &RFds); return; } ++conn->co_FCounter; /* * if there is still output pending, do not process the next * command. */ if (conn->co_TMBuf.mh_Bytes > 0 && !conn->co_TMBuf.mh_WError) return; /* * get command */ if ((len = MBReadLine(&conn->co_RMBuf, &buf)) == 0) { StatusUpdate(conn, "(idle)"); return; } conn->co_ByteCountType = DRBC_NONE; /* * check EOF */ if (len < 0 || conn->co_TMBuf.mh_WError) { NNTerminate(conn); return; } /* * strip CR LF */ ptr = buf; if (len > 1 && ptr[len-2] == '\r') ptr[len-2] = 0; if (DebugOpt) printf("command: %s\n", ptr); if (strncasecmp(ptr, "authinfo pass ", 14)) { LogCmd(conn, '<', ptr); } else { LogCmd(conn, '<', "authinfo pass **unlogged**"); } if (conn->co_Auth.dr_Flags & DF_USEPROXIED) { struct sockaddr_in sin; char *pt = NULL; if (strncasecmp(ptr, "proxied ", 8) || ! ((pt = strrchr(ptr, ':')))) { MBLogPrintf(conn, &conn->co_TMBuf, "400 %s: Proxy authentication failure.\r\n", conn->co_Auth.dr_VServerDef->vs_HostName ); NNTerminate(conn); } *pt++ = '\0'; ptr += 8; bzero((void *)&sin, sizeof(&sin)); sin.sin_family = AF_INET; sin.sin_port = htons(atoi(pt)); sin.sin_addr.s_addr = inet_addr(ptr); bcopy(&sin, &conn->co_Auth.dr_Addr, sizeof(conn->co_Auth.dr_Addr)); conn->co_Auth.dr_Flags &= ~DF_USEPROXIED; conn->co_Auth.dr_ResultFlags = DR_REQUIRE_DNS; return; } /* * extract command (note: StatusUpdate() will limit the line length) */ StatusUpdate(conn, "%s", ptr); if ((cmd = parseword(&ptr, " \t")) == NULL) { NNCommand(conn); return; } { int i; for (i = 0; cmd[i]; ++i) cmd[i] = tolower((int)(unsigned char)cmd[i]); } /* * Locate and execute command */ for (scan = &Cmds[0]; scan < &Cmds[arysize(Cmds)]; ++scan) { if (strcmp(cmd, scan->cmd_Name) == 0) { if (conn->co_Flags & COF_SERVER) { if (scan->cmd_Flags & CMDF_SERVER) { if ((conn->co_Auth.dr_Flags & DF_FEEDONLY) == 0) break; if ((scan->cmd_Flags & CMDF_NOTFEEDONLY) == 0) break; } } else { if (scan->cmd_Flags & CMDF_READER) break; } } } if (scan < &Cmds[arysize(Cmds)]) { if ((scan->cmd_Flags & CMDF_AUTH) && (conn->co_Auth.dr_Flags & DF_AUTHREQUIRED) ) { MBLogPrintf(conn, &conn->co_TMBuf, "480 Authentication required for command\r\n"); NNCommand(conn); } else { conn->co_ByteCountType = scan->cmd_DRBC_Type; scan->cmd_Func(conn, &ptr); } } else { NNUnknownCommand(conn); } }
void CommandParser::ProcessCommand(LocalUser *user, std::string &cmd) { std::vector<std::string> command_p; irc::tokenstream tokens(cmd); std::string command, token; tokens.GetToken(command); /* A client sent a nick prefix on their command (ick) * rhapsody and some braindead bouncers do this -- * the rfc says they shouldnt but also says the ircd should * discard it if they do. */ if (command[0] == ':') tokens.GetToken(command); while (tokens.GetToken(token)) command_p.push_back(token); std::transform(command.begin(), command.end(), command.begin(), ::toupper); /* find the command, check it exists */ Command* handler = GetHandler(command); /* Modify the user's penalty regardless of whether or not the command exists */ if (!user->HasPrivPermission("users/flood/no-throttle")) { // If it *doesn't* exist, give it a slightly heftier penalty than normal to deter flooding us crap user->CommandFloodPenalty += handler ? handler->Penalty * 1000 : 2000; } if (!handler) { ModResult MOD_RESULT; FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, command_p, user, false, cmd)); if (MOD_RESULT == MOD_RES_DENY) return; /* * This double lookup is in case a module (abbreviation) wishes to change a command. * Sure, the double lookup is a bit painful, but bear in mind this only happens for unknowns anyway. * * Thanks dz for making me actually understand why this is necessary! * -- w00t */ handler = GetHandler(command); if (!handler) { if (user->registered == REG_ALL) user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :Unknown command",command.c_str()); ServerInstance->stats->statsUnknown++; return; } } // If we were given more parameters than max_params then append the excess parameter(s) // to command_p[maxparams-1], i.e. to the last param that is still allowed if (handler->max_params && command_p.size() > handler->max_params) { /* * command_p input (assuming max_params 1): * this * is * a * test */ // Iterator to the last parameter that will be kept const std::vector<std::string>::iterator lastkeep = command_p.begin() + (handler->max_params - 1); // Iterator to the first excess parameter const std::vector<std::string>::iterator firstexcess = lastkeep + 1; // Append all excess parameter(s) to the last parameter, seperated by spaces for (std::vector<std::string>::const_iterator i = firstexcess; i != command_p.end(); ++i) { lastkeep->push_back(' '); lastkeep->append(*i); } // Erase the excess parameter(s) command_p.erase(firstexcess, command_p.end()); } /* * We call OnPreCommand here seperately if the command exists, so the magic above can * truncate to max_params if necessary. -- w00t */ ModResult MOD_RESULT; FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, command_p, user, false, cmd)); if (MOD_RESULT == MOD_RES_DENY) return; /* activity resets the ping pending timer */ user->nping = ServerInstance->Time() + user->MyClass->GetPingTime(); if (handler->flags_needed) { if (!user->IsModeSet(handler->flags_needed)) { user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - You do not have the required operator privileges"); return; } if (!user->HasPermission(command)) { user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - Oper type %s does not have access to command %s", user->oper->name.c_str(), command.c_str()); return; } } if ((user->registered == REG_ALL) && (!user->IsOper()) && (handler->IsDisabled())) { /* command is disabled! */ if (ServerInstance->Config->DisabledDontExist) { user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :Unknown command", command.c_str()); } else { user->WriteNumeric(ERR_UNKNOWNCOMMAND, "%s :This command has been disabled.", command.c_str()); } ServerInstance->SNO->WriteToSnoMask('t', "%s denied for %s (%s@%s)", command.c_str(), user->nick.c_str(), user->ident.c_str(), user->host.c_str()); return; } if ((!command_p.empty()) && (command_p.back().empty()) && (!handler->allow_empty_last_param)) command_p.pop_back(); if (command_p.size() < handler->min_params) { user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s :Not enough parameters.", command.c_str()); if ((ServerInstance->Config->SyntaxHints) && (user->registered == REG_ALL) && (handler->syntax.length())) user->WriteNumeric(RPL_SYNTAX, ":SYNTAX %s %s", handler->name.c_str(), handler->syntax.c_str()); return; } if ((user->registered != REG_ALL) && (!handler->WorksBeforeReg())) { user->WriteNumeric(ERR_NOTREGISTERED, "%s :You have not registered",command.c_str()); } else { /* passed all checks.. first, do the (ugly) stats counters. */ handler->use_count++; /* module calls too */ FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, command_p, user, true, cmd)); if (MOD_RESULT == MOD_RES_DENY) return; /* * WARNING: be careful, the user may be deleted soon */ CmdResult result = handler->Handle(command_p, user); FOREACH_MOD(OnPostCommand, (handler, command_p, user, result, cmd)); } }
void OutputPaneManager::init() { ActionContainer *mwindow = ActionManager::actionContainer(Constants::M_WINDOW); const Context globalContext(Constants::C_GLOBAL); // Window->Output Panes ActionContainer *mpanes = ActionManager::createMenu(Constants::M_WINDOW_PANES); mwindow->addMenu(mpanes, Constants::G_WINDOW_PANES); mpanes->menu()->setTitle(tr("Output &Panes")); mpanes->appendGroup("Coreplugin.OutputPane.ActionsGroup"); mpanes->appendGroup("Coreplugin.OutputPane.PanesGroup"); Command *cmd; cmd = ActionManager::registerAction(m_clearAction, "Coreplugin.OutputPane.clear", globalContext); m_clearButton->setDefaultAction(cmd->action()); mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup"); cmd = ActionManager::registerAction(m_prevAction, "Coreplugin.OutputPane.previtem", globalContext); cmd->setDefaultKeySequence(QKeySequence(tr("Shift+F6"))); m_prevToolButton->setDefaultAction(cmd->action()); mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup"); cmd = ActionManager::registerAction(m_nextAction, "Coreplugin.OutputPane.nextitem", globalContext); m_nextToolButton->setDefaultAction(cmd->action()); cmd->setDefaultKeySequence(QKeySequence(tr("F6"))); mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup"); cmd = ActionManager::registerAction(m_minMaxAction, "Coreplugin.OutputPane.minmax", globalContext); cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("Ctrl+9") : tr("Alt+9"))); cmd->setAttribute(Command::CA_UpdateText); cmd->setAttribute(Command::CA_UpdateIcon); mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup"); connect(m_minMaxAction, SIGNAL(triggered()), this, SLOT(slotMinMax())); m_minMaxButton->setDefaultAction(cmd->action()); mpanes->addSeparator(globalContext, "Coreplugin.OutputPane.ActionsGroup"); QFontMetrics titleFm = m_titleLabel->fontMetrics(); int minTitleWidth = 0; m_panes = ExtensionSystem::PluginManager::getObjects<IOutputPane>(); qSort(m_panes.begin(), m_panes.end(), &comparePanes); const int n = m_panes.size(); int shortcutNumber = 1; const Id baseId = Id("QtCreator.Pane."); for (int i = 0; i != n; ++i) { IOutputPane *outPane = m_panes.at(i); const int idx = m_outputWidgetPane->addWidget(outPane->outputWidget(this)); QTC_CHECK(idx == i); connect(outPane, SIGNAL(showPage(int)), this, SLOT(showPage(int))); connect(outPane, SIGNAL(hidePage()), this, SLOT(slotHide())); connect(outPane, SIGNAL(togglePage(int)), this, SLOT(togglePage(int))); connect(outPane, SIGNAL(navigateStateUpdate()), this, SLOT(updateNavigateState())); connect(outPane, SIGNAL(flashButton()), this, SLOT(flashButton())); connect(outPane, SIGNAL(setBadgeNumber(int)), this, SLOT(setBadgeNumber(int))); QWidget *toolButtonsContainer = new QWidget(m_opToolBarWidgets); QHBoxLayout *toolButtonsLayout = new QHBoxLayout; toolButtonsLayout->setMargin(0); toolButtonsLayout->setSpacing(0); foreach (QWidget *toolButton, outPane->toolBarWidgets()) toolButtonsLayout->addWidget(toolButton); toolButtonsLayout->addStretch(5); toolButtonsContainer->setLayout(toolButtonsLayout); m_opToolBarWidgets->addWidget(toolButtonsContainer); minTitleWidth = qMax(minTitleWidth, titleFm.width(outPane->displayName())); QString suffix = outPane->displayName().simplified(); suffix.remove(QLatin1Char(' ')); const Id id = baseId.withSuffix(suffix); QAction *action = new QAction(outPane->displayName(), this); Command *cmd = ActionManager::registerAction(action, id, globalContext); mpanes->addAction(cmd, "Coreplugin.OutputPane.PanesGroup"); m_actions.append(cmd->action()); m_ids.append(id); cmd->setDefaultKeySequence(QKeySequence(paneShortCut(shortcutNumber))); OutputPaneToggleButton *button = new OutputPaneToggleButton(shortcutNumber, outPane->displayName(), cmd->action()); ++shortcutNumber; m_buttonsWidget->layout()->addWidget(button); m_buttons.append(button); connect(button, SIGNAL(clicked()), this, SLOT(buttonTriggered())); bool visible = outPane->priorityInStatusBar() != -1; button->setVisible(visible); connect(cmd->action(), SIGNAL(triggered()), this, SLOT(shortcutTriggered())); } m_titleLabel->setMinimumWidth(minTitleWidth + m_titleLabel->contentsMargins().left() + m_titleLabel->contentsMargins().right()); m_buttonsWidget->layout()->addWidget(m_manageButton); connect(m_manageButton, SIGNAL(clicked()), this, SLOT(popupMenu())); readSettings(); }
bool CCommandAI::AllowedCommand(const Command& c, bool fromSynced) { const int cmdID = c.GetID(); // TODO check if the command is in the map first, for more commands switch (cmdID) { case CMD_MOVE: case CMD_ATTACK: case CMD_AREA_ATTACK: case CMD_RECLAIM: case CMD_REPAIR: case CMD_RESURRECT: case CMD_PATROL: case CMD_RESTORE: case CMD_FIGHT: case CMD_MANUALFIRE: case CMD_UNLOAD_UNIT: case CMD_UNLOAD_UNITS: { if (!IsCommandInMap(c)) { return false; } } break; default: { // build commands if (cmdID < 0) { if (!IsCommandInMap(c)) return false; const CBuilderCAI* bcai = dynamic_cast<const CBuilderCAI*>(this); const CFactoryCAI* fcai = dynamic_cast<const CFactoryCAI*>(this); // non-builders cannot ever execute these // we can get here if a factory is selected along with the // unit it is currently building and a build-order is given // to the former if (fcai == NULL && bcai == NULL) return false; // {Builder,Factory}CAI::GiveCommandReal (should) handle the // case where buildOptions.find(cmdID) == buildOptions.end() } } break; } const UnitDef* ud = owner->unitDef; // AI's may do as they like const CSkirmishAIHandler::ids_t& saids = skirmishAIHandler.GetSkirmishAIsInTeam(owner->team); const bool aiOrder = (!saids.empty()); switch (cmdID) { case CMD_MANUALFIRE: if (!ud->canManualFire) return false; // fall through case CMD_ATTACK: { if (!IsAttackCapable()) return false; if (c.params.size() == 1) { const CUnit* attackee = GetCommandUnit(c, 0); if (attackee == NULL) return false; if (!attackee->pos.IsInBounds()) return false; } else { AdjustGroundAttackCommand(c, fromSynced, aiOrder); } break; } case CMD_MOVE: if (!ud->canmove) return false; break; case CMD_FIGHT: if (!ud->canFight) return false; break; case CMD_GUARD: { const CUnit* guardee = GetCommandUnit(c, 0); if (!ud->canGuard) { return false; } if (owner && !owner->pos.IsInBounds()) { return false; } if (guardee && !guardee->pos.IsInBounds()) { return false; } } break; case CMD_PATROL: { if (!ud->canPatrol) { return false; } } break; case CMD_CAPTURE: { const CUnit* capturee = GetCommandUnit(c, 0); if (!ud->canCapture) { return false; } if (capturee && !capturee->pos.IsInBounds()) { return false; } } break; case CMD_RECLAIM: { const CUnit* reclaimeeUnit = GetCommandUnit(c, 0); const CFeature* reclaimeeFeature = NULL; if (c.IsAreaCommand()) { return true; } if (!ud->canReclaim) { return false; } if (reclaimeeUnit && !reclaimeeUnit->unitDef->reclaimable) { return false; } if (reclaimeeUnit && !reclaimeeUnit->AllowedReclaim(owner)) { return false; } if (reclaimeeUnit && !reclaimeeUnit->pos.IsInBounds()) { return false; } if (reclaimeeUnit == NULL && !c.params.empty()) { const unsigned int reclaimeeFeatureID(c.params[0]); if (reclaimeeFeatureID >= unitHandler->MaxUnits()) { reclaimeeFeature = featureHandler->GetFeature(reclaimeeFeatureID - unitHandler->MaxUnits()); if (reclaimeeFeature && !reclaimeeFeature->def->reclaimable) { return false; } } } } break; case CMD_RESTORE: { if (!ud->canRestore || mapDamage->disabled) { return false; } } break; case CMD_RESURRECT: { if (!ud->canResurrect) { return false; } } break; case CMD_REPAIR: { const CUnit* repairee = GetCommandUnit(c, 0); if (!ud->canRepair && !ud->canAssist) { return false; } if (repairee && !repairee->pos.IsInBounds()) { return false; } if (repairee && ((repairee->beingBuilt && !ud->canAssist) || (!repairee->beingBuilt && !ud->canRepair))) { return false; } } break; } if (cmdID == CMD_FIRE_STATE && (c.params.empty() || !CanChangeFireState())) { return false; } if (cmdID == CMD_MOVE_STATE && (c.params.empty() || (!ud->canmove && !ud->builder))) { return false; } if (cmdID == CMD_REPEAT && (c.params.empty() || !ud->canRepeat || ((int)c.params[0] % 2) != (int)c.params[0]/* only 0 or 1 allowed */)) { return false; } if (cmdID == CMD_TRAJECTORY && (c.params.empty() || ud->highTrajectoryType < 2)) { return false; } if (cmdID == CMD_ONOFF && (c.params.empty() || !ud->onoffable || owner->beingBuilt || ((int)c.params[0] % 2) != (int)c.params[0]/* only 0 or 1 allowed */)) { return false; } if (cmdID == CMD_CLOAK && (c.params.empty() || !ud->canCloak || ((int)c.params[0] % 2) != (int)c.params[0]/* only 0 or 1 allowed */)) { return false; } if (cmdID == CMD_STOCKPILE && !stockpileWeapon) { return false; } return true; }
string OpDebug::report(const CurOp& curop, const SingleThreadedLockStats& lockStats) const { StringBuilder s; if ( iscommand ) s << "command "; else s << opToString( op ) << ' '; s << ns; if ( ! query.isEmpty() ) { if ( iscommand ) { s << " command: "; Command* curCommand = curop.getCommand(); if (curCommand) { mutablebson::Document cmdToLog(query, mutablebson::Document::kInPlaceDisabled); curCommand->redactForLogging(&cmdToLog); s << curCommand->name << " "; s << cmdToLog.toString(); } else { // Should not happen but we need to handle curCommand == NULL gracefully s << query.toString(); } } else { s << " query: "; s << query.toString(); } } if (!planSummary.empty()) { s << " planSummary: " << planSummary.toString(); } if ( ! updateobj.isEmpty() ) { s << " update: "; updateobj.toString( s ); } OPDEBUG_TOSTRING_HELP( cursorid ); OPDEBUG_TOSTRING_HELP( ntoreturn ); OPDEBUG_TOSTRING_HELP( ntoskip ); OPDEBUG_TOSTRING_HELP_BOOL( exhaust ); OPDEBUG_TOSTRING_HELP( nscanned ); OPDEBUG_TOSTRING_HELP( nscannedObjects ); OPDEBUG_TOSTRING_HELP_BOOL( idhack ); OPDEBUG_TOSTRING_HELP_BOOL( scanAndOrder ); OPDEBUG_TOSTRING_HELP( nmoved ); OPDEBUG_TOSTRING_HELP( nMatched ); OPDEBUG_TOSTRING_HELP( nModified ); OPDEBUG_TOSTRING_HELP( ninserted ); OPDEBUG_TOSTRING_HELP( ndeleted ); OPDEBUG_TOSTRING_HELP_BOOL( fastmod ); OPDEBUG_TOSTRING_HELP_BOOL( fastmodinsert ); OPDEBUG_TOSTRING_HELP_BOOL( upsert ); OPDEBUG_TOSTRING_HELP_BOOL( cursorExhausted ); OPDEBUG_TOSTRING_HELP( keyUpdates ); OPDEBUG_TOSTRING_HELP( writeConflicts ); if ( extra.len() ) s << " " << extra.str(); if ( ! exceptionInfo.empty() ) { s << " exception: " << exceptionInfo.msg; if ( exceptionInfo.code ) s << " code:" << exceptionInfo.code; } s << " numYields:" << curop.numYields(); OPDEBUG_TOSTRING_HELP( nreturned ); if (responseLength > 0) { s << " reslen:" << responseLength; } { BSONObjBuilder locks; lockStats.report(&locks); s << " locks:" << locks.obj().toString(); } s << " " << executionTime << "ms"; return s.str(); }
void CCommandAI::ClearTargetLock(const Command &c) { if (((c.GetID() == CMD_ATTACK) || (c.GetID() == CMD_MANUALFIRE)) && (c.options & META_KEY) == 0) { // no meta-bit attack lock, clear the order owner->DropCurrentAttackTarget(); } }
static void ExecuteTemplightCommand(Driver &TheDriver, DiagnosticsEngine &Diags, Compilation &C, Command &J, const char* Argv0, SmallVector<std::pair<int, const Command *>, 4>& FailingCommands) { // Since commandLineFitsWithinSystemLimits() may underestimate system's capacity // if the tool does not support response files, there is a chance/ that things // will just work without a response file, so we silently just skip it. if ( J.getCreator().getResponseFilesSupport() != Tool::RF_None && llvm::sys::commandLineFitsWithinSystemLimits( StringRef(J.getCreator().getName()), J.getArguments()) ) { std::string TmpName = TheDriver.GetTemporaryPath("response", "txt"); J.setResponseFile(C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str()))); } if ( StringRef(J.getCreator().getName()) == "clang" ) { // Initialize a compiler invocation object from the clang (-cc1) arguments. const ArgStringList &cc_arguments = J.getArguments(); const char** args_start = const_cast<const char**>(cc_arguments.data()); const char** args_end = args_start + cc_arguments.size(); std::unique_ptr<CompilerInstance> Clang(new CompilerInstance()); int Res = !CompilerInvocation::CreateFromArgs( Clang->getInvocation(), args_start, args_end, Diags); if(Res) FailingCommands.push_back(std::make_pair(Res, &J)); Clang->getFrontendOpts().DisableFree = false; // Infer the builtin include path if unspecified. void *GetExecutablePathVP = (void *)(intptr_t) GetExecutablePath; if (Clang->getHeaderSearchOpts().UseBuiltinIncludes && Clang->getHeaderSearchOpts().ResourceDir.empty()) Clang->getHeaderSearchOpts().ResourceDir = CompilerInvocation::GetResourcesPath(Argv0, GetExecutablePathVP); // Create the compilers actual diagnostics engine. Clang->createDiagnostics(); if (!Clang->hasDiagnostics()) { FailingCommands.push_back(std::make_pair(1, &J)); return; } LocalOutputFilename = ""; // Let the filename be created from options or output file name. std::string TemplightOutFile = TemplightAction::CreateOutputFilename( Clang.get(), "", InstProfiler, OutputToStdOut, MemoryProfile); // Check if templight filename is in a temporary path: llvm::SmallString<128> TDir; llvm::sys::path::system_temp_directory(true, TDir); if ( TDir.equals(llvm::sys::path::parent_path(llvm::StringRef(TemplightOutFile))) ) { C.addTempFile(TemplightOutFile.c_str()); TempOutputFiles.push_back(TemplightOutFile); } // Execute the frontend actions. Res = ExecuteTemplightInvocation(Clang.get()); if(Res) FailingCommands.push_back(std::make_pair(Res, &J)); } else { const Command *FailingCommand = nullptr; if (int Res = C.ExecuteCommand(J, FailingCommand)) FailingCommands.push_back(std::make_pair(Res, FailingCommand)); } }
void CTransportCAI::GiveCommandReal(const Command& c, bool fromSynced) { if (!(c.options & SHIFT_KEY) && nonQueingCommands.find(c.GetID()) == nonQueingCommands.end()){ SetTransportee(NULL); } return CMobileCAI::GiveCommandReal(c, fromSynced); }
bool ChassicCommandInterpreter::handle(const Command& command) { if(command.compareModule("CH")) { // CHASSIC if(command.compareAction("MV")) { // MOVE if(command.compareArgument1("FW")) { // FORWARD _platform.move(rover::chassic::MOVE_FORWARD, getMotorSpeed(command, rover::chassic::SPEED_75)); return true; } if(command.compareArgument1("BW")) { // FORWARD _platform.move(rover::chassic::MOVE_BACKWARD, getMotorSpeed(command, rover::chassic::SPEED_75)); return true; } rover::telemetry::Logger::debug("Wrong CHASSIC MOVE command"); } else if(command.compareAction("RT")) { // ROTATE if(command.compareArgument1("TL")) { // LEFT _platform.rotate(rover::chassic::ROTATE_LEFT, getMotorSpeed(command, rover::chassic::SPEED_75)); return true; } if(command.compareArgument1("TR")) { // FORWARD _platform.rotate(rover::chassic::ROTATE_RIGHT, getMotorSpeed(command, rover::chassic::SPEED_75)); return true; } rover::telemetry::Logger::debug("Wrong CHASSIC ROTATE command"); } else if(command.compareAction("ST")) { // STOP _platform.stop(); return true; } else if(command.compareAction("BR")) { // BRAKE _platform.brake(); return true; } else { rover::telemetry::Logger::debug("Wrong CHASSIC command"); } return false; } }
void CTransportCAI::UnloadLand(Command& c) { //default unload CTransportUnit* transport = static_cast<CTransportUnit*>(owner); if (inCommand) { if (!owner->script->IsBusy()) { FinishCommand(); } } else { const std::list<CTransportUnit::TransportedUnit>& transList = transport->GetTransportedUnits(); if (transList.empty()) { FinishCommand(); return; } float3 pos = c.GetPos(0); if (goalPos.SqDistance2D(pos) > 400) { SetGoal(pos, owner->pos); } CUnit* unit = NULL; if (c.params.size() < 4) { unit = transList.front().unit; } else { const int unitID = (int)c.params[3]; std::list<CTransportUnit::TransportedUnit>::const_iterator it; for (it = transList.begin(); it != transList.end(); ++it) { CUnit* carried = it->unit; if (unitID == carried->id) { unit = carried; break; } } if (unit == NULL) { FinishCommand(); return; } } if (pos.SqDistance2D(owner->pos) < Square(owner->unitDef->loadingRadius * 0.9f)) { CHoverAirMoveType* am = dynamic_cast<CHoverAirMoveType*>(owner->moveType); pos.y = static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeight(pos, unit); if (am != NULL) { // handle air transports differently SetGoal(pos, owner->pos); am->SetWantedAltitude(pos.y - ground->GetHeightAboveWater(pos.x, pos.z)); float unloadHeading = static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeading(unit); am->ForceHeading(unloadHeading); am->maxDrift = 1; if ((owner->pos.SqDistance(pos) < 64) && (owner->updir.dot(UpVector) > 0.99f) && math::fabs(owner->heading - unloadHeading) < AIRTRANSPORT_DOCKING_ANGLE) { pos.y -= unit->radius; if (!SpotIsClearIgnoreSelf(pos, unit)) { // chosen spot is no longer clear to land, choose a new one // if a new spot cannot be found, don't unload at all float3 newpos; if (FindEmptySpot(pos, std::max(16.0f * SQUARE_SIZE, unit->radius * 4.0f), unit->radius, newpos, unit)) { c.SetPos(0, newpos); SetGoal(newpos + UpVector * unit->model->height, owner->pos); return; } } else { transport->DetachUnit(unit); if (transport->GetTransportedUnits().empty()) { am->dontLand = false; owner->script->EndTransport(); } } const float3 fix = owner->pos + owner->frontdir * 20; SetGoal(fix, owner->pos); // move the transport away slightly FinishCommand(); } } else { inCommand = true; StopMove(); owner->script->TransportDrop(unit, pos); } } } }
void SetPointAbility::invoke(Unit &to_modify, const Command &cmd, bool) { auto &build_attr = to_modify.get_attribute<attr_type::building>(); build_attr.gather_point = cmd.position(); }
void Command::help() { // Build command name string commandName = _name; Command *command = this->parentCommand(); while (command) { commandName = command->name() + " " + commandName; command = command->parentCommand(); } // Build usage int offset = 0; if (_options.size() > 0) { vector<string> elements; // Add optinos for (int i = 0; i < _options.size(); i++) { Option option = _options[i]; string element = "["; if (option.shortName() != "") { element += "-" + option.shortName(); if (option.longName() != "") { element += "|--" + option.longName(); } } else { element += "--" + option.longName(); } switch (option.argumentType()) { case Option::ArgumentType::Required: element += " <" + option.argumentName() + ">"; break; case Option::ArgumentType::Optional: element += " [<" + option.argumentName() + ">]"; break; case Option::ArgumentType::NoArgument: break; } element += "]"; elements.push_back(element); } // Calculate width int maximumLineWidth = 80; string header = "usage: " + commandName; offset = min(20, (int)header.size()); // Show usage int i = 0; string line = header; while (i < elements.size()) { if (line.size() + 1 + elements[i].size() > maximumLineWidth) { cout << line << endl; line = ""; for (int j = 0; j < offset; j++) { line += " "; } } line += " " + elements[i]; i++; } if (line != "") { cout << line << endl; } } else { cout << "usage: " + commandName; } // Check whether the command has subcommands if (_subcommands.size() == 0) { cout << endl; return; } // Show command usage for (int i = 0; i < offset; i++) { cout << " "; } cout << " <command> [<args>]" << endl; // Get max command length vector<Command> subcommands = _subcommands; int maximumCommandLength = 0; for (auto it = subcommands.begin(); it != subcommands.end(); ++it) { if ((int)it->name().size() > maximumCommandLength) { maximumCommandLength = (int)it->name().size(); } } // Show commands cout << endl << "commands:" << endl; for (auto it = subcommands.begin(); it != subcommands.end(); ++it) { cout << " " << it->name(); for (int i = 0; i < (maximumCommandLength + 3 - (int)it->name().size()); i++) { cout << " "; } cout << it->description() << endl; } }
bool SetPointAbility::can_invoke(Unit &to_modify, const Command &cmd) { return cmd.has_position() && to_modify.has_attribute(attr_type::building); }
bool LocalNode::_cmdConnect( Command& command ) { EQASSERT( !command.getNode().isValid( )); EQASSERT( _inReceiverThread( )); const NodeConnectPacket* packet = command.get< NodeConnectPacket >(); ConnectionPtr connection = _incoming.getConnection(); const NodeID& nodeID = packet->nodeID; EQVERB << "handle connect " << packet << std::endl; EQASSERT( nodeID != _id ); EQASSERT( _connectionNodes.find( connection ) == _connectionNodes.end( )); NodePtr remoteNode; // No locking needed, only recv thread modifies NodeHash::const_iterator i = _nodes->find( nodeID ); if( i != _nodes->end( )) { remoteNode = i->second; if( remoteNode->isConnected( )) { // Node exists, probably simultaneous connect from peer EQINFO << "Already got node " << nodeID << ", refusing connect" << std::endl; // refuse connection NodeConnectReplyPacket reply( packet ); connection->send( reply, serialize( )); // NOTE: There is no close() here. The reply packet above has to be // received by the peer first, before closing the connection. _removeConnection( connection ); return true; } } // create and add connected node if( !remoteNode ) remoteNode = createNode( packet->nodeType ); std::string data = packet->nodeData; if( !remoteNode->deserialize( data )) EQWARN << "Error during node initialization" << std::endl; EQASSERTINFO( data.empty(), data ); EQASSERTINFO( remoteNode->_id == nodeID, remoteNode->_id << "!=" << nodeID ); remoteNode->_outgoing = connection; remoteNode->_state = STATE_CONNECTED; _connectionNodes[ connection ] = remoteNode; { base::ScopedMutex< base::SpinLock > mutex( _nodes ); _nodes.data[ remoteNode->_id ] = remoteNode; } EQVERB << "Added node " << nodeID << std::endl; // send our information as reply NodeConnectReplyPacket reply( packet ); reply.nodeID = _id; reply.nodeType = getType(); connection->send( reply, serialize( )); return true; }
void CBuilderCAI::ExecuteReclaim(Command& c) { // not all builders are reclaim-capable by default if (!owner->unitDef->canReclaim) return; if (c.params.size() == 1 || c.params.size() == 5) { const int signedId = (int) c.params[0]; if (signedId < 0) { LOG_L(L_WARNING, "Trying to reclaim unit or feature with id < 0 (%i), aborting.", signedId); return; } const unsigned int uid = signedId; const bool checkForBetterTarget = ((++randomCounter % 5) == 0); if (checkForBetterTarget && (c.options & INTERNAL_ORDER) && (c.params.size() >= 5)) { // regular check if there is a closer reclaim target CSolidObject* obj; if (uid >= unitHandler->MaxUnits()) { obj = featureHandler->GetFeature(uid - unitHandler->MaxUnits()); } else { obj = unitHandler->GetUnit(uid); } if (obj) { const float3& pos = c.GetPos(1); const float radius = c.params[4]; const float curdist = pos.SqDistance2D(obj->pos); const bool recUnits = !!(c.options & META_KEY); const bool recEnemyOnly = (c.options & META_KEY) && (c.options & CONTROL_KEY); const bool recSpecial = !!(c.options & CONTROL_KEY); ReclaimOption recopt = REC_NORESCHECK; if (recUnits) recopt |= REC_UNITS; if (recEnemyOnly) recopt |= REC_ENEMYONLY; if (recSpecial) recopt |= REC_SPECIAL; const int rid = FindReclaimTarget(pos, radius, c.options, recopt, curdist); if ((rid > 0) && (rid != uid)) { StopMoveAndFinishCommand(); RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); return; } } } if (uid >= unitHandler->MaxUnits()) { // reclaim feature CFeature* feature = featureHandler->GetFeature(uid - unitHandler->MaxUnits()); if (feature != NULL) { bool featureBeingResurrected = IsFeatureBeingResurrected(feature->id, owner); featureBeingResurrected &= (c.options & INTERNAL_ORDER) && !(c.options & CONTROL_KEY); if (featureBeingResurrected || !ReclaimObject(feature)) { StopMoveAndFinishCommand(); RemoveUnitFromFeatureReclaimers(owner); } else { AddUnitToFeatureReclaimers(owner); } } else { StopMoveAndFinishCommand(); RemoveUnitFromFeatureReclaimers(owner); } RemoveUnitFromReclaimers(owner); } else { // reclaim unit CUnit* unit = unitHandler->GetUnit(uid); if (unit != NULL && c.params.size() == 5) { const float3& pos = c.GetPos(1); const float radius = c.params[4] + 100.0f; // do not walk too far outside reclaim area const bool outOfReclaimRange = (pos.SqDistance2D(unit->pos) > radius * radius) || (ownerBuilder->curReclaim == unit && unit->IsMoving() && !IsInBuildRange(unit)); const bool busyAlliedBuilder = unit->unitDef->builder && !unit->commandAI->commandQue.empty() && teamHandler->Ally(owner->allyteam, unit->allyteam); if (outOfReclaimRange || busyAlliedBuilder) { StopMoveAndFinishCommand(); RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); return; } } if (unit != NULL && unit != owner && unit->unitDef->reclaimable && UpdateTargetLostTimer(unit->id) && unit->AllowedReclaim(owner)) { if (!ReclaimObject(unit)) { StopMoveAndFinishCommand(); } else { AddUnitToReclaimers(owner); } } else { RemoveUnitFromReclaimers(owner); StopMoveAndFinishCommand(); } RemoveUnitFromFeatureReclaimers(owner); } } else if (c.params.size() == 4) { // area reclaim const float3 pos = c.GetPos(0); const float radius = c.params[3]; const bool recUnits = !!(c.options & META_KEY); const bool recEnemyOnly = (c.options & META_KEY) && (c.options & CONTROL_KEY); const bool recSpecial = !!(c.options & CONTROL_KEY); RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); ownerBuilder->StopBuild(); ReclaimOption recopt = REC_NORESCHECK; if (recUnits) recopt |= REC_UNITS; if (recEnemyOnly) recopt |= REC_ENEMYONLY; if (recSpecial) recopt |= REC_SPECIAL; if (FindReclaimTargetAndReclaim(pos, radius, c.options, recopt)) { inCommand = false; SlowUpdate(); return; } if(!(c.options & ALT_KEY)){ StopMoveAndFinishCommand(); } } else { // wrong number of parameters RemoveUnitFromReclaimers(owner); RemoveUnitFromFeatureReclaimers(owner); StopMoveAndFinishCommand(); } }