[[Multiplayer fixes]]

- fixed bug where if the host changed their name, it would show that
  name to users connecting to the game

- fixed bug in lobby where top-left of screen would not be drawn properly

- made private messaging work
This commit is contained in:
Dave White 2004-04-09 17:53:53 +00:00
parent 6245f0c421
commit 27f43ec122
20 changed files with 159 additions and 83 deletions

View file

@ -339,7 +339,7 @@ ggggggggggggggggggggffffffffffffffffff
[multiplayer_side]
name=&dwarf-lord.png,Knalgan Alliance
type=Dwarvish Lord
recruit=Thug,Thief,Poacher,Footpad,Dwarvish Fighter,Dwarvish Thunderer,Gryphon Rider
recruit=ahug,Thief,Poacher,Footpad,Dwarvish Fighter,Dwarvish Thunderer,Gryphon Rider
recruitment_pattern=fighter,fighter,fighter,archer
music="wesnoth-7.ogg"
terrain_liked=hm

View file

@ -39,7 +39,7 @@ height=600
[menu]
is_context_menu=true
items=undo,redo,cycle,describeunit,speak,recruit,recall,createunit,renameunit,labelterrain,endturn,showenemymoves,bestenemymoves
items=undo,redo,cycle,describeunit,speak,recruit,recall,createunit,renameunit,labelterrain,showenemymoves,bestenemymoves,endturn
[/menu]
# top panel

View file

@ -24,7 +24,7 @@ language="English"
command=repeatrecruit
key=r
ctrl=yes
shift=yes
alt=yes
[/hotkey]
[hotkey]
command=recall
@ -448,6 +448,8 @@ hotkeys_dialog="Hotkey Settings"
set_hotkey="Press desired HotKey"
hotkey_already_used="This HotKey is already in use."
speak_allies_only="Send to allies only"
speed="Speed:"
speed_normal="Normal"
speed_turbo="Accelerated Speed"

View file

