User:Geoff the Medio/Coding

From FreeOrionWiki
< User:Geoff the Medio
Revision as of 04:16, 16 May 2005 by Geoff the Medio (Talk | contribs) (FleetColonizeOrder class header)

Jump to: navigation, search

SidePanel::ClickColoinze()

void SidePanel::PlanetPanel::ClickColonize()
{
    const Planet *planet = GetPlanet();
    int empire_id = HumanClientApp::GetApp()->EmpireID();
    std::map<int, int> pending_colonization_orders = HumanClientApp::GetApp()->PendingColonizationOrders();
    std::map<int, int>::const_iterator it = pending_colonization_orders.find(planet->ID());
    if(it == pending_colonization_orders.end()) // colonize
    {
        Ship *ship = FindColonyShip(planet->SystemID());
        if(!ship)
            throw std::runtime_error("SidePanel::PlanetPanel::ClickColonize ship not found!");
        
        Fleet *fleet = ship->GetFleet();
  	    
	    if(!fleet->Accept(StationaryFleetVisitor(*fleet->Owners().begin())))
        {
            GG::ThreeButtonDlg dlg(320,200,UserString("SP_USE_DEPARTING_COLONY_SHIPS_QUESTION"),
                                   ClientUI::FONT,ClientUI::PTS,ClientUI::WND_COLOR,ClientUI::CTRL_BORDER_COLOR,ClientUI::CTRL_COLOR,ClientUI::TEXT_COLOR,2,
                                   "Yes","No");
            dlg.Run();
            if(dlg.Result()!=0)
                return;
        }
        
        HumanClientApp::Orders().IssueOrder( new FleetColonizeOrder(empire_id, ship->ID(), planet->ID()) );
        
        if (!fleet->NumShips()) {
            HumanClientApp::Orders().IssueOrder( new DeleteFleetOrder( empire_id, fleet->ID()) );
        }
    }
    else // cancel colonization
    {
        const FleetColonizeOrder *col_order = dynamic_cast<const FleetColonizeOrder*>(HumanClientApp::Orders().ExamineOrder(it->second));
        int ship_id = col_order ? col_order->ShipID() : UniverseObject::INVALID_OBJECT_ID;
        Ship *ship = GetUniverse().Object<Ship>(ship_id);
        int fleet_id = ship->FleetID();
        
        // check if ship's fleet still exists
        Fleet *fleet = ship ? GetUniverse().Object<Fleet>(fleet_id) : NULL;
        
        if (!fleet) {
            // fleet doesn't exist, so recind order that deleted it, thus recreating it
            std::map<int, int> del_ords = HumanClientApp::GetApp()->PendingDeleteFleetOrders();
            std::map<int, int>::iterator del_ord_it = del_ords.find(fleet_id);
            if (del_ord_it != del_ords.end())
                HumanClientApp::Orders().RecindOrder(del_ord_it->second);
            
            // try again to get poitner...
            fleet = GetUniverse().Object<Fleet>(fleet_id);
        }
  
        if (!fleet)
            throw std::runtime_error("Sidepanel::ClickColonize: Fleet couldn't be recreated by recinding delete order!");
        
        // Recind colonization order, adding ship back into fleet
        HumanClientApp::Orders().RecindOrder(it->second);

        // make sure that fleet appears at a possibly opend FleetWnd      
        for (FleetWnd::FleetWndItr it = FleetWnd::FleetWndBegin(); it != FleetWnd::FleetWndEnd(); ++it) {
            FleetWnd *fleet_wnd = *it;
            if(fleet->SystemID() == fleet_wnd->SystemID()
               && !fleet_wnd->ContainsFleet(fleet->ID())) 
            {
                fleet_wnd->AddFleet(GetUniverse().Object<Fleet>(fleet->ID()));
                break;
            }
        }
    }		
}

FleetColonizeOrder class header

class FleetColonizeOrder : public Order
{
public:
    /** \name Structors */ //@{
    FleetColonizeOrder();
    FleetColonizeOrder(const GG::XMLElement& elem);
    FleetColonizeOrder(int empire, int ship, int planet);
    //@}

    /** \name Accessors */ //@{
    int   PlanetID() const  {return m_planet;} ///< returns ID of the planet to be colonized
    int   ShipID  () const  {return m_ship  ;} ///< returns ID of the ship which is colonizing the planet

    virtual void           ServerExecute() const; //< called if the server allows the colonization effort 

