added 'campaign server'...

...and capability to connect to the server to download campaigns
This commit is contained in:
Dave White 2004-09-12 21:55:21 +00:00
parent 45a3f46773
commit aac88ce5cc
23 changed files with 864 additions and 250 deletions

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -103,6 +103,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@ -459,16 +461,14 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
if (etags --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
test -f $$subdir/TAGS && \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
@ -478,11 +478,9 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
@ -594,7 +592,7 @@ distcheck: dist
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac

15
aclocal.m4 vendored
View file

@ -1,4 +1,4 @@
# generated automatically by aclocal 1.8.5 -*- Autoconf -*-
# generated automatically by aclocal 1.8.3 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
# Free Software Foundation, Inc.
@ -40,7 +40,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"])
# Call AM_AUTOMAKE_VERSION so it can be traced.
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.8.5])])
[AM_AUTOMAKE_VERSION([1.8.3])])
# AM_AUX_DIR_EXPAND
@ -266,14 +266,9 @@ AC_CACHE_CHECK([dependency style of $depcc],
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly:
# icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported
if (grep 'ignoring option' conftest.err ||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
# (even with -Werror). So we grep stderr for any message
# that says an option was ignored.
if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else
am_cv_$1_dependencies_compiler_type=$depmode
break
fi

469
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -84,6 +84,11 @@ AC_ARG_ENABLE([server],
[server=$enableval],
[server=no])
AC_ARG_ENABLE([campaign_server],
[ --enable-campaign-server enable compilation of campaign server],
[campaignserver=$enableval],
[campaignserver=no])
AC_ARG_ENABLE([editor],
[ --enable-editor enable compilation of map editor],
[editor=$enableval],
@ -113,6 +118,7 @@ AC_ARG_ENABLE([wzip],
AM_CONDITIONAL([STATIC], [test x$static = xyes])
AM_CONDITIONAL([SERVER], [test x$server = xyes])
AM_CONDITIONAL([CAMPAIGNSERVER], [test x$campaignserver = xyes])
AM_CONDITIONAL([EDITOR], [test x$editor = xyes])
AM_CONDITIONAL([TOOLS], [test x$tools = xyes])
AM_CONDITIONAL([KDE], [test x$kde = xyes && test x$kdefound = xyes])
@ -588,6 +594,7 @@ AC_CONFIG_FILES([Makefile
icons/Makefile
src/Makefile
src/server/Makefile
src/campaign_server/Makefile
src/tools/Makefile
src/zip/Makefile])

View file

@ -20,6 +20,25 @@ gggggggDgggggtggggggggggggggggggggggg
ggggggDgggtgggggggggggggggggggggggggg
ggggggggggggggggggggggggggggggggggggg
"
[event]
name=moveto
[filter]
x=11
y=6
side=1
[not]
description=Baldras
[/not]
[/filter]
[message]
id=you_didnt_win
speaker=narrator
message= _ "You can come if you wish, but the leader is only interesting in speaking to Baldras."
[/message]
[/event]
turns=36
id=test

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -87,6 +87,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -70,6 +70,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@

View file

@ -68,6 +68,7 @@ wesnoth_SOURCES = about.cpp \
playlevel.cpp \
playturn.cpp \
preferences.cpp \
publish_campaign.cpp \
race.cpp \
replay.cpp \
reports.cpp \
@ -139,6 +140,7 @@ wesnoth_SOURCES = about.cpp \
playlevel.hpp \
playturn.hpp \
preferences.hpp \
publish_campaign.hpp \
race.hpp \
replay.hpp \
reports.hpp \

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -86,15 +86,16 @@ am_wesnoth_OBJECTS = about.$(OBJEXT) actions.$(OBJEXT) ai.$(OBJEXT) \
multiplayer_client.$(OBJEXT) multiplayer_connect.$(OBJEXT) \
multiplayer_lobby.$(OBJEXT) network.$(OBJEXT) \
pathfind.$(OBJEXT) pathutils.$(OBJEXT) playlevel.$(OBJEXT) \
playturn.$(OBJEXT) preferences.$(OBJEXT) race.$(OBJEXT) \
replay.$(OBJEXT) reports.$(OBJEXT) sdl_utils.$(OBJEXT) \
show_dialog.$(OBJEXT) sound.$(OBJEXT) statistics.$(OBJEXT) \
team.$(OBJEXT) terrain.$(OBJEXT) theme.$(OBJEXT) \
titlescreen.$(OBJEXT) tooltips.$(OBJEXT) unit.$(OBJEXT) \
unit_display.$(OBJEXT) unit_types.$(OBJEXT) video.$(OBJEXT) \
button.$(OBJEXT) file_chooser.$(OBJEXT) combo.$(OBJEXT) \
menu.$(OBJEXT) progressbar.$(OBJEXT) scrollbar.$(OBJEXT) \
slider.$(OBJEXT) textbox.$(OBJEXT) widget.$(OBJEXT)
playturn.$(OBJEXT) preferences.$(OBJEXT) \
publish_campaign.$(OBJEXT) race.$(OBJEXT) replay.$(OBJEXT) \
reports.$(OBJEXT) sdl_utils.$(OBJEXT) show_dialog.$(OBJEXT) \
sound.$(OBJEXT) statistics.$(OBJEXT) team.$(OBJEXT) \
terrain.$(OBJEXT) theme.$(OBJEXT) titlescreen.$(OBJEXT) \
tooltips.$(OBJEXT) unit.$(OBJEXT) unit_display.$(OBJEXT) \
unit_types.$(OBJEXT) video.$(OBJEXT) button.$(OBJEXT) \
file_chooser.$(OBJEXT) combo.$(OBJEXT) menu.$(OBJEXT) \
progressbar.$(OBJEXT) scrollbar.$(OBJEXT) slider.$(OBJEXT) \
textbox.$(OBJEXT) widget.$(OBJEXT)
wesnoth_OBJECTS = $(am_wesnoth_OBJECTS)
wesnoth_LDADD = $(LDADD)
am_wesnoth_editor_OBJECTS = editor.$(OBJEXT) editor_layout.$(OBJEXT) \
@ -157,9 +158,11 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/network.Po ./$(DEPDIR)/pathfind.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/pathutils.Po ./$(DEPDIR)/playlevel.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/playturn.Po ./$(DEPDIR)/preferences.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/progressbar.Po ./$(DEPDIR)/race.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/replay.Po ./$(DEPDIR)/reports.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/scrollbar.Po ./$(DEPDIR)/sdl_utils.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/progressbar.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/publish_campaign.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/race.Po ./$(DEPDIR)/replay.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/reports.Po ./$(DEPDIR)/scrollbar.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/sdl_utils.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/show_dialog.Po ./$(DEPDIR)/slider.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/sound.Po ./$(DEPDIR)/statistics.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/team.Po ./$(DEPDIR)/terrain.Po \
@ -199,6 +202,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@ -413,6 +418,7 @@ wesnoth_SOURCES = about.cpp \
playlevel.cpp \
playturn.cpp \
preferences.cpp \
publish_campaign.cpp \
race.cpp \
replay.cpp \
reports.cpp \
@ -484,6 +490,7 @@ wesnoth_SOURCES = about.cpp \
playlevel.hpp \
playturn.hpp \
preferences.hpp \
publish_campaign.hpp \
race.hpp \
replay.hpp \
reports.hpp \
@ -781,6 +788,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/playturn.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preferences.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/progressbar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/publish_campaign.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/race.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/replay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reports.Po@am__quote@
@ -1148,16 +1156,14 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
if (etags --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
test -f $$subdir/TAGS && \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
@ -1167,11 +1173,9 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)

View file

@ -0,0 +1,27 @@
bin_PROGRAMS = campaignd
#############################################################################
# Wesnothd Server #
#############################################################################
wesnothd_SOURCES = campaign_server.cpp \
../server/variable.cpp \
../config.cpp \
../filesystem.cpp \
../game_config.cpp \
../gettext.cpp \
../log.cpp \
../network.cpp \
../publish_campaign.cpp \
../server/variable.hpp \
../game_events.hpp \
../config.hpp \
../filesystem.hpp \
../game_config.hpp \
../gettext.hpp \
../log.hpp \
../network.hpp \
../publish_campaign.hpp
AM_CXXFLAGS = @SDL_CFLAGS@ -DLOCALEDIR=\"$(LOCALEDIR)\"
AM_LDFLAGS = @SDL_LIBS@ @SDL_NET_LIBS@

View file

@ -0,0 +1,132 @@
#include "../config.hpp"
#include "../network.hpp"
#include "../publish_campaign.hpp"
#include "../util.hpp"
#include <iostream>
namespace {
config construct_message(const std::string& msg)
{
config cfg;
cfg.add_child("message")["message"] = msg;
return cfg;
}
config construct_error(const std::string& msg)
{
config cfg;
cfg.add_child("error")["message"] = msg;
return cfg;
}
class campaign_server
{
public:
explicit campaign_server(const std::string& cfgfile);
void run();
private:
const config& campaigns() const { return *cfg_.child("campaigns"); }
config& campaigns() { return *cfg_.child("campaigns"); }
config cfg_;
const std::string file_;
const network::manager net_manager_;
const network::server_manager server_manager_;
};
campaign_server::campaign_server(const std::string& cfgfile)
: cfg_(read_file(cfgfile)), file_(cfgfile),
server_manager_(lexical_cast_default<int>(cfg_["port"],15002))
{
if(cfg_.child("campaigns") == NULL) {
cfg_.add_child("campaigns");
}
}
void campaign_server::run()
{
for(;;) {
try {
network::process_send_queue();
network::connection sock = network::accept_connection();
if(sock) {
std::cerr << "received connection from " << network::ip_address(sock) << "\n";
}
config data;
while((sock = network::receive_data(data)) != NULL) {
if(data.child("request_campaign_list") != NULL) {
config campaign_list = campaigns();
config::child_list cmps = campaign_list.get_children("campaign");
for(config::child_list::iterator i = cmps.begin(); i != cmps.end(); ++i) {
(**i)["passphrase"] = "";
}
config response;
response.add_child("campaigns",campaign_list);
network::send_data(response,sock);
} else if(const config* req = data.child("request_campaign")) {
const config* const campaign = campaigns().find_child("campaign","name",(*req)["name"]);
if(campaign == NULL) {
network::send_data(construct_error("Campaign not found."),sock);
} else {
config cfg;
compression_schema schema;
cfg.read_compressed(read_file((*campaign)["filename"]),schema);
network::queue_data(cfg,sock);
}
} else if(const config* upload = data.child("upload")) {
config* campaign = campaigns().find_child("campaign","name",(*upload)["name"]);
if(campaign != NULL && (*campaign)["passphrase"] != (*upload)["passphrase"]) {
network::send_data(construct_error("The campaign already exists, and your passphrase was incorrect."),sock);
} else if(campaign_name_legal((*upload)["name"]) == false) {
network::send_data(construct_error("The name of the campaign is invalid"),sock);
} else {
if(campaign == NULL) {
campaign = &campaigns().add_child("campaign");
}
(*campaign)["name"] = (*upload)["name"];
(*campaign)["filename"] = (*upload)["name"];
(*campaign)["passphrase"] = (*upload)["passphrase"];
const config* const data = upload->child("data");
if(data != NULL) {
compression_schema schema;
write_file((*campaign)["filename"],data->write_compressed(schema));
}
write_file(file_,cfg_.write());
network::send_data(construct_message("Campaign accepted."),sock);
}
}
}
} catch(network::error& e) {
if(!e.socket) {
std::cerr << "fatal network error\n";
break;
} else {
e.disconnect();
}
} catch(config::error& e) {
std::cerr << "error in receiving data...\n";
}
}
}
}
int main(int argc, char** argv)
{
try {
campaign_server("server.cfg").run();
} catch(config::error& e) {
std::cerr << "Could not parse config file\n";
} catch(io_exception& e) {
std::cerr << "File I/O error\n";
}
}

View file

@ -309,9 +309,10 @@ void internal_preprocess_data(const std::string& data,
//there.
if(newfilename != "" && (newfilename[0] == '~' || newfilename[0] == '@')) {
nfname = newfilename;
prefix = get_user_data_dir() + "/";
nfname.erase(nfname.begin(),nfname.begin()+1);
nfname = prefix + "data/" + nfname;
nfname = get_user_data_dir() + "/data/" + nfname;
std::cerr << "got relative name '" << newfilename << "' -> '" << nfname << "'\n";
if(newfilename[0] == '@' && file_exists(nfname) == false && is_directory(nfname) == false) {
nfname = "data/" + newfilename.substr(1);
@ -639,12 +640,8 @@ void config::read(const std::string& data,
last_element.top()[name] = element;
if(element->values.count("textdomain") != 0){
std::cerr << "out of " << element
<< ", restoring from textdomain "
<< current_textdomain;
current_textdomain = textdomains.top();
textdomains.pop();
std::cerr << " to " << current_textdomain << "\n";
}
state = IN_ELEMENT;
@ -751,8 +748,6 @@ void config::read(const std::string& data,
bindtextdomain(current_textdomain.c_str(),
get_intl_dir().c_str());
bind_textdomain_codeset (current_textdomain.c_str(), "UTF-8");
std::cerr << "textdomain = " << value << " in "
<< element_names.top() << "\n";
}
}

View file

@ -226,6 +226,15 @@ std::string get_dir(const std::string& dir_path)
return dir_path;
}
void make_directory(const std::string& path)
{
#ifdef _WIN32
_mkdir(path.c_str());
#else
mkdir(path.c_str(),AccessMode);
#endif
}
std::string get_cwd()
{
char buf[1024];

View file

@ -42,6 +42,8 @@ std::string get_user_data_dir();
std::string get_cwd();
void make_directory(const std::string& dirname);
std::string read_map(const std::string& name);
//function which returns true iff the given file is a directory

View file

@ -43,6 +43,7 @@
#include "pathfind.hpp"
#include "playlevel.hpp"
#include "preferences.hpp"
#include "publish_campaign.hpp"
#include "replay.hpp"
#include "show_dialog.hpp"
#include "sound.hpp"
@ -349,6 +350,62 @@ int play_game(int argc, char** argv)
return 0;
} else if(val == "--nosound") {
use_sound = false;
} else if(val == "--publish-campaign") {
if(arg+3 != argc && arg+4 != argc && arg+5 != argc) {
std::cerr << "usage: --publish-campaign <campaign> <passphrase> [<server> [<port>]]\n";
return 0;
}
const std::string& campaign = argv[++arg];
const std::string& passphrase = argv[++arg];
std::string host = "campaigns.wesnoth.org", port = "15002";
if(++arg != argc) {
host = argv[arg];
if(++arg != argc) {
port = argv[arg];
}
}
const std::vector<std::string>& campaigns = available_campaigns();
if(std::find(campaigns.begin(),campaigns.end(),campaign) == campaigns.end()) {
std::cerr << "Campaign not found. Available campaigns are:\n";
std::copy(campaigns.begin(),campaigns.end(),std::ostream_iterator<std::string>(std::cerr,"\n"));
return 0;
}
if(campaign_name_legal(campaign) == false) {
std::cerr << "Not a legal campaign name.\n";
}
config cfg;
archive_campaign(campaign,cfg);
const network::manager net_manager;
network::connection sock = network::connect(host,lexical_cast_default<int>(port,15002));
if(!sock) {
std::cerr << "Could not connect to server\n";
return 0;
}
config data;
config& upload = data.add_child("upload");
upload["name"] = campaign;
upload["passphrase"] = passphrase;
upload.add_child("data",cfg);
std::cerr << "uploading campaign...\n";
network::send_data(data,sock);
sock = network::receive_data(data,sock,60000);
if(!sock) {
std::cerr << "Connection timed out\n";
} else if(data.child("error")) {
std::cerr << "Server responded with an error: '" << (*data.child("error"))["message"] << "'\n";
} else if(data.child("message")) {
std::cerr << (*data.child("message"))["message"] << "\n";
}
return 0;
}
}
@ -920,10 +977,7 @@ int play_game(int argc, char** argv)
campaign_names.push_back(str.str());
}
if(campaign_names.empty()) {
gui::show_dialog(disp,NULL,"",_("There are no campaigns available"),gui::OK_ONLY);
continue;
}
campaign_names.push_back(_(" ,Get More Campaigns..."));
int res = 0;
@ -936,6 +990,92 @@ int play_game(int argc, char** argv)
continue;
}
//get more campaigns from server
if(res == int(campaign_names.size()-1)) {
std::string host = "campaigns.wesnoth.org";
const int res = gui::show_dialog(disp,NULL,_("Connect to Server"),
_("You will now connect to a campaign server to download campaigns."),
gui::OK_CANCEL,NULL,NULL,_("Server: "),&host);
if(res != 0) {
continue;
}
const std::vector<std::string> items = config::split(host,':');
host = items.front();
try {
const network::manager net_manager;
const network::connection sock = network::connect(items.front(),lexical_cast_default<int>(items.back(),15002));
if(!sock) {
gui::show_dialog(disp,NULL,_("Error"),_("Could not connect to host."),gui::OK_ONLY);
continue;
}
config cfg;
cfg.add_child("request_campaign_list");
network::send_data(cfg,sock);
network::connection res = gui::network_data_dialog(disp,_("Awaiting response from server"),cfg,sock);
if(!res) {
continue;
}
const config* const error = cfg.child("error");
if(error != NULL) {
gui::show_dialog(disp,NULL,_("Error"),(*error)["message"],gui::OK_ONLY);
continue;
}
const config* const campaigns_cfg = cfg.child("campaigns");
if(campaigns_cfg == NULL) {
gui::show_dialog(disp,NULL,_("Error"),_("Error communicating with the server."),gui::OK_ONLY);
continue;
}
std::vector<std::string> campaigns;
const config::child_list& cmps = campaigns_cfg->get_children("campaign");
for(config::child_list::const_iterator i = cmps.begin(); i != cmps.end(); ++i) {
campaigns.push_back((**i)["name"]);
}
if(campaigns.empty()) {
gui::show_dialog(disp,NULL,_("Error"),_("There are no campaigns available for download from this server."),gui::OK_ONLY);
continue;
}
const int index = gui::show_dialog(disp,NULL,_("Get Campaign"),_("Choose the campaign to download."),gui::OK_CANCEL,&campaigns);
if(index < 0 || index >= int(campaigns.size())) {
continue;
}
config request;
request.add_child("request_campaign")["name"] = campaigns[index];
network::send_data(request,sock);
res = gui::network_data_dialog(disp,_("Downloading campaign..."),cfg,sock);
if(!res) {
continue;
}
if(cfg.child("error") != NULL) {
gui::show_dialog(disp,NULL,_("Error"),(*cfg.child("error"))["message"],gui::OK_ONLY);
continue;
}
unarchive_campaign(cfg);
gui::show_dialog(disp,NULL,_("Campaign Installed"),_("The campaign has been installed. You will have to restart Wesnoth before you can play it."),gui::OK_ONLY);
continue;
} catch(config::error& e) {
gui::show_dialog(disp,NULL,_("Error"),_("Network communication error."),gui::OK_ONLY);
continue;
} catch(network::error& e) {
gui::show_dialog(disp,NULL,_("Error"),_("Remote host disconnected."),gui::OK_ONLY);
continue;
}
}
const config& campaign = *campaigns[res];
state.scenario = campaign["first_scenario"];

View file

@ -59,6 +59,7 @@ void write_events(config& cfg);
bool unit_matches_filter(const unit& u, const config& filter);
bool unit_matches_filter(unit_map::const_iterator itor, const config& filter);
bool unit_matches_filter(const unit& u, const config& filter);
//function to fire an event. Events may have up to two arguments, both of
//which must be locations.

View file

@ -500,8 +500,8 @@ connection receive_data(config& cfg, connection connection_num, int timeout)
cfg.read_compressed(buffer,schema->second.incoming);
std::cerr << "--- RECEIVED DATA from " << ((int)*i) << ": '"
<< cfg.write() << "'\n--- END RECEIVED DATA\n";
// std::cerr << "--- RECEIVED DATA from " << ((int)*i) << ": '"
// << cfg.write() << "'\n--- END RECEIVED DATA\n";
return *i;
@ -561,8 +561,8 @@ void send_data(const config& cfg, connection connection_num, size_t max_size, SE
std::string value(4,'x');
value += cfg.write_compressed(schema->second.outgoing);
std::cerr << "--- SEND DATA to " << ((int)connection_num) << ": '"
<< cfg.write() << "'\n--- END SEND DATA\n";
// std::cerr << "--- SEND DATA to " << ((int)connection_num) << ": '"
// << cfg.write() << "'\n--- END SEND DATA\n";
char buf[4];
SDLNet_Write32(value.size()+1-4,buf);
@ -682,4 +682,6 @@ std::pair<int,int> current_transfer_stats()
return std::pair<int,int>(current_connection->second.upto,current_connection->second.buf.size());
}
bool sends_queued() { return send_queue.empty() == false; }
} //end namespace network

View file

@ -134,6 +134,8 @@ struct error
void disconnect();
};
bool sends_queued();
}
#endif

