void CSelectedUnitsAI::GiveCommandNet(Command &c, int player)
{
    const vector<int>& netSelected = selectedUnits.netSelected[player];
    vector<int>::const_iterator ui;

    int nbrOfSelectedUnits = netSelected.size();

    if (nbrOfSelectedUnits < 1) {
        // no units to command
    }
    else if ((c.id == CMD_ATTACK) &&
             ((c.params.size() == 6) ||
              ((c.params.size() == 4) && (c.params[3] > 0.001f)))) {
        SelectAttack(c, player);
    }
    else if (nbrOfSelectedUnits == 1) {
        // a single unit selected
        CUnit* unit = uh->units[*netSelected.begin()];
        if(unit) {
            unit->commandAI->GiveCommand(c, false);
            if (MayRequireSetMaxSpeedCommand(c)) {
                AddUnitSetMaxSpeedCommand(unit, c.options);
            }
            if (c.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 (((c.id == CMD_MOVE) || (c.id == CMD_FIGHT)) && (c.params.size() == 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 = uh->units[*ui];
            if(unit) {
                if (groupSpeed) {
                    AddGroupSetMaxSpeedCommand(unit, c.options);
                } else {
                    AddUnitSetMaxSpeedCommand(unit, c.options);
                }
            }
        }
    }
    else if ((c.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.params[0], c.params[1], c.params[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 + (sqrt((float)nbrOfSelectedUnits) * 32.0f);

        // push back some extra params so it confer with a front move
        c.params.push_back(pos.x + (sideDir.x * length));
        c.params.push_back(pos.y + (sideDir.y * length));
        c.params.push_back(pos.z + (sideDir.z * length));

        MakeFrontMove(&c, player);

        const bool groupSpeed = !!(c.options & CONTROL_KEY);
        for(ui = netSelected.begin(); ui != netSelected.end(); ++ui) {
            CUnit* unit = uh->units[*ui];
            if(unit) {
                if (groupSpeed) {
                    AddGroupSetMaxSpeedCommand(unit, c.options);
                } else {
                    AddUnitSetMaxSpeedCommand(unit, c.options);
                }
            }
        }
    }
    else if ((c.options & CONTROL_KEY) &&
             ((c.id == CMD_MOVE) || (c.id == CMD_PATROL) || (c.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 = uh->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 = uh->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 (c.id == CMD_WAIT) {
            if (player == gu->myPlayerNum) {
                waitCommandsAI.AcknowledgeCommand(c);
            }
        }
    }
}
/*
Group-AI.
Processing commands given to selected group.
*/
void CSelectedUnitsAI::GiveCommandNet(Command &c,int player) {
	int nbrOfSelectedUnits = selectedUnits.netSelected[player].size();

	if(nbrOfSelectedUnits < 1)			//No units to command.
		return;

	if(nbrOfSelectedUnits == 1) {	//Only one single unit selected.
		CUnit* unit=uh->units[*selectedUnits.netSelected[player].begin()];
		if(unit)
			unit->commandAI->GiveCommand(c);
		return;
	}


	if(c.id==CMD_MOVE && c.params.size()==6){
		MakeFrontMove(&c,player);

	} else if(c.id == CMD_MOVE && (c.options & ALT_KEY)) {
		CalculateGroupData(player);
		
		float3 pos(c.params[0],c.params[1],c.params[2]);
		float3 frontdir=pos-centerCoor;										//use the vector from the middle of group to new pos as forward dir
		frontdir.y=0;
		frontdir.Normalize();

		float3 sideDir=frontdir.cross(UpVector);

		float length=100+sqrtf(nbrOfSelectedUnits)*32;		//calculate so that the units form in an aproximate square

		c.params.push_back(pos.x+sideDir.x*length);				//push back some extra params so it confer with a front move
		c.params.push_back(pos.y+sideDir.y*length);
		c.params.push_back(pos.z+sideDir.z*length);

		MakeFrontMove(&c,player);
		
	} else if((c.id == CMD_MOVE || c.id == CMD_PATROL)&& (c.options & CONTROL_KEY)) {
		CalculateGroupData(player);
		for(vector<int>::iterator ui = selectedUnits.netSelected[player].begin(); ui != selectedUnits.netSelected[player].end(); ++ui) {
			CUnit* unit=uh->units[*ui];
			if(unit){
				//Sets the wanted speed of this unit (and the group).
				Command uc;
				uc.id = CMD_SET_WANTED_MAX_SPEED;
				uc.options = c.options;
				if(c.options & ALT_KEY)		//ALT overrides group-speed-setting.
					uc.params.push_back(unit->moveType->maxSpeed);
				else
					uc.params.push_back(minMaxSpeed);
				unit->commandAI->GiveCommand(uc);
				//Modifying the destination relative to the center of the group.
				uc = c;
				uc.params[CMDPARAM_MOVE_X] += unit->midPos.x - centerCoor.x;
				uc.params[CMDPARAM_MOVE_Y] += unit->midPos.y - centerCoor.y;
				uc.params[CMDPARAM_MOVE_Z] += unit->midPos.z - centerCoor.z;
				unit->commandAI->GiveCommand(uc);
			}
		}
	} else {
		for(vector<int>::iterator ui = selectedUnits.netSelected[player].begin(); ui != selectedUnits.netSelected[player].end(); ++ui) {
			CUnit* unit=uh->units[*ui];
			if(unit){
				unit->commandAI->GiveCommand(c);
			}
		}
	}
}