Merge branch 'server_set_to_idle'

This commit is contained in:
Chris Beck 2014-03-17 07:59:13 -04:00
commit cb6033ceb3
16 changed files with 94 additions and 24 deletions

View file

@ -29,6 +29,11 @@ Version 1.13.0-dev:
* Changed: Dropped support for AmigaOS, BeOS, and OS/2.
* Increased the sound mixer channel allocation from 16 to 32, thereby
raising the limit for simultaneous sound effects from 5 to 21.
* Fix bug #21758: "Ready not blocked while player pick faction."
* Fix bug #18829: "ai sides show up as "controller=network" on remote clients".
This issue is the source of some difficulties with mp campaigns which occur
when the campaign is reloaded from a non-host side, or after a player rejoins
from observer status. Hopefully, reloading campaigns is easier after this.
Version 1.11.11:
* Add-ons server:

View file

@ -192,8 +192,13 @@ void flg_manager::reset_gender_combo(gui::combo& combo_gender) const
combo_gender.set_selected(current_gender_index());
}
bool flg_manager::is_random_faction()
{
return (*current_faction_)["random_faction"].to_bool();
}
void flg_manager::resolve_random() {
if ((*current_faction_)["random_faction"].to_bool()) {
if (is_random_faction()) {
std::vector<std::string> faction_choices, faction_excepts;
faction_choices = utils::split((*current_faction_)["choices"]);

View file

@ -53,6 +53,7 @@ public:
void reset_leader_combo(gui::combo& combo_leader) const;
void reset_gender_combo(gui::combo& combo_gender) const;
bool is_random_faction();
void resolve_random();
// Picks the first faction with the greater amount of data

View file

@ -922,9 +922,9 @@ void game_display::send_notification(const std::string& /*owner*/, const std::st
if (i != i_end) {
i->message = message + "\n" + i->message;
int endl_pos = 0;
int endl_pos = -1;
for (int ctr = 0; ctr < 5; ctr++)
endl_pos = i->message.find('\n', endl_pos);
endl_pos = i->message.find('\n', endl_pos+1);
i->message = i->message.substr(0,endl_pos);

View file

@ -177,7 +177,7 @@ public:
for(std::vector<team>::const_iterator it = resources::teams->begin();
it != resources::teams->end();
++it) {
if(!it->is_ai() && !it->is_idle() && !it->is_empty() && !it->current_player().empty())
if(!it->is_ai() && !it->is_network_ai() && !it->is_idle() && !it->is_empty() && !it->current_player().empty())
nicks.insert(it->current_player());
}

View file

@ -459,7 +459,7 @@ static void enter_wait_mode(game_display& disp, const config& game_config,
switch (res) {
case mp::ui::PLAY:
play_game(disp, state, game_config, IO_CLIENT,
preferences::skip_mp_replay() && observe, true, preferences::blindfold_replay() && observe);
preferences::skip_mp_replay() && observe, true, preferences::blindfold_replay() && observe, observe);
recorder.clear();
break;

View file

@ -595,11 +595,6 @@ void connect::update_playerlist_state(bool silent)
set_user_list(playerlist, silent);
set_user_menu_items(playerlist);
}
if (!silent && !engine_.sides_available() && engine_.can_start_game()) {
DBG_MP << "play party full sound" << std::endl;
sound::play_UI_sound(game_config::sounds::party_full_bell);
}
}
} // end namespace mp

View file

@ -21,6 +21,7 @@
#include "map.hpp"
#include "multiplayer_ui.hpp"
#include "mp_game_utils.hpp"
#include "sound.hpp"
#include "tod_manager.hpp"
#include <boost/foreach.hpp>
@ -690,7 +691,9 @@ std::pair<bool, bool> connect_engine::process_network_data(const config& data,
LOG_CF << "client has taken a valid position\n";
bool was_reserved = (side_engines_[side_taken]->controller() == CNTR_RESERVED);
import_user(data, false, side_taken);
side_engines_[side_taken]->set_waiting_to_choose_status(!was_reserved);
update_and_send_diff();
@ -710,9 +713,14 @@ std::pair<bool, bool> connect_engine::process_network_data(const config& data,
if (const config& change_faction = data.child("change_faction")) {
int side_taken = find_user_side_index_by_id(change_faction["name"]);
if (side_taken != -1 || !first_scenario_) {
bool was_waiting_for_faction = side_engines_[side_taken]->waiting_to_choose_faction();
import_user(change_faction, false, side_taken);
update_and_send_diff();
if (was_waiting_for_faction && can_start_game()) {
DBG_MP << "play party full sound" << std::endl;
sound::play_UI_sound(game_config::sounds::party_full_bell);
}
}
}
@ -848,6 +856,8 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine,
current_player_(cfg["current_player"]),
player_id_(cfg["player_id"]),
ai_algorithm_(),
waiting_to_choose_faction_(allow_changes_ && allow_player_),
chose_random_(cfg["chose_random"].to_bool(false)),
flg_(parent_.era_factions_, cfg_, parent_.force_lock_settings_,
parent_.params_.saved_game, color_)
{
@ -1008,6 +1018,10 @@ config side_engine::new_config() const
res["name"] = res["user_description"];
res["allow_changes"] = !parent_.params_.saved_game && allow_changes_;
res["chose_random"] = false;
if(cfg_.has_attribute("chose_random")) {
res["chose_random"] = cfg_["chose_random"];
}
if (!parent_.params_.saved_game) {
// Find a config where a default leader is and set a new type
@ -1097,9 +1111,15 @@ bool side_engine::ready_for_start() const
return true;
}
if (available_for_user()) return false;
if (controller_ == CNTR_NETWORK && !player_id_.empty()) {
// Side is assigned to a network player.
return true;
if (player_id_ == preferences::login()) {
return true;//the host is ready
}
if (!waiting_to_choose_faction_ || !allow_changes_) {
return true; // Side is assigned to a network player, and they got a chance to choose faction if allowed
}
}
return false;
@ -1162,6 +1182,8 @@ void side_engine::resolve_random()
return;
}
chose_random_ = flg_.is_random_faction();
flg_.resolve_random();
LOG_MP << "side " << (index_ + 1) << ": faction=" <<
@ -1172,6 +1194,7 @@ void side_engine::resolve_random()
void side_engine::reset()
{
player_id_.clear();
set_waiting_to_choose_status(false);
set_controller(parent_.default_controller_);
if (!parent_.params_.saved_game) {
@ -1198,6 +1221,7 @@ void side_engine::place_user(const config& data, bool contains_selection)
flg_.set_current_faction(data["faction"].str());
flg_.set_current_leader(data["leader"].str());
flg_.set_current_gender(data["gender"].str());
waiting_to_choose_faction_ = false;
}
}
@ -1257,6 +1281,7 @@ bool side_engine::controller_changed(const int selection)
// If not, make sure that no user is assigned to this side.
if (selected_cntr == parent_.default_controller_ && selection != 0) {
player_id_ = controller_options_[selection].second;
set_waiting_to_choose_status(false);
} else {
player_id_.clear();
}

View file

@ -193,6 +193,9 @@ public:
void set_ai_algorithm(const std::string& ai_algorithm)
{ ai_algorithm_ = ai_algorithm; }
bool allow_player() const { return allow_player_; }
bool waiting_to_choose_faction() const { return waiting_to_choose_faction_; }
void set_waiting_to_choose_status(bool status) { waiting_to_choose_faction_ = status;}
bool chose_random() const { return chose_random_;}
const std::vector<std::string>& player_teams() const
{ return parent_.player_teams_; }
flg_manager& flg() { return flg_; }
@ -224,6 +227,8 @@ private:
std::string player_id_;
std::string ai_algorithm_;
bool waiting_to_choose_faction_;
bool chose_random_;
flg_manager flg_;
};

View file

@ -365,7 +365,7 @@ static LEVEL_RESULT playmp_scenario(const config& game_config,
LEVEL_RESULT play_game(game_display& disp, game_state& gamestate,
const config& game_config, io_type_t io_type, bool skip_replay,
bool network_game, bool blindfold_replay)
bool network_game, bool blindfold_replay, bool observer)
{
std::string type = gamestate.classification().campaign_type;
if(type.empty())
@ -428,7 +428,9 @@ LEVEL_RESULT play_game(game_display& disp, game_state& gamestate,
while(scenario != NULL) {
// If we are a multiplayer client, tweak the controllers
LOG_RG << "*** Playcampaign.cpp: Tweaking controllers ***" << std::endl;
if(io_type == IO_CLIENT) {
LOG_RG << "*** Playcampaign.cpp: We are a IO_CLIENT ***" << std::endl;
if(scenario != &starting_pos) {
starting_pos = *scenario;
scenario = &starting_pos;
@ -436,11 +438,27 @@ LEVEL_RESULT play_game(game_display& disp, game_state& gamestate,
BOOST_FOREACH(config &side, starting_pos.child_range("side"))
{
if (side["current_player"] == preferences::login()) {
LOG_RG << "*** Playcampaign.cpp: Tweaked " << side["controller"] << " -> " << std::endl;
if (!observer && side["current_player"] == preferences::login()) {//if we are not an observer and we are this player, it is our side
side["controller"] = "human";
} else if (side["controller"] != "null") {
side["controller"] = "network";
}
} else if (side["controller"] == "ai" || side["controller"] == "human_ai" || side["controller"] == "network_ai") {
side["controller"] = "network_ai"; //if server sends an ai side at start of scenario, it
} else if (side["controller"] != "null") { //is owned by the host (and definitely not us)
side["controller"] = "network"; //otherwise, side is controlled by human-host or null
} //and shold be networked, null resp.
//(did we miss anything?)
LOG_RG << "\t\t\t\t\t" << side["controller"] << std::endl;
}
} else if (io_type == IO_SERVER)
{
LOG_RG << "*** Playcampaign.cpp: We are a IO_SERVER ***" << std::endl;
BOOST_FOREACH(config &side, starting_pos.child_range("side"))
{
LOG_RG << "*** Playcampaign.cpp: Tweaked " << side["controller"] << " -> " << std::endl;
if (side["controller"] == "ai") {
side["controller"] = "human_ai"; //this is to guarantee that in an actual mp game, all ai sides will be "human_ai"
} //or "network_ai", and "ai" only occurs during configuration.
LOG_RG << "\t\t\t\t\t" << side["controller"] << std::endl;
}
}

View file

@ -36,7 +36,8 @@ LEVEL_RESULT play_game(game_display& disp, game_state& state,
io_type_t io_type=IO_NONE,
bool skip_replay = false,
bool network_game = false,
bool blindfold_replay = false);
bool blindfold_replay = false,
bool observer = false);
void play_replay(display& disp, game_state& state,
const config& game_config, CVideo& video);

View file

@ -191,7 +191,15 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
} else if (controller == "network_ai" && !tm.is_network_ai()) {
tm.make_network_ai();
} else if (controller == "ai" && !tm.is_ai()) {
tm.make_ai();
//if we are the controller, this should become human_ai, if not then network_ai
//this is to ensure that no side during an mp game is ever "ai", and always either human_ai or network_ai (except during configuration)
if (player == preferences::login()) {
tm.make_human_ai();
} else {
tm.make_network_ai();
}
} else if (controller == "idle" && !tm.is_idle()) {
tm.make_idle();
}
else
{
@ -236,7 +244,7 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
const bool have_leader = leader.valid();
if (controller == "ai"){
tm.make_ai();
tm.make_network_ai();
tm.set_current_player("ai" + side_drop);
if (have_leader) leader->rename("ai" + side_drop);
return restart?PROCESS_RESTART_TURN:PROCESS_CONTINUE;
@ -270,7 +278,7 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
//get all allies in as options to transfer control
BOOST_FOREACH(team &t, *resources::teams)
{
if (!t.is_enemy(side) && !t.is_human() && !t.is_ai() && !t.is_empty()
if (!t.is_enemy(side) && !t.is_human() && !t.is_ai() && !t.is_network_ai() && !t.is_empty()
&& t.current_player() != tm.current_player())
{
//if this is an ally of the dropping side and it is not us (choose local player

View file

@ -183,6 +183,8 @@ void game::start_game(const player_map::const_iterator starter) {
// Set all side controllers to 'human' so that observers will understand
// that they can't take control of any sides if they happen to have the
// same name as one of the descriptions.
// iceiceice 3/17/2014: disabled this behavior as it causes out of sync
// the observer issue is now handled by ... client remembers if they are observing.
const simple_wml::node::child_list& sides = level_.root().children("side");
for(simple_wml::node::child_list::const_iterator s = sides.begin(); s != sides.end(); ++s) {
nsides_++;
@ -194,7 +196,7 @@ void game::start_game(const player_map::const_iterator starter) {
LOG_GAME << msg.str() << " (game id: " << id_ << ")\n";
send_and_record_server_message(msg.str());
}
(*s)->set_attr("controller", "human");
//(*s)->set_attr("controller", "human");
}
}

View file

@ -2286,7 +2286,8 @@ void server::process_data_lobby(const network::connection sock,
if (!joined) {
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
<< "\tattempted to observe game:\t\"" << (*g)->name() << "\" ("
<< game_id << ") which doesn't allow observers.\n";
<< game_id << ") which doesn't allow observers.\n"
<< "(*g)->allow_observers() = " << (*g)->allow_observers() << std::endl;
send_doc(leave_game_doc, sock);
rooms_.lobby().send_server_message("Attempt to observe a game that doesn't allow observers. (You probably joined the game shortly after it filled up.)", sock);
send_doc(games_and_users_list_, sock);

View file

@ -60,7 +60,7 @@ const char * const team::attributes[] = {
"countdown_time", "disallow_observers", "faction",
"faction_from_recruit", "faction_name", "gold_lock", "income_lock",
"leader", "random_leader", "team_lock", "terrain_liked",
"user_description", "default_recruit", "controller_lock",
"user_description", "default_recruit", "controller_lock", "chose_random",
// Terminate the list with NULL.
NULL };
@ -99,6 +99,7 @@ team::team_info::team_info() :
share_view(false),
disallow_observers(false),
allow_player(false),
chose_random(false),
no_leader(true),
hidden(true),
no_turn_confirmation(false),
@ -128,6 +129,7 @@ void team::team_info::read(const config &cfg)
objectives_changed = cfg["objectives_changed"].to_bool();
disallow_observers = cfg["disallow_observers"].to_bool();
allow_player = cfg["allow_player"].to_bool(true);
chose_random = cfg["chose_random"].to_bool(false);
no_leader = cfg["no_leader"].to_bool();
hidden = cfg["hidden"].to_bool();
no_turn_confirmation = cfg["suppress_end_turn_confirmation"].to_bool();
@ -256,6 +258,7 @@ void team::team_info::write(config& cfg) const
cfg["recall_cost"] = recall_cost;
cfg["disallow_observers"] = disallow_observers;
cfg["allow_player"] = allow_player;
cfg["chose_random"] = chose_random;
cfg["no_leader"] = no_leader;
cfg["hidden"] = hidden;
cfg["suppress_end_turn_confirmation"] = no_turn_confirmation;

View file

@ -102,6 +102,7 @@ private:
bool share_maps, share_view;
bool disallow_observers;
bool allow_player;
bool chose_random;
bool no_leader;
bool hidden;
bool no_turn_confirmation; // Can suppress confirmations when ending a turn.