146
src/publish_campaign.cpp Normal file
View file

@ -0,0 +1,146 @@
#include "config.hpp"
#include "filesystem.hpp"
#include "publish_campaign.hpp"
#include <algorithm>
#include <cstring>
namespace {
const std::string campaign_dir = get_user_data_dir() + "/data/campaigns";
}
std::vector<std::string> available_campaigns()
{
std::vector<std::string> res;
std::vector<std::string> files, dirs;
get_files_in_dir(campaign_dir,&files,&dirs);
for(std::vector<std::string>::const_iterator i = dirs.begin(); i != dirs.end(); ++i) {
const std::string cfg_file = *i + ".cfg";
if(std::find(files.begin(),files.end(),cfg_file) != files.end()) {
res.push_back(*i);
}
}
return res;
}
namespace {
const char escape_char = 1;
bool needs_escaping(char c) { return c == 0 || c == escape_char; }
std::string encode_binary(const std::string& str)
{
std::string res;
res.resize(str.size());
size_t n = 0;
for(std::string::const_iterator j = str.begin(); j != str.end(); ++j) {
if(needs_escaping(*j)) {
res.resize(res.size()+1);
res[n++] = escape_char;
res[n++] = *j + 1;
} else {
res[n++] = *j;
}
}
return res;
}
std::string unencode_binary(const std::string& str)
{
std::string res;
res.resize(str.size());
size_t n = 0;
for(std::string::const_iterator j = str.begin(); j != str.end(); ++j) {
if(*j == escape_char && j+1 != str.end()) {
++j;
res[n++] = *j - 1;
res.resize(res.size()-1);
} else {
res[n++] = *j;
}
}
return res;
}
void archive_file(const std::string& path, const std::string& fname, config& cfg)
{
cfg["name"] = fname;
cfg["contents"] = encode_binary(read_file(path + '/' + fname));
}
void archive_dir(const std::string& path, const std::string& dirname, config& cfg)
{
cfg["name"] = dirname;
const std::string dir = path + '/' + dirname;
std::vector<std::string> files, dirs;
get_files_in_dir(dir,&files,&dirs);
for(std::vector<std::string>::const_iterator i = files.begin(); i != files.end(); ++i) {
archive_file(dir,*i,cfg.add_child("file"));
}
for(std::vector<std::string>::const_iterator j = dirs.begin(); j != dirs.end(); ++j) {
archive_dir(dir,*j,cfg.add_child("dir"));
}
}
}
void archive_campaign(const std::string& campaign_name, config& cfg)
{
archive_file(campaign_dir,campaign_name + ".cfg",cfg.add_child("file"));
archive_dir(campaign_dir,campaign_name,cfg.add_child("dir"));
}
namespace {
void unarchive_file(const std::string& path, const config& cfg)
{
write_file(path + '/' + cfg["name"],unencode_binary(cfg["contents"]));
}
void unarchive_dir(const std::string& path, const config& cfg)
{
const std::string dir = path + '/' + cfg["name"];
make_directory(dir);
const config::child_list& dirs = cfg.get_children("dir");
for(config::child_list::const_iterator i = dirs.begin(); i != dirs.end(); ++i) {
unarchive_dir(dir,**i);
}
const config::child_list& files = cfg.get_children("file");
for(config::child_list::const_iterator j = files.begin(); j != files.end(); ++j) {
unarchive_file(dir,**j);
}
}
}
void unarchive_campaign(const config& cfg)
{
unarchive_dir(campaign_dir,cfg);
}
namespace {
bool two_dots(char a, char b) { return a == '.' && b == '.'; }
}
bool campaign_name_legal(const std::string& name)
{
if(name == "" || strlen(name.c_str()) == 0 ||
std::find(name.begin(),name.end(),'/') != name.end() ||
std::find(name.begin(),name.end(),'\\') != name.end() ||
std::find(name.begin(),name.end(),':') != name.end() ||
std::adjacent_find(name.begin(),name.end(),two_dots) != name.end()) {
return false;
} else {
return true;
}
}

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -105,6 +105,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@ -510,11 +512,9 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)

View file

@ -59,7 +59,7 @@ void truncate_message(std::string& str)
class server
{
public:
explicit server(int port, input_stream& input);
server(int port, input_stream& input);
void run();
private:
void process_command(const std::string& cmd);

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -146,6 +146,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@ -626,11 +628,9 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)

View file

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.8.5 from Makefile.am.
# Makefile.in generated by automake 1.8.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@ -101,6 +101,8 @@ AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CAMPAIGNSERVER_FALSE = @CAMPAIGNSERVER_FALSE@
CAMPAIGNSERVER_TRUE = @CAMPAIGNSERVER_TRUE@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
@ -491,11 +493,9 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)