Assets and server only build (#71)

不再无脑替换掉assets素材;
添加server-only构建方式,减少依赖库
This commit is contained in:
notify 2023-03-08 12:14:02 +08:00 committed by GitHub
parent 5488469ad6
commit 8aa7bdf447
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 168 additions and 82 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@ build/
lib/libgit2/ lib/libgit2/
*.o *.o
zh_CN.qm zh_CN.qm
.fk_ver
# IDE & LSP # IDE & LSP
.kdev4/ .kdev4/

View File

@ -1,21 +1,29 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(FreeKill VERSION 0.0.1) project(FreeKill VERSION 0.0.4)
add_definitions(-DFK_VERSION=\"${CMAKE_PROJECT_VERSION}\")
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
include_directories(fkparse/src) include_directories(fkparse/src)
add_subdirectory(fkparse) add_subdirectory(fkparse)
endif () endif ()
find_package(Qt6 REQUIRED COMPONENTS
Network
)
if (NOT DEFINED FK_SERVER_ONLY)
find_package(Qt6 REQUIRED COMPONENTS find_package(Qt6 REQUIRED COMPONENTS
Gui Gui
Qml Qml
Widgets Widgets
Network
Multimedia Multimedia
QuickControls2 QuickControls2
LinguistTools LinguistTools
) )
else ()
add_definitions(-DFK_SERVER_ONLY)
endif()
find_package(OpenSSL) find_package(OpenSSL)
find_package(Lua) find_package(Lua)
@ -24,7 +32,7 @@ find_package(SQLite3)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(REQUIRED_QT_VERSION "6.3") set(REQUIRED_QT_VERSION "6.4")
include_directories(include/lua) include_directories(include/lua)
include_directories(include) include_directories(include)
@ -44,6 +52,8 @@ endif()
file(GLOB SWIG_FILES "${PROJECT_SOURCE_DIR}/src/swig/*.i") file(GLOB SWIG_FILES "${PROJECT_SOURCE_DIR}/src/swig/*.i")
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill-wasm.i) set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill-wasm.i)
elseif (DEFINED FK_SERVER_ONLY)
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill-nogui.i)
else () else ()
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill.i) set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill.i)
endif () endif ()
@ -58,10 +68,20 @@ add_custom_command(
) )
qt_add_executable(FreeKill) qt_add_executable(FreeKill)
if (NOT DEFINED FK_SERVER_ONLY)
qt_add_translations(FreeKill qt_add_translations(FreeKill
TS_FILES lang/zh_CN.ts TS_FILES lang/zh_CN.ts
QM_FILES_OUTPUT_VARIABLE zh_CN.qm QM_FILES_OUTPUT_VARIABLE zh_CN.qm
) )
endif()
add_custom_command(
TARGET FreeKill
POST_BUILD
COMMENT "Generating version file .fk_ver"
COMMAND echo ${CMAKE_PROJECT_VERSION} > ${PROJECT_SOURCE_DIR}/.fk_ver
)
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten") if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
file(GLOB_RECURSE FK_RESOURCE_FILES file(GLOB_RECURSE FK_RESOURCE_FILES

View File

@ -29,6 +29,7 @@ mkdir assets/res/server
cp ../server/init.sql assets/res/server cp ../server/init.sql assets/res/server
cp ../LICENSE assets/res cp ../LICENSE assets/res
cp ../zh_CN.qm assets/res cp ../zh_CN.qm assets/res
cp ../.fk_ver assets/res
# Due to Qt Android's bug, we need make sure every directory has a subfile (not subdir) # Due to Qt Android's bug, we need make sure every directory has a subfile (not subdir)
function fixDir() { function fixDir() {

View File

@ -10,35 +10,32 @@ set(freekill_SRCS
"server/server.cpp" "server/server.cpp"
"server/serverplayer.cpp" "server/serverplayer.cpp"
"server/room.cpp" "server/room.cpp"
"client/client.cpp"
"client/clientplayer.cpp"
"ui/qmlbackend.cpp"
"swig/freekill-wrap.cxx" "swig/freekill-wrap.cxx"
) )
set(freekill_HEADERS if (NOT DEFINED FK_SERVER_ONLY)
"core/util.h" list(APPEND freekill_SRCS
"core/player.h" "client/client.cpp"
"network/server_socket.h" "client/clientplayer.cpp"
"network/client_socket.h" "ui/qmlbackend.cpp"
"network/router.h"
"server/server.h"
"server/serverplayer.h"
"server/room.h"
"client/client.h"
"client/clientplayer.h"
"ui/qmlbackend.h"
) )
endif ()
set(FKP_LIB fkparse) set(FKP_LIB fkparse)
set(QT_LIB set(QT_LIB
Qt6::Network
)
if (NOT DEFINED FK_SERVER_ONLY)
list(APPEND QT_LIB
Qt6::Qml Qt6::Qml
Qt6::Gui Qt6::Gui
Qt6::Widgets Qt6::Widgets
Qt6::Network
Qt6::Multimedia Qt6::Multimedia
Qt6::QuickControls2 Qt6::QuickControls2
) )
endif()
if (WIN32) if (WIN32)
set(LUA_LIB ${PROJECT_SOURCE_DIR}/lib/win/lua54.dll) set(LUA_LIB ${PROJECT_SOURCE_DIR}/lib/win/lua54.dll)
set(SQLITE3_LIB ${PROJECT_SOURCE_DIR}/lib/win/sqlite3.dll) set(SQLITE3_LIB ${PROJECT_SOURCE_DIR}/lib/win/sqlite3.dll)
@ -79,8 +76,6 @@ else ()
set(GIT_LIB git2) set(GIT_LIB git2)
endif () endif ()
source_group("Include" FILES ${freekill_HEADERS})
target_sources(FreeKill PRIVATE ${freekill_SRCS}) target_sources(FreeKill PRIVATE ${freekill_SRCS})
target_precompile_headers(FreeKill PRIVATE "pch.h") target_precompile_headers(FreeKill PRIVATE "pch.h")
target_link_libraries(FreeKill PRIVATE target_link_libraries(FreeKill PRIVATE

View File

@ -3,7 +3,10 @@
#include "router.h" #include "router.h"
#include "clientplayer.h" #include "clientplayer.h"
#ifndef FK_SERVER_ONLY
#include "qmlbackend.h" #include "qmlbackend.h"
#endif
class Client : public QObject { class Client : public QObject {
Q_OBJECT Q_OBJECT

View File

@ -1,9 +1,14 @@
#include "packman.h" #include "packman.h"
#include "util.h" #include "util.h"
#include "qmlbackend.h"
#include "git2.h" #include "git2.h"
#include <qjsondocument.h> #include <qjsondocument.h>
#ifndef FK_SERVER_ONLY
#include "qmlbackend.h"
#else
static void *Backend = nullptr;
#endif
PackMan *Pacman; PackMan *Pacman;
PackMan::PackMan(QObject *parent) : QObject(parent) { PackMan::PackMan(QObject *parent) : QObject(parent) {
@ -51,7 +56,9 @@ void PackMan::loadSummary(const QString &jsonData, bool useThread) {
thread->start(); thread->start();
connect(thread, &QThread::finished, [=](){ connect(thread, &QThread::finished, [=](){
thread->deleteLater(); thread->deleteLater();
#ifndef FK_SERVER_ONLY
Backend->emitNotifyUI("DownloadComplete", ""); Backend->emitNotifyUI("DownloadComplete", "");
#endif
}); });
} else { } else {
f(); f();
@ -82,7 +89,9 @@ void PackMan::downloadNewPack(const QString &url, bool useThread) {
thread->start(); thread->start();
connect(thread, &QThread::finished, [=](){ connect(thread, &QThread::finished, [=](){
thread->deleteLater(); thread->deleteLater();
#ifndef FK_SERVER_ONLY
Backend->emitNotifyUI("DownloadComplete", ""); Backend->emitNotifyUI("DownloadComplete", "");
#endif
}); });
} else { } else {
threadFunc(); threadFunc();
@ -164,6 +173,7 @@ static int transfer_progress_cb(const git_indexer_progress *stats, void *payload
stats->indexed_objects, stats->received_bytes); stats->indexed_objects, stats->received_bytes);
} }
} else { } else {
#ifndef FK_SERVER_ONLY
if (stats->received_objects == stats->total_objects) { if (stats->received_objects == stats->total_objects) {
auto msg = QString("Resolving deltas %1/%2") auto msg = QString("Resolving deltas %1/%2")
.arg(stats->indexed_deltas).arg(stats->total_deltas); .arg(stats->indexed_deltas).arg(stats->total_deltas);
@ -174,6 +184,7 @@ static int transfer_progress_cb(const git_indexer_progress *stats, void *payload
.arg(stats->indexed_objects).arg(stats->received_bytes / 1024); .arg(stats->indexed_objects).arg(stats->received_bytes / 1024);
Backend->emitNotifyUI("UpdateBusyText", msg); Backend->emitNotifyUI("UpdateBusyText", msg);
} }
#endif
} }
return 0; return 0;

View File

@ -1,4 +1,3 @@
#include "qmlbackend.h"
#ifndef Q_OS_WASM #ifndef Q_OS_WASM
#include "server.h" #include "server.h"
#include "packman.h" #include "packman.h"
@ -12,12 +11,15 @@
#include "applink.c" #include "applink.c"
#endif #endif
#ifndef FK_SERVER_ONLY
#include <QSplashScreen> #include <QSplashScreen>
#include <QScreen> #include <QScreen>
#include <QFileDialog> #include <QFileDialog>
# ifndef Q_OS_ANDROID # ifndef Q_OS_ANDROID
# include <QQuickStyle> # include <QQuickStyle>
# endif # endif
#include "qmlbackend.h"
#endif
#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM) #if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath) static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
@ -49,6 +51,21 @@ static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
} }
#endif #endif
static void installFkAssets(const QString &src, const QString &dest) {
QFile f(dest + "/.fk_ver");
if (f.exists() && f.open(QIODevice::ReadOnly)) {
auto ver = f.readAll();
if (ver == FK_VERSION) {
return;
}
}
#ifdef Q_OS_ANDROID
copyPath(src, dest);
#elif defined(Q_OS_LINUX)
system(QString("cp -r %1 %2").arg(src).arg(dest).toUtf8());
#endif
}
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -59,12 +76,12 @@ static void prepareForLinux() {
int len = readlink("/proc/self/exe", buf, 256); int len = readlink("/proc/self/exe", buf, 256);
if (!strcmp(buf, "/usr/bin/FreeKill")) { if (!strcmp(buf, "/usr/bin/FreeKill")) {
system("mkdir -p ~/.local/share/FreeKill"); system("mkdir -p ~/.local/share/FreeKill");
system("cp -r /usr/share/FreeKill ~/.local/share"); installFkAssets("/usr/share/FreeKill", "~/.local/share");
chdir(getenv("HOME")); chdir(getenv("HOME"));
chdir(".local/share/FreeKill"); chdir(".local/share/FreeKill");
} else if (!strcmp(buf, "/usr/local/bin/FreeKill")) { } else if (!strcmp(buf, "/usr/local/bin/FreeKill")) {
system("mkdir -p ~/.local/share/FreeKill"); system("mkdir -p ~/.local/share/FreeKill");
system("cp -r /usr/local/share/FreeKill ~/.local/share"); installFkAssets("/usr/local/share/FreeKill", "~/.local/share");
chdir(getenv("HOME")); chdir(getenv("HOME"));
chdir(".local/share/FreeKill"); chdir(".local/share/FreeKill");
} }
@ -90,10 +107,12 @@ void fkMsgHandler(QtMsgType type, const QMessageLogContext &context, const QStri
break; break;
case QtCriticalMsg: case QtCriticalMsg:
fprintf(stderr, "[%s/CRITICAL] %s\n", threadName.constData(), localMsg.constData()); fprintf(stderr, "[%s/CRITICAL] %s\n", threadName.constData(), localMsg.constData());
#ifndef FK_SERVER_ONLY
if (Backend != nullptr) { if (Backend != nullptr) {
Backend->notifyUI("ErrorDialog", QString("⛔ %1/Error occured!\n %2") Backend->notifyUI("ErrorDialog", QString("⛔ %1/Error occured!\n %2")
.arg(threadName).arg(localMsg)); .arg(threadName).arg(localMsg));
} }
#endif
break; break;
case QtFatalMsg: case QtFatalMsg:
fprintf(stderr, "[%s/FATAL] %s\n", threadName.constData(), localMsg.constData()); fprintf(stderr, "[%s/FATAL] %s\n", threadName.constData(), localMsg.constData());
@ -107,13 +126,13 @@ int main(int argc, char *argv[])
qInstallMessageHandler(fkMsgHandler); qInstallMessageHandler(fkMsgHandler);
QCoreApplication *app; QCoreApplication *app;
QCoreApplication::setApplicationName("FreeKill"); QCoreApplication::setApplicationName("FreeKill");
QCoreApplication::setApplicationVersion("Alpha 0.0.1"); QCoreApplication::setApplicationVersion(FK_VERSION);
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
prepareForLinux(); prepareForLinux();
#endif #endif
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription("FreeKill server"); parser.setApplicationDescription("FreeKill server");
parser.addHelpOption(); parser.addHelpOption();
@ -147,7 +166,14 @@ int main(int argc, char *argv[])
} }
return app->exec(); return app->exec();
} }
#endif
#ifdef FK_SERVER_ONLY
qFatal("This is server-only build and have no GUI support.\n\
Please use ./FreeKill -s to start a server in command line.");
#else #else
# ifdef Q_OS_WASM
copyPath(":/", QDir::currentPath()); copyPath(":/", QDir::currentPath());
# endif # endif
@ -170,7 +196,7 @@ int main(int argc, char *argv[])
QSplashScreen splash(QPixmap("assets:/res/image/splash.jpg").scaled(screenWidth, screenHeight)); QSplashScreen splash(QPixmap("assets:/res/image/splash.jpg").scaled(screenWidth, screenHeight));
splash.showFullScreen(); splash.showFullScreen();
SHOW_SPLASH_MSG("Copying resources..."); SHOW_SPLASH_MSG("Copying resources...");
copyPath("assets:/res", QDir::currentPath()); installFkAssets("assets:/res", QDir::currentPath());
# else # else
QSplashScreen splash(QPixmap("image/splash.jpg")); QSplashScreen splash(QPixmap("image/splash.jpg"));
splash.show(); splash.show();
@ -235,4 +261,5 @@ int main(int argc, char *argv[])
delete Pacman; delete Pacman;
return ret; return ret;
#endif
} }

View File

@ -2,7 +2,7 @@
#include "client.h" #include "client.h"
#include "client_socket.h" #include "client_socket.h"
#include <qjsondocument.h> #include <qjsondocument.h>
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
#include "server.h" #include "server.h"
#include "serverplayer.h" #include "serverplayer.h"
#endif #endif
@ -16,7 +16,7 @@ Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
setSocket(socket); setSocket(socket);
expectedReplyId = -1; expectedReplyId = -1;
replyTimeout = 0; replyTimeout = 0;
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
extraReplyReadySemaphore = nullptr; extraReplyReadySemaphore = nullptr;
#endif #endif
} }
@ -49,7 +49,7 @@ void Router::setSocket(ClientSocket *socket)
} }
} }
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
void Router::setReplyReadySemaphore(QSemaphore *semaphore) void Router::setReplyReadySemaphore(QSemaphore *semaphore)
{ {
extraReplyReadySemaphore = semaphore; extraReplyReadySemaphore = semaphore;
@ -59,7 +59,7 @@ void Router::setReplyReadySemaphore(QSemaphore *semaphore)
void Router::request(int type, const QString& command, void Router::request(int type, const QString& command,
const QString& jsonData, int timeout) const QString& jsonData, int timeout)
{ {
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
// In case a request is called without a following waitForReply call // In case a request is called without a following waitForReply call
if (replyReadySemaphore.available() > 0) if (replyReadySemaphore.available() > 0)
replyReadySemaphore.acquire(replyReadySemaphore.available()); replyReadySemaphore.acquire(replyReadySemaphore.available());
@ -115,7 +115,7 @@ int Router::getTimeout() const
// cancel last request from the sender // cancel last request from the sender
void Router::cancelRequest() void Router::cancelRequest()
{ {
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
replyMutex.lock(); replyMutex.lock();
expectedReplyId = -1; expectedReplyId = -1;
replyTimeout = 0; replyTimeout = 0;
@ -130,7 +130,7 @@ void Router::cancelRequest()
QString Router::waitForReply(int timeout) QString Router::waitForReply(int timeout)
{ {
QString ret; QString ret;
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
replyReadySemaphore.tryAcquire(1, timeout * 1000); replyReadySemaphore.tryAcquire(1, timeout * 1000);
replyMutex.lock(); replyMutex.lock();
ret = m_reply; ret = m_reply;
@ -141,7 +141,7 @@ QString Router::waitForReply(int timeout)
void Router::abortRequest() void Router::abortRequest()
{ {
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
replyMutex.lock(); replyMutex.lock();
if (expectedReplyId != -1) { if (expectedReplyId != -1) {
replyReadySemaphore.release(); replyReadySemaphore.release();
@ -156,7 +156,7 @@ void Router::abortRequest()
void Router::handlePacket(const QByteArray& rawPacket) void Router::handlePacket(const QByteArray& rawPacket)
{ {
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
static QMap<QString, void (*)(ServerPlayer *, const QString &)> lobby_actions; static QMap<QString, void (*)(ServerPlayer *, const QString &)> lobby_actions;
if (lobby_actions.size() <= 0) { if (lobby_actions.size() <= 0) {
lobby_actions["UpdateAvatar"] = [](ServerPlayer *sender, const QString &jsonData){ lobby_actions["UpdateAvatar"] = [](ServerPlayer *sender, const QString &jsonData){
@ -230,9 +230,11 @@ void Router::handlePacket(const QByteArray& rawPacket)
if (type & TYPE_NOTIFICATION) { if (type & TYPE_NOTIFICATION) {
if (type & DEST_CLIENT) { if (type & DEST_CLIENT) {
#ifndef FK_SERVER_ONLY
ClientInstance->callLua(command, jsonData); ClientInstance->callLua(command, jsonData);
#endif
} }
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
else else
{ {
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent()); ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
@ -257,13 +259,15 @@ void Router::handlePacket(const QByteArray& rawPacket)
this->requestTimeout = packet[4].toInt(); this->requestTimeout = packet[4].toInt();
if (type & DEST_CLIENT) { if (type & DEST_CLIENT) {
#ifndef FK_SERVER_ONLY
qobject_cast<Client *>(parent())->callLua(command, jsonData); qobject_cast<Client *>(parent())->callLua(command, jsonData);
#endif
} else { } else {
// requesting server is not allowed // requesting server is not allowed
Q_ASSERT(false); Q_ASSERT(false);
} }
} }
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
else if (type & TYPE_REPLY) { else if (type & TYPE_REPLY) {
QMutexLocker locker(&replyMutex); QMutexLocker locker(&replyMutex);

View File

@ -29,7 +29,7 @@ public:
ClientSocket *getSocket() const; ClientSocket *getSocket() const;
void setSocket(ClientSocket *socket); void setSocket(ClientSocket *socket);
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
void setReplyReadySemaphore(QSemaphore *semaphore); void setReplyReadySemaphore(QSemaphore *semaphore);
#endif #endif
@ -67,7 +67,7 @@ private:
int expectedReplyId; int expectedReplyId;
int replyTimeout; int replyTimeout;
QString m_reply; // should be json string QString m_reply; // should be json string
#ifndef Q_OS_WASM #ifndef FK_CLIENT_ONLY
QSemaphore replyReadySemaphore; QSemaphore replyReadySemaphore;
QSemaphore *extraReplyReadySemaphore; QSemaphore *extraReplyReadySemaphore;
#endif #endif

View File

@ -3,8 +3,6 @@
// core gui qml // core gui qml
#include <QtCore> #include <QtCore>
#include <QApplication>
#include <QtQml>
// network // network
#include <QTcpServer> #include <QTcpServer>
@ -22,4 +20,14 @@ typedef int LuaFunction;
#define DESKTOP_BUILD #define DESKTOP_BUILD
#endif #endif
#if defined(Q_OS_WASM)
#define FK_CLIENT_ONLY
#endif
// You may define FK_SERVER_ONLY with cmake .. -D...
#ifndef FK_SERVER_ONLY
#include <QApplication>
#include <QtQml>
#endif
#endif // _PCH_H #endif // _PCH_H

16
src/swig/freekill-nogui.i Normal file
View File

@ -0,0 +1,16 @@
%module fk
%{
#include "server.h"
#include "serverplayer.h"
#include "clientplayer.h"
#include "room.h"
#include "util.h"
class ClientPlayer *Self = nullptr;
%}
%include "naturalvar.i"
%include "qt.i"
%include "player.i"
%include "server.i"
%include "sqlite3.i"