Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wasm v0 client #871

Merged
merged 4 commits into from
Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,12 @@ jobs:
QT_VERSION: 5.15.2
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Cache Qt build
id: qtcache
uses: actions/cache@v2
with:
path: ~/qt
key: qt-wasm-${{ env.QT_VERSION }}-svg2
key: qt-wasm-${{ env.QT_VERSION }}-svg-socket
- name: Install build tools
run: |
sudo apt-get update
Expand Down Expand Up @@ -244,6 +242,10 @@ jobs:
run: |
source emsdk/emsdk_env.sh
cd qtbase
git config --global user.email "[email protected]"
git config --global user.name "root"
git fetch origin 76d12eea2252c5e537dff15b103bdc1f925cf760
git cherry-pick 76d12eea2252c5e537dff15b103bdc1f925cf760
./configure -xplatform wasm-emscripten -opensource -confirm-license -prefix ~/qt -nomake examples
make install
- uses: actions/checkout@v2
Expand Down
29 changes: 28 additions & 1 deletion client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,34 @@ if(FREECIV_ENABLE_CLIENT)
add_subdirectory(gui-qt)
add_executable(freeciv21-client ${GUI_TYPE} packhand.cpp) # packhand.c depends on gui-qt
if(EMSCRIPTEN)
target_link_options(freeciv21-client PRIVATE -sTOTAL_MEMORY=52428800)
target_link_options(freeciv21-client PRIVATE
-sASSERTIONS=1
-sWEBSOCKET_URL=wss://
-sTOTAL_MEMORY=52428800
-sALLOW_MEMORY_GROWTH=1
"-sEXPORTED_RUNTIME_METHODS=['UTF16ToString','stringToUTF16','callMain','printErr']"
--bind
-sUSE_SDL_MIXER=2
"--preload-file=${CMAKE_SOURCE_DIR}/data/flags@data/flags"
"--preload-file=${CMAKE_SOURCE_DIR}/data/helpdata.txt@data/helpdata.txt"
"--preload-file=${CMAKE_SOURCE_DIR}/data/misc@data/misc"
"--preload-file=${CMAKE_SOURCE_DIR}/data/buildings@data/buildings"
"--preload-file=${CMAKE_SOURCE_DIR}/data/wonders@data/wonders"
"--preload-file=${CMAKE_SOURCE_DIR}/data/hexemplio.tilespec@data/hexemplio.tilespec"
"--preload-file=${CMAKE_SOURCE_DIR}/data/hexemplio@data/hexemplio"
"--preload-file=${CMAKE_SOURCE_DIR}/data/amplio2.tilespec@data/amplio2.tilespec"
"--preload-file=${CMAKE_SOURCE_DIR}/data/amplio2@data/amplio2"
"--preload-file=${CMAKE_SOURCE_DIR}/data/themes/gui-qt/Classic@data/themes/gui-qt/Classic"
"--preload-file=${CMAKE_SOURCE_DIR}/data/themes/gui-qt/icons@data/themes/gui-qt/icons"
"--preload-file=${CMAKE_SOURCE_DIR}/data/stdmusic.musicspec@data/stdmusic.musicspec"
"--preload-file=${CMAKE_SOURCE_DIR}/data/stdmusic@data/stdmusic"
"--preload-file=${CMAKE_SOURCE_DIR}/data/stdsounds@data/stdsounds"
"--preload-file=${CMAKE_SOURCE_DIR}/data/stdsounds.soundspec@data/stdsounds.soundspec"
"--exclude-file=*CMakeLists*"
"--exclude-file=*.icns"
"--exclude-file=*.serv"
"--exclude-file=*.svg"
)
endif()
target_link_libraries(freeciv21-client client)
target_link_libraries(freeciv21-client gui-qt)
Expand Down
8 changes: 1 addition & 7 deletions client/client_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -773,8 +773,7 @@ void set_client_state(enum client_states newstate)
qFatal(_("There was an error while auto connecting; aborting."));
exit(EXIT_FAILURE);
} else {
start_autoconnecting_to_server(url);
auto_connect = false; // Don't try this again.
try_to_autoconnect(url);
}
}

Expand Down Expand Up @@ -1081,11 +1080,6 @@ double real_timer_callback()

voteinfo_queue_check_removed();

{
double autoconnect_time = try_to_autoconnect(url);
time_until_next_call = MIN(time_until_next_call, autoconnect_time);
}

