From: <geo...@us...> - 2009-12-29 17:46:33
|
Revision: 3301 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=3301&view=rev Author: geoffthemedio Date: 2009-12-29 17:46:26 +0000 (Tue, 29 Dec 2009) Log Message: ----------- -Fixed issue where systems containing enemy fleets that had been created on the previous turn by issuing new fleet orders would become basically visible to players because those fleets were created with 0 stealth by default and visibility was updated and stored before the fleets' stealth meters were updated and acted on by effects from (for example) ship parts and hulls. New fleets created with NewFleetOrder now have stealth set to METER_MAX and then meter effects are executed after orders are executed on the server during turn processing. These two changes are probably redundant for purposes of this bug, but don't hurt and might prevent future issues. -Removed visibility turn update from visibility update function and added back manual calls to turn update function. This lets the times during turn updates when visibility turns are updated be controlled more precisely. -Added explicit updates of visibility turn history back to turn processing. This is not every time visibility is updated, as some history updates would be redundant, despite the actual visibility update still being useful for turn processing. -Commented out some debug output. -Tweaked the empire code that determine supply unobstructed systems in an attempt to fix issue where supply is being shown as delivered to systems it shouldn't: those containing enemy fleets. I'm not sure if supply is actually being delivered to these systems during server turn processing, or why it shows up as receiving supply on the client if there is a difference between what's shown and what actually happens. The new code is probably a bit cleaner regardless so is being committed. Modified Paths: -------------- trunk/FreeOrion/Empire/Empire.cpp trunk/FreeOrion/server/ServerApp.cpp trunk/FreeOrion/universe/Fleet.cpp trunk/FreeOrion/universe/Ship.cpp trunk/FreeOrion/universe/Universe.cpp trunk/FreeOrion/util/Order.cpp Modified: trunk/FreeOrion/Empire/Empire.cpp =================================================================== --- trunk/FreeOrion/Empire/Empire.cpp 2009-12-27 07:37:57 UTC (rev 3300) +++ trunk/FreeOrion/Empire/Empire.cpp 2009-12-29 17:46:26 UTC (rev 3301) @@ -1304,45 +1304,35 @@ { m_supply_unobstructed_systems.clear(); - // find "unobstructed" systems that can propegate fleet supply routes - const std::vector<System*> all_systems = GetMainObjectMap().FindObjects<System>(); + // get all fleets, or just fleets visible to this client's empire + const std::vector<Fleet*> fleets = GetUniverse().Objects().FindObjects<Fleet>(); - for (std::vector<System*>::const_iterator it = all_systems.begin(); it != all_systems.end(); ++it) { - const System* system = *it; - int system_id = system->ID(); + // find systems that contain friendly fleets or objects that can block supply + std::set<int> systems_containing_friendly_fleets; + std::set<int> systems_containing_obstructing_objects; + for (std::vector<Fleet*>::const_iterator it = fleets.begin(); it != fleets.end(); ++it) { + const Fleet* fleet = *it; + int system_id = fleet->SystemID(); + if (system_id == UniverseObject::INVALID_OBJECT_ID || m_supply_unobstructed_systems.find(system_id) == m_supply_unobstructed_systems.end()) + continue; // not in a potential supply unobstructed systema + else if (fleet->OwnedBy(m_id)) + systems_containing_friendly_fleets.insert(system_id); + else // owned by another empire, or has no owners + systems_containing_obstructing_objects.insert(system_id); + } - // to be unobstructed, systems must be known to this empire - if (known_systems.find(system_id) == known_systems.end()) - continue; - - //std::cout << "... system " << system->Name() << " is explored" << std::endl; - - // ...and ( contain a friendly fleet *or* not contain a hostile fleet ) - bool blocked = false; - std::vector<int> fleet_ids = system->FindObjectIDs<Fleet>(); - for (std::vector<int>::const_iterator it = fleet_ids.begin(); it != fleet_ids.end(); ++it) { - const Fleet* fleet = GetObject<Fleet>(*it); - if (!fleet) { - Logger().errorStream() << "Empire::UpdateSupplyUnobstructedSystems couldn't get fleet with id " << *it; - continue; - } - - // check if this empire owns this fleet. - if (fleet->OwnedBy(m_id)) { - // this empire owns this fleet. the system is unobstructed regardless of what else is here - blocked = false; - break; - } else { - // this empire doesn't own this fleet. the system might be obstructed, but need to check the - // rest of the fleets to be sure. TODO: deal with other affiliations, like neutral empires or - // allies of this empire - blocked = true; - } - } - if (!blocked) { - m_supply_unobstructed_systems.insert(system_id); - //std::cout << " ... unobstructed system: " << system_id << std::endl; - } + // check each potential supplyable system for whether it can propegate + // supply. having no obstructing objects or having a friendly fleet means + // it can + for (std::set<int>::const_iterator known_systems_it = known_systems.begin(); known_systems_it != known_systems.end(); ++known_systems_it) { + int sys_id = *known_systems_it; + if (systems_containing_friendly_fleets.find(sys_id) != systems_containing_friendly_fleets.end()) + m_supply_unobstructed_systems.insert(sys_id); + else if (systems_containing_obstructing_objects.find(sys_id) == systems_containing_obstructing_objects.end()) + m_supply_unobstructed_systems.insert(sys_id); + // otherwise, system contains no friendly fleets but does contain an + // unfriendly fleet, so it is obstructed, so isn't included in the + // unobstructed systems set } } @@ -2313,11 +2303,24 @@ m_production_progress[i] -= item_cost * build_turns; switch (m_production_queue[i].item.build_type) { case BT_BUILDING: { - Planet* planet = objects.Object<Planet>(m_production_queue[i].location); - assert(planet); + int planet_id = m_production_queue[i].location; + Planet* planet = objects.Object<Planet>(planet_id); + if (!planet) { + Logger().errorStream() << "Couldn't get planet with id " << planet_id << " on which to create building"; + continue; + } + Building* building = new Building(m_id, m_production_queue[i].item.name, planet->ID()); + // start with max stealth to ensure new building won't be + // visisble to other empires on first turn if it shouldn't be. + // current value will be clamped to max meter value after + // effects are applied + building->GetMeter(METER_STEALTH)->SetCurrent(Meter::METER_MAX); + int building_id = universe.Insert(building); + planet->AddBuilding(building_id); + SitRepEntry* entry = CreateBuildingBuiltSitRep(m_production_queue[i].item.name, planet->ID()); AddSitRepEntry(entry); //Logger().debugStream() << "New Building created on turn: " << building->CreationTurn(); @@ -2334,6 +2337,12 @@ // create new fleet with new ship Fleet* fleet = new Fleet("", system->X(), system->Y(), m_id); + // start with max stealth to ensure new fleet won't be visisble + // to other empires on first turn if it shouldn't be. current + // value will be clamped to max meter value after effects are + // applied + fleet->GetMeter(METER_STEALTH)->SetCurrent(Meter::METER_MAX); + int fleet_id = universe.Insert(fleet); system->Insert(fleet); @@ -2341,15 +2350,15 @@ // add ship Ship* ship = new Ship(m_id, m_production_queue[i].item.design_id); - // start with with maxed meters. current values will be clamped to max value - // after effects are applied to set that max value appropriately + // start with with maxed meters. current values will be + // clamped to max value after effects are applied to set that + // max value appropriately ship->GetMeter(METER_FUEL)->SetCurrent(Meter::METER_MAX); ship->GetMeter(METER_SHIELD)->SetCurrent(Meter::METER_MAX); ship->GetMeter(METER_DETECTION)->SetCurrent(Meter::METER_MAX); ship->GetMeter(METER_STEALTH)->SetCurrent(Meter::METER_MAX); ship->GetMeter(METER_HEALTH)->SetCurrent(Meter::METER_MAX); - int ship_id = universe.Insert(ship); ship->Rename(NewShipName()); Modified: trunk/FreeOrion/server/ServerApp.cpp =================================================================== --- trunk/FreeOrion/server/ServerApp.cpp 2009-12-27 07:37:57 UTC (rev 3300) +++ trunk/FreeOrion/server/ServerApp.cpp 2009-12-29 17:46:26 UTC (rev 3301) @@ -536,14 +536,21 @@ EmpireManager& empires = Empires(); ObjectMap& objects = m_universe.Objects(); + // inform players of impending order execution + for (std::map<int, OrderSet*>::iterator it = m_turn_sequence.begin(); it != m_turn_sequence.end(); ++it) { + // broadcast UI message to all players + for (ServerNetworking::const_established_iterator player_it = m_networking.established_begin(); player_it != m_networking.established_end(); ++player_it) { + (*player_it)->SendMessage(TurnProgressMessage((*player_it)->ID(), Message::PROCESSING_ORDERS, it->first)); + } + } + Logger().debugStream() << "ServerApp::ProcessTurns executing orders"; - // Now all orders, then process turns + // execute orders for (std::map<int, OrderSet*>::iterator it = m_turn_sequence.begin(); it != m_turn_sequence.end(); ++it) { // broadcast UI message to all players for (ServerNetworking::const_established_iterator player_it = m_networking.established_begin(); player_it != m_networking.established_end(); ++player_it) { (*player_it)->SendMessage(TurnProgressMessage((*player_it)->ID(), Message::PROCESSING_ORDERS, it->first)); } - Empire* empire = empires.Lookup(it->first); empire->ClearSitRep(); OrderSet* order_set = it->second; @@ -554,6 +561,13 @@ } } + // re-execute all meter-related effects after orders, so that new + // UniverseObjects created during order executtion (eg. new fleets) will + // have effects applied to them this turn, ensuring (eg.) new fleets will + // have the appropriate stealth level on the turn they are created. + m_universe.ApplyMeterEffectsAndUpdateMeters(); + + Logger().debugStream() << "ServerApp::ProcessTurns colonize order filtering"; // filter FleetColonizeOrder for later processing typedef std::map<int, std::vector<boost::shared_ptr<FleetColonizeOrder> > > ColonizeOrderMap; @@ -717,6 +731,7 @@ // post-movement visibility update m_universe.UpdateEmpireObjectVisibilities(); + m_universe.UpdateEmpireLatestKnownObjectsAndVisibilityTurns(); Logger().debugStream() << "ServerApp::ProcessTurns combat"; @@ -837,6 +852,7 @@ // post-combat visibility update m_universe.UpdateEmpireObjectVisibilities(); + m_universe.UpdateEmpireLatestKnownObjectsAndVisibilityTurns(); // process production and growth phase @@ -912,10 +928,6 @@ } - // post-growth visibility update - m_universe.UpdateEmpireObjectVisibilities(); - - // copy latest updated current meter values to initial current values, and // initial current values to previous values, so that clients will have // this information based on values after all changes that occured this turn @@ -949,6 +961,8 @@ ++m_current_turn; + // new turn visibility update + m_universe.UpdateEmpireObjectVisibilities(); m_universe.UpdateEmpireLatestKnownObjectsAndVisibilityTurns(); Modified: trunk/FreeOrion/universe/Fleet.cpp =================================================================== --- trunk/FreeOrion/universe/Fleet.cpp 2009-12-27 07:37:57 UTC (rev 3300) +++ trunk/FreeOrion/universe/Fleet.cpp 2009-12-29 17:46:26 UTC (rev 3301) @@ -686,7 +686,7 @@ return; } - Logger().debugStream() << "Fleet '" << this->Name() << "' adding ship: " << ship_id; + //Logger().debugStream() << "Fleet '" << this->Name() << "' adding ship: " << ship_id; if (Ship* s = GetObject<Ship>(ship_id)) { if (System* system = GetObject<System>(this->SystemID())) { system->Insert(s); Modified: trunk/FreeOrion/universe/Ship.cpp =================================================================== --- trunk/FreeOrion/universe/Ship.cpp 2009-12-27 07:37:57 UTC (rev 3300) +++ trunk/FreeOrion/universe/Ship.cpp 2009-12-29 17:46:26 UTC (rev 3301) @@ -258,7 +258,7 @@ // if ship is being moved away from its fleet, remove from the fleet. otherwise, keep ship in fleet. if (Fleet* fleet = GetObject<Fleet>(this->FleetID())) { - Logger().debugStream() << "Ship::MoveTo removing " << this->ID() << " from fleet " << fleet->Name(); + //Logger().debugStream() << "Ship::MoveTo removing " << this->ID() << " from fleet " << fleet->Name(); fleet->RemoveShip(this->ID()); } } Modified: trunk/FreeOrion/universe/Universe.cpp =================================================================== --- trunk/FreeOrion/universe/Universe.cpp 2009-12-27 07:37:57 UTC (rev 3300) +++ trunk/FreeOrion/universe/Universe.cpp 2009-12-29 17:46:26 UTC (rev 3301) @@ -52,15 +52,14 @@ } } - namespace { - const bool ENABLE_VISIBILITY_EMPIRE_MEMORY = true; // toggles using memory with visibility, so that empires retain knowledge of objects viewed on previous turns + const bool ENABLE_VISIBILITY_EMPIRE_MEMORY = true; // toggles using memory with visibility, so that empires retain knowledge of objects viewed on previous turns } namespace { struct vertex_system_id_t {typedef boost::vertex_property_tag kind;}; ///< a system graph property map type - const double OFFROAD_SLOWDOWN_FACTOR = 1000000000.0; // the factor by which non-starlane travel is slower than starlane travel + const double OFFROAD_SLOWDOWN_FACTOR = 1000000000.0; // the factor by which non-starlane travel is slower than starlane travel DataTableMap& UniverseDataTables() { @@ -1527,6 +1526,8 @@ if (!target) continue; + //Logger().debugStream() << " ... considering stealthy object " << target->Name() << " (" << target->ID() << ")"; + //// check if stealthy object is a fleet. if so, don't bother //// setting its visibility now, but later get visibility by //// propegating from ships in fleet @@ -1569,6 +1570,11 @@ if (dist2 <= detect_range * detect_range) target_visibility_to_detector = VIS_PARTIAL_VISIBILITY; + + if (target_visibility_to_detector <= VIS_NO_VISIBILITY) + continue; + + // Note that owning an object grants FULL visibility in the containing loop @@ -1598,14 +1604,20 @@ const Fleet* container_fleet = universe_object_cast<const Fleet*>(container_obj); + //Logger().debugStream() << "Container object " << container_obj->Name() << " (" << container_obj->ID() << ")"; + // for each contained object within container for (std::vector<int>::iterator contained_obj_it = contained_objects.begin(); contained_obj_it != contained_objects.end(); ++contained_obj_it) { int contained_obj_id = *contained_obj_it; + //Logger().debugStream() << " ... contained object (" << contained_obj_id << ")"; + // for each empire with a visibility map for (EmpireObjectVisibilityMap::iterator empire_it = m_empire_object_visibility.begin(); empire_it != m_empire_object_visibility.end(); ++empire_it) { ObjectVisibilityMap& vis_map = empire_it->second; + //Logger().debugStream() << " ... ... empire id " << empire_it->first; + // find current empire's visibility entry for current container object ObjectVisibilityMap::iterator container_vis_it = vis_map.find(container_obj_id); // if no entry yet stored for this object, default to not visible @@ -1639,9 +1651,11 @@ Visibility contained_obj_vis = contained_vis_it->second; // no need to propegate if contained object isn't visible to current empire - if (contained_obj_vis == VIS_NO_VISIBILITY) + if (contained_obj_vis <= VIS_NO_VISIBILITY) continue; + //Logger().debugStream() << " ... ... contained object vis: " << contained_obj_vis; + // contained object is at least basically visible. // container should be at least partially visible, but don't // want to decrease visibility of container if it is already @@ -1651,6 +1665,10 @@ // special case for fleets: grant partial visibility if // visible contained object is partially or better visible + // this way fleet ownership is known to players who can + // see ships with partial or better visibility (and thus + // know the owner of the ships and thus should know the + // owners of the fleet) if (container_fleet && contained_obj_vis >= VIS_PARTIAL_VISIBILITY && container_vis_it->second < VIS_PARTIAL_VISIBILITY) container_vis_it->second = VIS_PARTIAL_VISIBILITY; } @@ -1739,12 +1757,12 @@ } } } - - UpdateEmpireLatestKnownObjectsAndVisibilityTurns(); } void Universe::UpdateEmpireLatestKnownObjectsAndVisibilityTurns() { + Logger().debugStream() << "Universe::UpdateEmpireLatestKnownObjectsAndVisibilityTurns()"; + // assumes m_empire_object_visibility has been updated // for each object in universe @@ -1810,6 +1828,7 @@ vis_turn_map[VIS_BASIC_VISIBILITY] = current_turn; } } + //Logger().debugStream() << " ... Setting empire " << empire_id << " object " << full_object->Name() << " (" << object_id << ") vis " << vis << " (and higher) turn to " << current_turn; } else { Logger().errorStream() << "Universe::UpdateEmpireLatestKnownObjectsAndVisibilityTurns() found invalid visibility for object with id " << object_id << " by empire with id " << empire_id; continue; Modified: trunk/FreeOrion/util/Order.cpp =================================================================== --- trunk/FreeOrion/util/Order.cpp 2009-12-27 07:37:57 UTC (rev 3300) +++ trunk/FreeOrion/util/Order.cpp 2009-12-29 17:46:26 UTC (rev 3301) @@ -181,6 +181,7 @@ return; } fleet = new Fleet(m_fleet_name, system->X(), system->Y(), EmpireID()); + fleet->GetMeter(METER_STEALTH)->SetCurrent(Meter::METER_MAX); // an ID is provided to ensure consistancy between server and client universes universe.InsertID(fleet, m_new_id); system->Insert(fleet); |