Skip to content

Commit

Permalink
Merge commit '42cc7df' into ppa
Browse files Browse the repository at this point in the history
  • Loading branch information
o01eg committed Oct 22, 2024
2 parents f841b22 + 42cc7df commit 651cd50
Show file tree
Hide file tree
Showing 14 changed files with 420 additions and 116 deletions.
237 changes: 205 additions & 32 deletions Empire/Empire.cpp

Large diffs are not rendered by default.

57 changes: 50 additions & 7 deletions Empire/Empire.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ class FO_COMMON_API Empire final {
* is determined in Empire::UpdateSupplyUnobstructedSystems(). */
[[nodiscard]] bool PreservedLaneTravel(int start_system_id, int dest_system_id) const;

using IntSet = boost::container::flat_set<int>;
struct LaneEndpoints {
int start = INVALID_OBJECT_ID;
int end = INVALID_OBJECT_ID;
Expand All @@ -200,6 +199,8 @@ class FO_COMMON_API Empire final {
};
using LaneSet = boost::container::flat_set<LaneEndpoints>;

using IntSet = boost::container::flat_set<int>;

[[nodiscard]] IntSet ExploredSystems() const; ///< ids of systems that this empire has explored
[[nodiscard]] int TurnSystemExplored(int system_id) const;
[[nodiscard]] LaneSet KnownStarlanes(const Universe& universe) const; ///< map from system id (start) to set of system ids (endpoints) of all starlanes known to this empire
Expand Down Expand Up @@ -522,6 +523,24 @@ class FO_COMMON_API Empire final {
std::map<std::string, int> m_policy_adoption_current_duration; ///< how many turns each currently-adopted policy has been adopted since it was last adopted. somewhat redundant with adoption_turn in AdoptionInfo, but seems necessary to avoid off-by-one issues between client and server
std::set<std::string, std::less<>> m_available_policies; ///< names of unlocked policies

public:
// prepare policy info to serialize for various recipient empires
void PrepPolicyInfoForSerialization(const ScriptingContext& context);

private:
std::map<int, decltype(m_adopted_policies)> m_adopted_policies_to_serialize_for_empires;
std::map<int, decltype(m_initial_adopted_policies)> m_initial_adopted_policies_to_serialize_for_empires;
std::map<int, decltype(m_policy_adoption_total_duration)> m_policy_adoption_total_duration_to_serialize_for_empires;
std::map<int, decltype(m_policy_adoption_current_duration)> m_policy_adoption_current_duration_to_serialize_for_empires;
std::map<int, decltype(m_available_policies)> m_available_policies_to_serialize_for_empires;

const decltype(m_adopted_policies)& GetAdoptedPoliciesToSerialize(int encoding_empire) const;
const decltype(m_initial_adopted_policies)& GetInitialPoliciesToSerialize(int encoding_empire) const;
const decltype(m_policy_adoption_total_duration)& GetAdoptionTotalDurationsToSerialize(int encoding_empire) const;
const decltype(m_policy_adoption_current_duration)& GetAdoptionCurrentDurationsToSerialize(int encoding_empire) const;
const decltype(m_available_policies)& GetAvailablePoliciesToSerialize(int encoding_empire) const;


using StringFlatSet = boost::container::flat_set<std::string, std::less<>>;
using StringIntMap = boost::container::flat_map<std::string, int, std::less<>>;
using MeterMap = boost::container::flat_map<std::string, Meter, std::less<>>;
Expand Down Expand Up @@ -592,18 +611,42 @@ class FO_COMMON_API Empire final {
int m_auto_turn_count = 0; ///< auto-turn counter value
int m_last_turn_received = INVALID_GAME_TURN; ///< last turn empire completedly received game state

public:
// prepare tech, queue, and availability info for serialization for various empires
void PrepQueueAvailabilityInfoForSerialization(const ScriptingContext& context);

private:
std::map<int, decltype(m_techs)> m_techs_to_serialize_for_empires;
std::map<int, decltype(m_research_queue)> m_research_queue_to_serialize_for_empires;
std::map<int, decltype(m_research_progress)> m_research_progress_to_serialize_for_empires;
std::map<int, decltype(m_production_queue)> m_production_queue_to_serialize_for_empires;
std::map<int, decltype(m_influence_queue)> m_influence_queue_to_serialize_for_empires;
std::map<int, decltype(m_available_building_types)> m_available_building_types_to_serialize_for_empires;
std::map<int, decltype(m_available_ship_parts)> m_available_ship_parts_to_serialize_for_empires;
std::map<int, decltype(m_available_ship_hulls)> m_available_ship_hulls_to_serialize_for_empires;

const decltype(Empire::m_techs)& GetTechsToSerialize(int encoding_empire);
const decltype(Empire::m_research_queue)& GetResearchQueueToSerialize(int encoding_empire);
const decltype(Empire::m_research_progress)& GetResearchProgressToSerialize(int encoding_empire);
const decltype(Empire::m_production_queue)& GetProductionQueueToSerialize(int encoding_empire);
const decltype(Empire::m_influence_queue)& GetInfluenceQueueToSerialize(int encoding_empire);
const decltype(Empire::m_available_building_types)& GetAvailableBuildingsToSerialize(int encoding_empire);
const decltype(Empire::m_available_ship_parts)& GetAvailablePartsToSerialize(int encoding_empire);
const decltype(Empire::m_available_ship_hulls)& GetAvailableHullsToSerialize(int encoding_empire);


/** The source id is the id of any object owned by the empire. It is
mutable so that Source() can be const and still cache its result. */
mutable int m_source_id = INVALID_OBJECT_ID;
mutable int m_source_id = INVALID_OBJECT_ID;

int m_outposts_owned = 0; ///< how many uncolonized outposts does this empire currently own?
int m_outposts_owned = 0; ///< how many uncolonized outposts does this empire currently own?

bool m_ready = false; ///< readiness status of empire
bool m_authenticated = false; ///< Empire's Player's authentication flag. Set if only player with empire's player's name should play this empire.
bool m_eliminated = false; ///< Whether the empire has lost
bool m_ready = false; ///< readiness status of empire
bool m_authenticated = false; ///< Empire's Player's authentication flag. Set if only player with empire's player's name should play this empire.
bool m_eliminated = false; ///< Whether the empire has lost

friend class boost::serialization::access;
Empire();
Empire() { Init(); }
template <typename Archive>
void serialize(Archive& ar, const unsigned int version);
};
Expand Down
1 change: 1 addition & 0 deletions Empire/InfluenceQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct FO_COMMON_API InfluenceQueue {
using iterator = QueueType::iterator ;
using const_iterator = QueueType::const_iterator;

InfluenceQueue() = default;
explicit InfluenceQueue(int empire_id) :
m_empire_id(empire_id)
{}
Expand Down
3 changes: 2 additions & 1 deletion Empire/ProductionQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ struct FO_COMMON_API ProductionQueue {
/** The const ProductionQueue iterator type. Dereference yields a Element. */
typedef QueueType::const_iterator const_iterator;

ProductionQueue(int empire_id);
ProductionQueue() = default;
explicit ProductionQueue(int empire_id);

[[nodiscard]] int ProjectsInProgress() const noexcept { return m_projects_in_progress; } ///< number of production projects currently (perhaps partially) funded.
[[nodiscard]] float TotalPPsSpent() const; ///< number of PPs currently spent on the projects in this queue.
Expand Down
3 changes: 2 additions & 1 deletion Empire/ResearchQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ struct FO_COMMON_API ResearchQueue {
/** The const ResearchQueue iterator type. Dereference yields an Element. */
typedef QueueType::const_iterator const_iterator;

ResearchQueue(int empire_id) :
ResearchQueue() = default;
explicit ResearchQueue(int empire_id) :
m_empire_id(empire_id)
{}

Expand Down
37 changes: 21 additions & 16 deletions UI/CUIControls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2066,13 +2066,16 @@ void ResourceInfoPanel::DoLayout() {
MultiTurnProgressBar::MultiTurnProgressBar(int num_segments, float percent_completed, float percent_predicted,
GG::Clr bar_color, GG::Clr bg_color, GG::Clr outline_color) :
Control(GG::X0, GG::Y0, GG::X1, GG::Y1, GG::NO_WND_FLAGS),
m_num_segments(num_segments),
m_num_segments(std::min<int>(2048, std::max<int>(1, num_segments))),
m_perc_completed(percent_completed),
m_perc_predicted(percent_predicted),
m_clr_bar(bar_color),
m_clr_bg(bg_color),
m_clr_outline(outline_color)
{
if (m_num_segments > 1000)
WarnLogger() << "Very many segments in MultiTurnProgressBar!";

// validate percentage values
if (m_perc_completed < 0.0f || m_perc_predicted < 0.0f ||
(m_perc_completed + m_perc_predicted) > 1.0f)
Expand Down Expand Up @@ -2118,21 +2121,23 @@ void MultiTurnProgressBar::Render() {
// segment lines
GG::GL2DVertexBuffer segment_verts;
GG::GLRGBAColorBuffer segment_colors;
if (m_num_segments > 1u) {
segment_verts.reserve(std::size_t{2u} * m_num_segments);
segment_colors.reserve(std::size_t{2u} * m_num_segments);

GG::Clr current_colour(GG::DarkenClr(m_clr_bar));

for (int n = 1; n < static_cast<int>(m_num_segments); ++n) {
GG::X separator_x(ul.x + Width() * n / static_cast<int>(m_num_segments));
if (separator_x > comp_rect.lr.x)
current_colour = GG::LightenClr(m_clr_bg);
segment_verts.store(separator_x, ul.y);
segment_verts.store(separator_x, lr.y);
segment_colors.store(current_colour);
segment_colors.store(current_colour);
}
if (m_num_segments > 1u && m_num_segments < Value(Width())) {
try {
segment_verts.reserve(std::size_t{2u} * m_num_segments);
segment_colors.reserve(std::size_t{2u} * m_num_segments);

GG::Clr current_colour(GG::DarkenClr(m_clr_bar));

for (int n = 1; n < static_cast<int>(m_num_segments); ++n) {
GG::X separator_x(ul.x + Width() * n / static_cast<int>(m_num_segments));
if (separator_x > comp_rect.lr.x)
current_colour = GG::LightenClr(m_clr_bg);
segment_verts.store(separator_x, ul.y);
segment_verts.store(separator_x, lr.y);
segment_colors.store(current_colour);
segment_colors.store(current_colour);
}
} catch (...) {}
}

glDisable(GL_TEXTURE_2D);
Expand Down
3 changes: 2 additions & 1 deletion UI/CUIWnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,9 @@ void CUIWnd::InitSizeMove(GG::Pt ul, GG::Pt lr) {

// If the window has already had its default position specified (either in the ctor
// or a previous call to this function), apply this position to the window.
const std::string option_window_left_name = option_prefix + window_mode + ".left";
if (db.Get<bool>(option_initialized_name) ||
db.Get<GG::X>(option_prefix + window_mode + ".left") == INVALID_X)
db.Get<GG::X>(option_window_left_name) == INVALID_X)
{
SetDefaultedOptions();
SizeMove(ul, lr);
Expand Down
20 changes: 13 additions & 7 deletions UI/ProductionWnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,16 @@ namespace {
const ScriptingContext context;

SetDragDropDataType(BuildDesignatorWnd::PRODUCTION_ITEM_DROP_TYPE);
auto [total_cost, minimum_turns] = elem.ProductionCostAndTime(context);
auto [total_cost, minimum_turns] = elem.ProductionCostAndTime(context); // may return {-1.0f, -1}
total_cost *= elem.blocksize;

total_cost = std::max(total_cost, 0.0f);
minimum_turns = std::max(1, minimum_turns);

auto empire = context.GetEmpire(GGHumanClientApp::GetApp()->EmpireID());
float pp_accumulated = empire ? empire->ProductionStatus(queue_index, context) : 0.0f; // returns as PP
if (pp_accumulated == -1.0f)
pp_accumulated = 0.0f;
const float pp_accumulated = std::max<float>(
0.0f,
empire ? empire->ProductionStatus(queue_index, context) : 0.0f); // returns as PP

panel = GG::Wnd::Create<QueueProductionItemPanel>(
GG::X0, GG::Y0, ClientWidth() - X_MARGIN,
Expand Down Expand Up @@ -410,7 +413,10 @@ namespace {
m_turn_spending(turn_spending),
m_total_cost(total_cost),
m_completed_progress(completed_progress)
{}
{
if (m_total_turns < 1 || m_total_cost < 0)
WarnLogger() << "Low turns or total cost";
}

void QueueProductionItemPanel::CompleteConstruction() {
GG::Control::CompleteConstruction();
Expand Down Expand Up @@ -523,11 +529,11 @@ namespace {
outline_color = GG::LightenClr(outline_color);

m_progress_bar = GG::Wnd::Create<MultiTurnProgressBar>(
m_total_turns, perc_complete, next_progress,
std::max<int>(m_total_turns, 1), perc_complete, next_progress,
GG::LightenClr(ClientUI::TechWndProgressBarBackgroundColor()),
ClientUI::TechWndProgressBarColor(), outline_color);

double max_spending_per_turn = m_total_cost / m_total_turns;
double max_spending_per_turn = m_total_cost / std::max<int>(m_total_turns, 1);
std::string turn_spending_text = boost::io::str(FlexibleFormat(UserString("PRODUCTION_TURN_COST_STR"))
% DoubleToString(m_turn_spending, 3, false)
% DoubleToString(max_spending_per_turn, 3, false));
Expand Down
18 changes: 17 additions & 1 deletion default/stringtables/en.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,22 @@ RULE_BASIC_VIS_SYSTEM_INFO_SHOWN_DESC

<u>If Off</u>: Basic level visible systems that have never been detected at higher visiblity have unknown name and star type.'''

RULE_HIDDEN_POLICIES
Hide Empire Policies

RULE_HIDDEN_POLICIES_DESC
'''<u>If On</u>: Players who are not allied to an empire do not know other empires' adopted or available policies.

<u>If Off</u>: All players know all other empires' adopted and available policies.'''

RULE_HIDDEN_TECHS_QUEUES_AVAILABILITIES
Hide Empire Techs, Queues, and Availabilites

RULE_HIDDEN_TECHS_QUEUES_AVAILABILITIES_DESC
'''<u>If On</u>: Players who are not allied to an empire do not know other empires' researched techs, queues and part, hull, or building availabilities.

<u>If Off</u>: All players know all other empires' researched techs, queues, and availabilities.'''

RULE_HABITABLE_SIZE_TINY
Tiny planets Habitable size

Expand Down Expand Up @@ -5702,7 +5718,7 @@ ADOPTED_POLICIES
'''Adopted Policies: '''

NO_POLICIES_ADOPTED
No Policies Adopted
No Policies Known Adopted

AVAILABLE_PARTS
'''Available Parts: '''
Expand Down
45 changes: 40 additions & 5 deletions server/ServerApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,15 @@ bool ServerApp::NewGameInitVerifyJoiners(const std::vector<PlayerSetupData>& pla
void ServerApp::SendNewGameStartMessages() {
std::map<int, PlayerInfo> player_info_map = GetPlayerInfoMap();

const ScriptingContext context{m_universe, m_empires, m_galaxy_setup_data,
m_species_manager, m_supply_manager};

for (auto& empire : m_empires | range_values) {
empire->UpdateOwnedObjectCounters(m_universe);
empire->PrepQueueAvailabilityInfoForSerialization(context);
empire->PrepPolicyInfoForSerialization(context);
}

// send new game start messages
DebugLogger() << "SendGameStartMessages: Sending GameStartMessages to players";
for (auto player_connection_it = m_networking.established_begin(); // can't easily use range for loop due to non-standard begin and end
Expand Down Expand Up @@ -1468,6 +1477,15 @@ void ServerApp::LoadGameInit(const std::vector<PlayerSaveGameData>& player_save_

const auto player_info_map = GetPlayerInfoMap();



for (auto& empire : m_empires | range_values) {
empire->UpdateOwnedObjectCounters(m_universe);
empire->PrepQueueAvailabilityInfoForSerialization(context);
empire->PrepPolicyInfoForSerialization(context);
}


// assemble player state information, and send game start messages
DebugLogger() << "ServerApp::CommonGameInit: Sending GameStartMessages to players";

Expand Down Expand Up @@ -2090,12 +2108,20 @@ int ServerApp::AddPlayerIntoGame(const PlayerConnectionPtr& player_connection, i
if (GetOptionsDB().Get<bool>("network.server.drop-empire-ready")) {
// drop ready status
empire->SetReady(false);
m_networking.SendMessageAll(PlayerStatusMessage(Message::PlayerStatus::PLAYING_TURN,
empire_id));
m_networking.SendMessageAll(PlayerStatusMessage(Message::PlayerStatus::PLAYING_TURN, empire_id));
}

auto player_info_map = GetPlayerInfoMap();
bool use_binary_serialization = player_connection->IsBinarySerializationUsed();
const auto player_info_map = GetPlayerInfoMap();
const bool use_binary_serialization = player_connection->IsBinarySerializationUsed();

const ScriptingContext context{m_universe, m_empires, m_galaxy_setup_data,
m_species_manager, m_supply_manager};

for (auto& empire : m_empires | range_values) {
empire->UpdateOwnedObjectCounters(m_universe);
empire->PrepQueueAvailabilityInfoForSerialization(context);
empire->PrepPolicyInfoForSerialization(context);
}

player_connection->SendMessage(GameStartMessage(
m_single_player_game, empire_id,
Expand Down Expand Up @@ -4313,6 +4339,12 @@ void ServerApp::PreCombatProcessTurns() {
// indicate that the clients are waiting for their new Universes
m_networking.SendMessageAll(TurnProgressMessage(Message::TurnProgressPhase::DOWNLOADING));

for (auto& empire : m_empires | range_values) {
empire->UpdateOwnedObjectCounters(m_universe);
empire->PrepQueueAvailabilityInfoForSerialization(context);
empire->PrepPolicyInfoForSerialization(context);
}

// send partial turn updates to all players after orders and movement
// exclude those without empire and who are not Observer or Moderator
for (auto player_it = m_networking.established_begin();
Expand Down Expand Up @@ -4639,8 +4671,11 @@ void ServerApp::PostCombatProcessTurns() {

// misc. other updates and records
m_universe.UpdateStatRecords(context);
for (auto& empire : m_empires | range_values)
for (auto& empire : m_empires | range_values) {
empire->UpdateOwnedObjectCounters(m_universe);
empire->PrepQueueAvailabilityInfoForSerialization(context);
empire->PrepPolicyInfoForSerialization(context);
}


// indicate that the clients are waiting for their new gamestate
Expand Down
10 changes: 9 additions & 1 deletion server/ServerFSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3418,7 +3418,15 @@ sc::result WaitingForTurnEnd::react(const RevertOrders& msg) {
server.ClearEmpireTurnOrders(empire_id);

// re-send player initial turn update
bool use_binary_serialization = sender->IsBinarySerializationUsed();
const ScriptingContext context{server.GetUniverse(), server.Empires(), server.GetGalaxySetupData(),
server.GetSpeciesManager(), server.GetSupplyManager()};
for (auto& empire : server.Empires() | range_values) {
empire->UpdateOwnedObjectCounters(server.GetUniverse());
empire->PrepQueueAvailabilityInfoForSerialization(context);
empire->PrepPolicyInfoForSerialization(context);
}

const bool use_binary_serialization = sender->IsBinarySerializationUsed();
sender->SendMessage(TurnUpdateMessage(empire_id, server.CurrentTurn(),
server.Empires(), server.GetUniverse(),
server.GetSpeciesManager(), GetCombatLogManager(),
Expand Down
3 changes: 2 additions & 1 deletion server/ServerFramework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ auto PythonServer::InitModules() -> bool
if (GetOptionsDB().Get<int>("network.server.python.asyncio-interval") > 0) {
py::object asyncio = py::import("asyncio");

m_asyncio_event_loop = asyncio.attr("get_event_loop")();
m_asyncio_event_loop = asyncio.attr("new_event_loop")();
asyncio.attr("set_event_loop")(m_asyncio_event_loop);
}

DebugLogger() << "Server Python modules successfully initialized!";
Expand Down
2 changes: 2 additions & 0 deletions util/GameRuleRanks.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace GameRuleRanks {
RULE_RESEED_PRNG_SERVER_RANK = 1,
RULE_EXTRASOLAR_SHIP_DETECTION_RANK = 2,
RULE_BASIC_VIS_SYSTEM_INFO_SHOWN_RANK = 10,
RULE_HIDDEN_POLICIES_RANK = 20,
RULE_HIDDEN_TECHS_RANK = 21,
RULE_NUM_COMBAT_ROUNDS_RANK = 30,
RULE_AGGRESSIVE_SHIPS_COMBAT_VISIBLE_RANK = 35,
RULE_OVERRIDE_VIS_LEVEL_RANK = 40,
Expand Down
Loading

0 comments on commit 651cd50

Please sign in to comment.