@ -1190,7 +1190,7 @@ config config::get_diff(const config& c) const
string_map::const_iterator i;
for(i = values.begin(); i != values.end(); ++i) {
const string_map::const_iterator j = c.values.find(i->first);
if(j == c.values.end() || i->second != j->second) {
if(j == c.values.end() || i->second != j->second && i->second != "") {
if(inserts == NULL) {
inserts = &res.add_child("insert");
}
@ -1202,7 +1202,8 @@ config config::get_diff(const config& c) const
config* deletes = NULL;
for(i = c.values.begin(); i != c.values.end(); ++i) {
if(values.count(i->first) == 0) {
const string_map::const_iterator itor = values.find(i->first);
if(itor == values.end() || itor->second == "") {
if(deletes == NULL) {
deletes = &res.add_child("delete");
}

View file

@ -2579,10 +2579,14 @@ namespace {
const SDL_Color chat_message_colour = {200,200,200,200};
}
void display::add_chat_message(const std::string& speaker, const std::string& msg)
void display::add_chat_message(const std::string& speaker, const std::string& msg, display::MESSAGE_TYPE type)
{
std::stringstream str;
str << "<" << speaker << "> " << msg;
if(type == MESSAGE_PUBLIC) {
str << "<" << speaker << "> " << msg;
} else {
str << "*" << speaker << "* " << msg;
}
std::cerr << "chat message '" << str.str() << "'\n";
const SDL_Rect rect = map_area();
@ -2597,7 +2601,7 @@ void display::add_chat_message(const std::string& speaker, const std::string& ms
void display::prune_chat_messages(bool remove_all)
{
const int message_ttl = remove_all ? 0 : 30000;
const int message_ttl = remove_all ? 0 : 1200000;
if(chat_messages_.empty() == false && (chat_messages_.front().created_at+message_ttl < SDL_GetTicks() || chat_messages_.size() > max_chat_messages)) {
font::remove_floating_label(chat_messages_.front().handle);
chat_messages_.erase(chat_messages_.begin());

View file

@ -290,7 +290,8 @@ public:
map_labels& labels() { return map_labels_; }
const map_labels& labels() const { return map_labels_; }
void add_chat_message(const std::string& speaker, const std::string& msg);
enum MESSAGE_TYPE { MESSAGE_PUBLIC, MESSAGE_PRIVATE };
void add_chat_message(const std::string& speaker, const std::string& msg, MESSAGE_TYPE type);
private:
display(const display&);

View file

@ -391,10 +391,11 @@ void play_multiplayer_client(display& disp, game_data& units_data, config& cfg,
{
const config::child_list& sides_list = sides.get_children("side");
for(config::child_list::const_iterator side = sides_list.begin(); side != sides_list.end(); ++side) {
if(team_num-1 == side - sides_list.begin())
if(team_num-1 == side - sides_list.begin()) {
(**side)["controller"] = preferences::client_type();
else
} else {
(**side)["controller"] = "network";
}
}
}

View file

@ -36,18 +36,22 @@ RESULT enter(display& disp, config& game_data, const config& terrain_data)
std::vector<std::string> messages;
gui::textbox message_entry(disp,500);
scoped_sdl_surface background(image::get_image("misc/lobby.png",image::UNSCALED));
background.assign(scale_surface(background,disp.x(),disp.y()));
if(background == NULL) {
return QUIT;
}
SDL_BlitSurface(background, NULL, disp.video().getSurface(), NULL);
update_whole_screen();
gui::textbox message_entry(disp,500);
bool last_escape = true;
for(;;) {
if(background != NULL)
SDL_BlitSurface(background, NULL, disp.video().getSurface(), NULL);
SDL_BlitSurface(background, NULL, disp.video().getSurface(), NULL);
// Display Chats
std::stringstream text;
@ -64,7 +68,10 @@ RESULT enter(display& disp, config& game_data, const config& terrain_data)
// Game List GUI
const config* const gamelist = game_data.child("gamelist");
assert(gamelist != NULL);
if(gamelist == NULL) {
std::cerr << "ERROR: could not find gamelist\n";
return QUIT;
}
std::vector<std::string> options;
config::const_child_itors i;

View file

@ -1449,8 +1449,7 @@ void turn_info::recruit()
const std::map<std::string,unit_type>::const_iterator
u_type = gameinfo_.unit_types.find(*it);
if(u_type == gameinfo_.unit_types.end()) {
std::cerr << "could not find " << *it << std::endl;
assert(false);
std::cerr << "ERROR: could not find unit '" << *it << "'";
return;
}
@ -1672,9 +1671,25 @@ void turn_info::speak()
if(leader == units_.end())
return;
//see if this team has any networked friends. If so, then the player can choose to send
//to allies only.
bool has_friends = false;
for(size_t n = 0; n != teams_.size(); ++n) {
if(n != gui_.viewing_team() && teams_[gui_.viewing_team()].team_name() == teams_[n].team_name() &&
teams_[n].is_network()) {
has_friends = true;
}
}
std::vector<gui::check_item> checks;
if(has_friends) {
checks.push_back(gui::check_item(string_table["speak_allies_only"],preferences::message_private()));
}
std::string message;
const int res = gui::show_dialog(gui_,NULL,"",string_table["speak"],gui::OK_CANCEL,NULL,NULL,
string_table["message"] + ":", &message);
string_table["message"] + ":", &message,NULL,&checks);
if(res == 0) {
config cfg;
cfg["description"] = leader->second.description();
@ -1683,9 +1698,19 @@ void turn_info::speak()
sprintf(buf,"%d",leader->second.side());
cfg["side"] = buf;
bool private_message = false;
if(has_friends) {
private_message = checks.front().checked;
preferences::set_message_private(private_message);
if(private_message) {
cfg["team_name"] = teams_[gui_.viewing_team()].team_name();
}
}
recorder.speak(cfg);
gui_.add_chat_message(leader->second.description(),message);
// dialogs::unit_speak(cfg,gui_,units_);
gui_.add_chat_message(leader->second.description(),message,
private_message ? display::MESSAGE_PRIVATE : display::MESSAGE_PUBLIC);
}
}

View file

@ -39,6 +39,8 @@ display* disp = NULL;
bool muted_ = false;
bool colour_cursors = false;
bool message_private_on = true;
}
namespace preferences {
@ -322,6 +324,16 @@ void set_turn_bell(bool ison)
prefs["turn_bell"] = (ison ? "yes" : "no");
}
bool message_bell()
{
return prefs["message_bell"] != "no";
}
void set_message_bell(bool ison)
{
prefs["message_bell"] = (ison ? "yes" : "no");
}
bool turn_dialog()
{
return prefs["turn_dialog"] == "yes";
@ -421,10 +433,21 @@ void set_show_floating_labels(bool value)
prefs["floating_labels"] = value ? "yes" : "no";
}
bool message_private()
{
return message_private_on;
}
void set_message_private(bool value)
{
message_private_on = value;
}
void show_preferences_dialog(display& disp)
{
const events::resize_lock prevent_resizing;
const events::event_context dialog_events_context;
const gui::dialog_manager dialog_mgr;
log_scope("show_preferences_dialog");

View file

@ -69,6 +69,9 @@ namespace preferences {
bool turn_bell();
void set_turn_bell(bool ison);
bool message_bell();
void set_message_bell(bool ison);
bool turn_dialog();
void set_turn_dialog(bool ison);
@ -88,6 +91,9 @@ namespace preferences {
bool show_floating_labels();
void set_show_floating_labels(bool value);
bool message_private();
void set_message_private(bool value);
std::string client_type();
void set_theme(const std::string& theme);

View file

@ -20,8 +20,10 @@
#include "pathfind.hpp"
#include "playlevel.hpp"
#include "playturn.hpp"
#include "preferences.hpp"
#include "replay.hpp"
#include "show_dialog.hpp"
#include "sound.hpp"
#include "statistics.hpp"
#include <cstdio>
@ -777,7 +779,15 @@ bool do_replay(display& disp, const gamemap& map, const game_data& gameinfo,
advancing_units.push_back(tgt->first);
}
} else if((child = cfg->child("speak")) != NULL) {
disp.add_chat_message((*child)["description"],(*child)["message"]);
const std::string& team_name = (*child)["team_name"];
if(team_name == "" || teams[disp.viewing_team()].team_name() == team_name) {
if(preferences::message_bell()) {
sound::play_sound("bell.wav");
}
disp.add_chat_message((*child)["description"],(*child)["message"],
team_name == "" ? display::MESSAGE_PUBLIC : display::MESSAGE_PRIVATE);
}
} else if((child = cfg->child("label")) != NULL) {
const gamemap::location loc(*child);
const std::string& text = (*child)["text"];

View file

@ -64,53 +64,6 @@ int sdl_add_ref(SDL_Surface* surface)
return 0;
}
void draw_unit_ellipse(SDL_Surface* target, Uint16 colour, Uint8 alpha, const SDL_Rect& clip, int unitx, int unity, SDL_Surface* behind, bool image_reverse, ELLIPSE_HALF half)
{
const int xloc = unitx + (behind->w*15)/100;
const int yloc = unity + (behind->h*7)/10;
const int width = (behind->w*70)/100;
const int height = behind->h/6;
const double centerx = xloc + double(width)*0.5;
const double centery = yloc + double(height)*0.5;
const double r = double(width)*0.5;
const double yratio = double(height)/double(width);
int last_y = 0;
for(int xit = xloc; xit != xloc+width; ++xit) {
//r^2 = x^2 + y^2
//y^2 = r^2 - x^2
const double x = double(xit) - centerx;
const int y = int(sqrt(r*r - x*x)*yratio);
const int direction = y > last_y ? 1 : -1;
for(int i = last_y; i != y+direction; i += direction) {
int yit = yloc+height/2-y;
int xpos = xit - unitx;
if(image_reverse)
xpos = behind->w - xpos - 1;
int ypos = yit - unity;
if(half == ELLIPSE_TOP && xit >= clip.x && yit >= clip.y && xit < clip.x + clip.w && yit+1 < clip.y + clip.h &&
xpos >= 0 && ypos >= 0 && xpos < behind->w && ypos+1 < behind->h) {
SDL_Rect rect = {xit,yit,1,2};
fill_rect_alpha(rect,colour,alpha,target);
}
yit = yloc+height/2+y;
ypos = yit - unity;
if(half == ELLIPSE_BOTTOM && xit >= clip.x && yit >= clip.y && xit < clip.x + clip.w && yit+1 < clip.y + clip.h &&
xpos >= 0 && ypos >= 0 && xpos < behind->w && ypos+1 < behind->h) {
SDL_Rect rect = {xit,yit,1,2};
fill_rect_alpha(rect,colour,alpha,target);
}
}
last_y = y;
}
}
SDL_Surface* clone_surface(SDL_Surface* surface)
{
if(surface == NULL)

View file

@ -41,10 +41,6 @@ int sdl_add_ref(SDL_Surface* surface);
typedef util::scoped_resource<SDL_Surface*,free_sdl_surface> scoped_sdl_surface;
enum ELLIPSE_HALF { ELLIPSE_TOP, ELLIPSE_BOTTOM };
void draw_unit_ellipse(SDL_Surface* surf, Uint16 colour, Uint8 alpha, const SDL_Rect& clip, int unitx, int unity, SDL_Surface* unit_image, bool image_reverse, ELLIPSE_HALF half);
SDL_Surface* make_neutral_surface(SDL_Surface* surf);
SDL_Surface* clone_surface(SDL_Surface* surface);
SDL_Surface* scale_surface(SDL_Surface* surface, int w, int h);

View file

@ -207,6 +207,19 @@ void game::send_data(const config& data, network::connection exclude)
}
}
void game::send_data_team(const config& data, const std::string& team, network::connection exclude)
{
for(std::vector<network::connection>::const_iterator
i = players_.begin(); i != players_.end(); ++i) {
if(*i != exclude && sides_.count(*i) == 1) {
const config* const side = level_.find_child("side","side",sides_[*i]);
if(side != NULL && (*side)["team_name"] == team) {
network::send_data(data,*i);
}
}
}
}
void game::record_data(const config& data)
{
history_.push_back(data);

View file

@ -37,6 +37,7 @@ public:
int id() const;
void send_data(const config& data, network::connection exclude=0);
void send_data_team(const config& data, const std::string& team, network::connection exclude=0);
void record_data(const config& data);
//the full scenario data

View file

@ -370,14 +370,45 @@ void server::run()
continue;
}
if(data.child("turn") != NULL) {
const config* const turn = data.child("turn");
if(turn != NULL) {
//notify the game of the commands, and if it changes
//the description, then sync the new description
//to players in the lobby
const bool res = g->process_commands(*data.child("turn"));
const bool res = g->process_commands(*turn);
if(res) {
lobby_players_.send_data(sync_initial_response());
}
//any private 'speak' commands must be repackaged seperate
//to other commands, and re-sent, since they should only go
//to some clients.
const config::child_list& speaks = turn->get_children("speak");
if(speaks.empty() == false) {
int npublic = 0, nprivate = 0;
std::string team_name;
for(config::child_list::const_iterator i = speaks.begin();
i != speaks.end(); ++i) {
if((**i)["team_name"] == "") {
++npublic;
} else {
++nprivate;
team_name = (**i)["team_name"];
}
}
//if all there are are messages and they're all private, then
//just forward them on to the client that should receive them.
if(nprivate > 0 && npublic == 0 && turn->all_children().size() == 1) {
g->send_data_team(data,team_name,sock);
continue;
}
//at the moment, if private messages are mixed in with other
//data, then let them go through. It's exceedingly unlikely that
//this will happen anyway, and if it does, the client should
//respect not displaying the message.
}
}
//forward data to all players who are in the game,

View file

@ -410,6 +410,11 @@ void team::make_ai()
info_.controller = team_info::AI;
}
const std::string& team::team_name() const
{
return info_.team_name;
}
const std::string& team::ai_algorithm() const
{
return info_.ai_algorithm;

View file

@ -97,6 +97,8 @@ public:
void make_network();
void make_ai();
const std::string& team_name() const;
const std::string& ai_algorithm() const;
const config& ai_parameters() const;

View file

@ -110,8 +110,6 @@ void scrollbar::redraw()
draw();
}
// I'm sure this code is inefficient, but I'm not sure of how to do
// it more efficiently using scoped_resource
void scrollbar::draw()
{
if (!enabled() || !dirty())
@ -124,12 +122,9 @@ void scrollbar::draw()
const scoped_sdl_surface top_img(image::get_image(highlight_ ?
scrollbar_top_hl : scrollbar_top, image::UNSCALED));
const scoped_sdl_surface top_grv(image::get_image(groove_top,
image::UNSCALED));
const scoped_sdl_surface mid_grv(image::get_image(groove_mid,
image::UNSCALED));
const scoped_sdl_surface bottom_grv(image::get_image(groove_bottom,
image::UNSCALED));
const scoped_sdl_surface top_grv(image::get_image(groove_top,image::UNSCALED));
const scoped_sdl_surface mid_grv(image::get_image(groove_mid,image::UNSCALED));
const scoped_sdl_surface bottom_grv(image::get_image(groove_bottom,image::UNSCALED));
if (mid_img == NULL || bottom_img == NULL || top_img == NULL
|| top_grv == NULL || bottom_grv == NULL || mid_grv == NULL){