[[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:
parent
6245f0c421
commit
27f43ec122
20 changed files with 159 additions and 83 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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){
|
||||
|
|
Loading…
Add table
Reference in a new issue