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/
*.o
zh_CN.qm
.fk_ver
# IDE & LSP
.kdev4/

View File

@ -1,21 +1,29 @@
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")
include_directories(fkparse/src)
add_subdirectory(fkparse)
endif ()
find_package(Qt6 REQUIRED COMPONENTS
Network
)
if (NOT DEFINED FK_SERVER_ONLY)
find_package(Qt6 REQUIRED COMPONENTS
Gui
Qml
Widgets
Network
Multimedia
QuickControls2
LinguistTools
)
else ()
add_definitions(-DFK_SERVER_ONLY)
endif()
find_package(OpenSSL)
find_package(Lua)
@ -24,7 +32,7 @@ find_package(SQLite3)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 11)
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)
@ -44,6 +52,8 @@ endif()
file(GLOB SWIG_FILES "${PROJECT_SOURCE_DIR}/src/swig/*.i")
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
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 ()
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill.i)
endif ()
@ -58,10 +68,20 @@ add_custom_command(
)
qt_add_executable(FreeKill)
if (NOT DEFINED FK_SERVER_ONLY)
qt_add_translations(FreeKill
TS_FILES lang/zh_CN.ts
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")
file(GLOB_RECURSE FK_RESOURCE_FILES

View File

@ -29,6 +29,7 @@ mkdir assets/res/server
cp ../server/init.sql assets/res/server
cp ../LICENSE 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)
function fixDir() {

View File

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

View File

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

View File

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

View File

@ -1,4 +1,3 @@
#include "qmlbackend.h"
#ifndef Q_OS_WASM
#include "server.h"
#include "packman.h"
@ -12,12 +11,15 @@
#include "applink.c"
#endif
#ifndef FK_SERVER_ONLY
#include <QSplashScreen>
#include <QScreen>
#include <QFileDialog>
# ifndef Q_OS_ANDROID
# include <QQuickStyle>
# endif
#include "qmlbackend.h"
#endif
#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
@ -49,6 +51,21 @@ static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
}
#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)
#include <stdlib.h>
#include <unistd.h>
@ -59,12 +76,12 @@ static void prepareForLinux() {
int len = readlink("/proc/self/exe", buf, 256);
if (!strcmp(buf, "/usr/bin/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(".local/share/FreeKill");
} else if (!strcmp(buf, "/usr/local/bin/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(".local/share/FreeKill");
}
@ -90,10 +107,12 @@ void fkMsgHandler(QtMsgType type, const QMessageLogContext &context, const QStri
break;
case QtCriticalMsg:
fprintf(stderr, "[%s/CRITICAL] %s\n", threadName.constData(), localMsg.constData());
#ifndef FK_SERVER_ONLY
if (Backend != nullptr) {
Backend->notifyUI("ErrorDialog", QString("⛔ %1/Error occured!\n %2")
.arg(threadName).arg(localMsg));
}
#endif
break;
case QtFatalMsg:
fprintf(stderr, "[%s/FATAL] %s\n", threadName.constData(), localMsg.constData());
@ -107,13 +126,13 @@ int main(int argc, char *argv[])
qInstallMessageHandler(fkMsgHandler);
QCoreApplication *app;
QCoreApplication::setApplicationName("FreeKill");
QCoreApplication::setApplicationVersion("Alpha 0.0.1");
QCoreApplication::setApplicationVersion(FK_VERSION);
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
prepareForLinux();
#endif
#ifndef Q_OS_WASM
#ifndef FK_CLIENT_ONLY
QCommandLineParser parser;
parser.setApplicationDescription("FreeKill server");
parser.addHelpOption();
@ -147,7 +166,14 @@ int main(int argc, char *argv[])
}
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
# ifdef Q_OS_WASM
copyPath(":/", QDir::currentPath());
# endif
@ -170,7 +196,7 @@ int main(int argc, char *argv[])
QSplashScreen splash(QPixmap("assets:/res/image/splash.jpg").scaled(screenWidth, screenHeight));
splash.showFullScreen();
SHOW_SPLASH_MSG("Copying resources...");
copyPath("assets:/res", QDir::currentPath());
installFkAssets("assets:/res", QDir::currentPath());
# else
QSplashScreen splash(QPixmap("image/splash.jpg"));
splash.show();
@ -235,4 +261,5 @@ int main(int argc, char *argv[])
delete Pacman;
return ret;
#endif
}

View File

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

View File

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

View File

@ -3,8 +3,6 @@
// core gui qml
#include <QtCore>
#include <QApplication>
#include <QtQml>
// network
#include <QTcpServer>
@ -22,4 +20,14 @@ typedef int LuaFunction;
#define DESKTOP_BUILD
#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

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"