    virtual GG::XMLElement XMLEncode() const; ///< constructs an XMLElement for the order
    //@}

private:
    /**
     *  Preconditions:
     *     - m_fleet must be the ID of a fleet owned by issuing empire
     *     - m_planet must be the ID of an un-owned planet.
     *     - the fleet and the planet must have the same x,y coordinates
     *     - the fleet must contain a colony ship
     *
     *  Postconditions:
     *      - a colony ship will be removed from the fleet and deallocated
     *        if the fleet becomes empty it will be deallocated.
     *      - the empire issuing the order will be added to the list of owners
     *            for the planet
     *      - the planet's population will be increased
     *      - the planet will be added to the empire's list of owned planets
     *     
     */
    //< either ExecuteServerApply or ExecuteServerRevoke is called!!!
    virtual void ExecuteImpl() const;
    virtual bool UndoImpl() const;

    int m_ship;
    int m_planet;

    // these are for undoing this order only
    mutable int m_colony_fleet_id;   // the fleet from which the colony ship was taken
};

DeleteFleetOrder class header

/////////////////////////////////////////////////////
// DeleteFleetOrder
/////////////////////////////////////////////////////
/** the Order subclass that represents forming a new fleet. 
    Only one of system or position will be used to place the new fleet.*/
class DeleteFleetOrder : public Order
{
public:
    /** \name Structors */ //@{
    DeleteFleetOrder();
    DeleteFleetOrder(const GG::XMLElement& elem);
    DeleteFleetOrder(int empire, int fleet);
    //@}

    /** \name Accessors */ //@{
    int   FleetID() const   {return m_fleet;}  ///< returns ID of the fleet to be deleted

    virtual GG::XMLElement XMLEncode() const; ///< constructs an XMLElement for the order
    //@}

private:
    /**
     *  Preconditions:
     *     - m_fleet must be the ID of a fleet owned by issuing empire
     *     - m_planet must be the ID of an un-owned planet.
     *     - the fleet and the planet must have the same x,y coordinates
     *     - the fleet must contain a colony ship
     *
     *  Postconditions:
     *      - a colony ship will be removed from the fleet and deallocated
     *        if the fleet becomes empty it will be deallocated.
     *      - the empire issuing the order will be added to the list of owners
     *            for the planet
     *      - the planet's population will be increased
     *      - the planet will be added to the empire's list of owned planets
     *     
     */
    //< either ExecuteServerApply or ExecuteServerRevoke is called!!!
    virtual void ExecuteImpl() const;
    virtual bool UndoImpl() const;

    int m_fleet;
	
	// these are for undoing this order only
	mutable std::string m_fleet_name;
	mutable int m_system_id;
};


FleetColonizeOrder function definitions

FleetColonizeOrder::FleetColonizeOrder() : 
    Order(),
    m_ship(UniverseObject::INVALID_OBJECT_ID),
    m_planet(UniverseObject::INVALID_OBJECT_ID)
{
}

FleetColonizeOrder::FleetColonizeOrder(const GG::XMLElement& elem) : Order(elem.Child("Order"))
{
    if(elem.Tag() != ("FleetColonizeOrder"))
        throw std::invalid_argument("Attempted to construct FleetColonizeOrder from malformed XMLElement");
    
    m_ship   = lexical_cast<int>(elem.Child("m_ship").Text());
    m_planet = lexical_cast<int>(elem.Child("m_planet").Text());
    m_colony_fleet_id = lexical_cast<int>(elem.Child("m_colony_fleet_id").Text());
}

FleetColonizeOrder::FleetColonizeOrder(int empire, int ship, int planet) : 
    Order(empire),
    m_ship(ship),
    m_planet(planet)
{
}

void FleetColonizeOrder::ServerExecute() const
{
    Universe& universe = GetUniverse();
    universe.Delete(m_ship);
    Planet* planet = universe.Object<Planet>(m_planet);
    planet->ResetMaxMeters();
    planet->AdjustMaxMeters();
    planet->AdjustPop(INITIAL_COLONY_POP);
    planet->GetMeter(METER_FARMING)->SetCurrent(INITIAL_COLONY_POP);
    planet->GetMeter(METER_HEALTH)->SetCurrent(planet->GetMeter(METER_HEALTH)->Max());
    planet->AddOwner(EmpireID());
    if (System* system = planet->GetSystem())
        system->AddOwner(EmpireID());
}

XMLElement FleetColonizeOrder::XMLEncode() const
{
    XMLElement retval("FleetColonizeOrder");
    retval.AppendChild(Order::XMLEncode());
    retval.AppendChild(XMLElement("m_ship", lexical_cast<std::string>(m_ship)));
    retval.AppendChild(XMLElement("m_planet", lexical_cast<std::string>(m_planet)));
    retval.AppendChild(XMLElement("m_colony_fleet_id", lexical_cast<std::string>(m_colony_fleet_id)));
    return retval;
}