if (C_S_RUNNING != client_state()) {
return time_until_next_call;
}
Expand Down
107 changes: 53 additions & 54 deletions client/clinet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// Qt
#include <QString>
#include <QTcpSocket>
#include <QTimer>
#include <QUrl>

// utility
Expand Down Expand Up @@ -55,10 +56,10 @@
#include "clinet.h"

// In autoconnect mode, try to connect to once a second
#define AUTOCONNECT_INTERVAL 500
const int AUTOCONNECT_INTERVAL = 500;

// In autoconnect mode, try to connect 100 times
#define MAX_AUTOCONNECT_ATTEMPTS 100
const int MAX_AUTOCONNECT_ATTEMPTS = 100;

/**
Close socket and cleanup. This one doesn't print a message, so should
Expand Down Expand Up @@ -96,6 +97,7 @@ static void client_conn_close_callback(struct connection *pconn)
qUtf8Printable(reason));
}

namespace {
/**
Try to connect to a server:
- try to create a TCP socket to the given URL (default to
Expand All @@ -108,6 +110,9 @@ static void client_conn_close_callback(struct connection *pconn)
message in ERRBUF and return the Unix error code (ie., errno, which
will be non-zero).
*/

QUrl connect_to;

static int try_to_connect(const QUrl &url, char *errbuf, int errbufsize)
{
// Apply defaults
Expand All @@ -123,35 +128,44 @@ static int try_to_connect(const QUrl &url, char *errbuf, int errbufsize)

// connection in progress? wait.
if (client.conn.used) {
(void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize);
return -1;
if (url_copy != connect_to) {
(void) fc_strlcpy(
errbuf, _("Canceled previous connection, trying new connection."),
errbufsize);
client.conn.sock->abort();
connect_to = url_copy;
} else {
(void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize);
return -1;
}
}
client.conn.used = true; // Now there will be a connection :)
client.conn.sock->disconnect(client.conn.sock);

// Connect
if (!client.conn.sock) {
client.conn.sock = new QTcpSocket;
QObject::connect(
client.conn.sock,
QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
[] {
if (client.conn.sock != nullptr) {
log_debug("%s", qUtf8Printable(client.conn.sock->errorString()));
real_output_window_append(client.conn.sock->errorString(), NULL,
-1);
}
client.conn.used = false;
});
}
client.conn.sock->connectToHost(url.host(), url.port());
if (!client.conn.sock->waitForConnected(-1)) {
errbuf[0] = '\0';
return -1;
}
make_connection(client.conn.sock, url.userName());
QObject::connect(
client.conn.sock,
QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
[] {
if (client.conn.sock != nullptr) {
log_debug("%s", qUtf8Printable(client.conn.sock->errorString()));
real_output_window_append(client.conn.sock->errorString(), NULL,
-1);
}
client.conn.used = false;
});
QObject::connect(client.conn.sock, &QTcpSocket::connected,
[userName = url.userName()] {
make_connection(client.conn.sock, userName);
});
zekoz marked this conversation as resolved.
Show resolved Hide resolved

client.conn.sock->connectToHost(url.host(), url.port());
return 0;
}
} // namespace