void FleetColonizeOrder::ExecuteImpl() const
{
    ValidateEmpireID();

    Universe& universe = GetUniverse();
    
    // look up the ship and fleet in question
    Ship* ship = universe.Object<Ship>(m_ship);
    Fleet* fleet = universe.Object<Fleet>(ship->FleetID());
   
    // ensure fleet exists
    if (!fleet)
        throw std::runtime_error("Illegal fleet id specified in fleet colonize order.");

    // verify that empire issuing order owns specified fleet
    if (!fleet->OwnedBy(EmpireID()))
        throw std::runtime_error("Empire attempted to issue colonize order to another's fleet.");

    // verify that planet exists and is un-occupied.
    Planet* planet = universe.Object<Planet>(m_planet);
    if (planet == NULL)
        throw std::runtime_error("Colonization order issued with invalid planet id.");

    if (!planet->Unowned())
        throw std::runtime_error("Colonization order issued for owned planet.");    

    // verify that planet is in same system as the fleet
    if (planet->SystemID() != fleet->SystemID() ||
        planet->SystemID() == UniverseObject::INVALID_OBJECT_ID) {
        throw std::runtime_error("Fleet specified in colonization order is not in "
                                 "specified system.");
    }

    planet->SetIsAboutToBeColonized(true);

    m_colony_fleet_id = fleet->ID(); // record the fleet in which the colony ship started

    // Remove colony ship from fleet;
    fleet->RemoveShip(m_ship);
}

bool FleetColonizeOrder::UndoImpl() const
{
    // Note that this function does double duty: it serves as a normal client-side undo, but must also
    // serve as a server-side undo, when more than one empire tries to colonize the same planet at the
    // same time.

    Universe& universe = GetUniverse();
    
    Fleet* fleet = universe.Object<Fleet>(m_colony_fleet_id);
    Planet* planet = universe.Object<Planet>(m_planet);

    planet->SetIsAboutToBeColonized(false);
    
    Ship* ship = universe.Object<Ship>(m_ship);

    // if the fleet from which the colony ship came no longer exists or has moved, make a new one	
    if (!fleet || fleet->SystemID() != ship->SystemID()) {
        System* system = planet->GetSystem();
        fleet = new Fleet("Colony Fleet", system->X(), system->Y(), EmpireID());
        universe.Insert(fleet);
        fleet->AddShip(ship->ID());
        system->Insert(fleet);
    } else {
        fleet->AddShip(ship->ID());
    }

    return true;
}

DeleteFleetOrder function definitions

////////////////////////////////////////////////
// DeleteFleetOrder
////////////////////////////////////////////////
DeleteFleetOrder::DeleteFleetOrder() : 
    Order(),
    m_fleet(-1)
{
}

DeleteFleetOrder::DeleteFleetOrder(const GG::XMLElement& elem):
    Order(elem.Child("Order"))
{
    if(elem.Tag() != ("DeleteFleetOrder"))
        throw std::invalid_argument("Attempted to construct DeleteFleetOrder from malformed XMLElement");

    m_fleet = lexical_cast<int>(elem.Child("m_fleet").Text());
}

DeleteFleetOrder::DeleteFleetOrder(int empire, int fleet) : 
    Order(empire),
    m_fleet(fleet)
{
}

GG::XMLElement DeleteFleetOrder::XMLEncode() const
{
    XMLElement retval("DeleteFleetOrder");
    retval.AppendChild(Order::XMLEncode());
    retval.AppendChild(XMLElement("m_fleet", lexical_cast<std::string>(m_fleet)));
    return retval;
}

void DeleteFleetOrder::ExecuteImpl() const
{
    ValidateEmpireID();

    Fleet* fleet = GetUniverse().Object<Fleet>(FleetID());

    if(!fleet)
        throw std::runtime_error("Illegal fleet id specified in fleet colonize order.");

    if (!fleet->OwnedBy(EmpireID()))
        throw std::runtime_error("Empire attempted to issue deletion order to another's fleet.");

    if (fleet->NumShips())
        throw std::runtime_error("Attempted to delete an unempty fleet.");

    // store info so as to be able to recind order
	m_system_id = fleet->GetSystem()->ID();
	m_fleet_name = fleet->Name();

	GetUniverse().Delete(FleetID());
}

bool DeleteFleetOrder::UndoImpl() const
{
    Universe& universe = GetUniverse();
    System* system = universe.Object<System>(m_system_id);
    
    Fleet *fleet = new Fleet(m_fleet_name, system->X(), system->Y(), EmpireID());
           
    universe.InsertID(fleet, m_fleet);
    system->Insert(fleet);

    return true;
}