/**
Connect to a freeciv21-server instance -- or at least try to. On success,
Expand Down Expand Up @@ -324,22 +338,15 @@ void input_from_server(QTcpSocket *sock)
}
}

static bool autoconnecting = false;
/**
Make an attempt to autoconnect to the server.
It returns number of seconds it should be called again.
*/
double try_to_autoconnect(const QUrl &url)
void try_to_autoconnect(const QUrl &url)
{
char errbuf[512];
static int count = 0;

// Don't repeat autoconnect if not autoconnecting or the user
// established a connection by himself.
if (!autoconnecting || client.conn.established) {
return FC_INFINITY;
}

count++;

if (count >= MAX_AUTOCONNECT_ATTEMPTS) {
Expand All @@ -348,32 +355,24 @@ double try_to_autoconnect(const QUrl &url)
exit(EXIT_FAILURE);
}

if (try_to_connect(url, errbuf, sizeof(errbuf)) == 0) {
// Success! Don't call me again
autoconnecting = false;
return FC_INFINITY;
} else {
// All errors are fatal
qCritical(_("Error contacting server \"%s\":\n %s\n"),
qUtf8Printable(url.toDisplayString()), errbuf);
exit(EXIT_FAILURE);
if (!client.conn.sock) {
client.conn.sock = new QTcpSocket;
}
}

/**
Start trying to autoconnect to freeciv21-server. Calls
get_server_address(), then arranges for try_to_autoconnect(), which
calls try_to_connect(), to be called roughly every
AUTOCONNECT_INTERVAL milliseconds, until success, fatal error or
user intervention.
*/
void start_autoconnecting_to_server(const QUrl &url)
{
output_window_printf(
ftc_client,
_("Auto-connecting to \"%s\" every %f second(s) for %d times"),
qUtf8Printable(url.toDisplayString()), 0.001 * AUTOCONNECT_INTERVAL,
MAX_AUTOCONNECT_ATTEMPTS);
QObject::connect(
client.conn.sock,
QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
[url] {
if (client.conn.sock != nullptr) {
output_window_printf(ftc_client,
_("Failed to autoconnect to %s: %d of %d "
"attempts, retrying..."),
qUtf8Printable(url.toDisplayString()), count,
MAX_AUTOCONNECT_ATTEMPTS);
QTimer::singleShot(AUTOCONNECT_INTERVAL,
[url]() { try_to_autoconnect(url); });
}
});

autoconnecting = true;
try_to_connect(url, errbuf, sizeof(errbuf));
}
3 changes: 1 addition & 2 deletions client/clinet.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,4 @@ void make_connection(QTcpSocket *sock, const QString &username);
void input_from_server(QTcpSocket *sock);
void disconnect_from_server();

double try_to_autoconnect(const QUrl &url);
void start_autoconnecting_to_server(const QUrl &url);
void try_to_autoconnect(const QUrl &url);
3 changes: 3 additions & 0 deletions client/gui-qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ if(APPLE)
INCLUDE Qt5::QCocoaIntegrationPlugin Qt5::QSvgPlugin
)
endif()
if(EMSCRIPTEN)
qt5_import_plugins(gui-qt INCLUDE Qt5::QWasmIntegrationPlugin)
endif()
4 changes: 4 additions & 0 deletions client/gui-qt/fc_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ extern "C" void real_science_report_dialog_update(void *);
*/
fc_client::fc_client() : QMainWindow(), current_file(QLatin1String(""))
{
#ifdef __EMSCRIPTEN__
setWindowFlags(Qt::FramelessWindowHint);
setWindowState(Qt::WindowFullScreen);
#endif
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
status_bar_queue.clear();
for (int i = 0; i <= PAGE_GAME; i++) {
Expand Down
10 changes: 10 additions & 0 deletions client/gui-qt/page_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ void server_scan_error(struct server_scan *scan, const char *message)
*/
void page_network::destroy_server_scans()
{
#ifndef __EMSCRIPTEN__
if (meta_scan) {
server_scan_finish(meta_scan);
meta_scan = NULL;
Expand All @@ -305,13 +306,15 @@ void page_network::destroy_server_scans()
lan_scan_timer->disconnect();
FC_FREE(lan_scan_timer);
}
#endif
}

/**
Stop and restart the metaserver and lan server scans.
*/
void page_network::update_network_lists()
{
#ifndef __EMSCRIPTEN__
destroy_server_scans();

lan_scan_timer = new QTimer(this);
Expand All @@ -331,13 +334,15 @@ void page_network::update_network_lists()
&page_network::slot_meta_scan);
meta_scan_timer->start(800);
}
#endif
}

/**
This function updates the list of servers every so often.
*/
bool page_network::check_server_scan(server_scan *scan_data)
{
#ifndef __EMSCRIPTEN__
struct server_scan *scan = scan_data;
enum server_scan_status stat;

Expand All @@ -357,6 +362,9 @@ bool page_network::check_server_scan(server_scan *scan_data)
}

return !(stat == SCAN_STATUS_ERROR || stat == SCAN_STATUS_DONE);
#else
return true;
#endif
}

/**
Expand Down Expand Up @@ -502,6 +510,7 @@ void page_network::slot_selection_changed(const QItemSelection &selected,
ui.lan_widget->clearSelection();
}

#ifndef __EMSCRIPTEN__
srvrs = server_scan_get_list(meta_scan);
if (srvrs) {
pserver = server_list_get(srvrs, index.row());
Expand Down Expand Up @@ -535,4 +544,5 @@ void page_network::slot_selection_changed(const QItemSelection &selected,
ui.info_widget->setItem(k, col, item);
}
}
#endif
}