Wasm (#36)
* compile with wasm * pack into qrc * disable colorized msg for browser and cmd.exe * run lua in wasm * run the game * font & pixmap anim * special init page for web * doc for compile wasm
This commit is contained in:
parent
f434e9ee9b
commit
fb425e15fb
|
@ -2,8 +2,10 @@ cmake_minimum_required(VERSION 3.16)
|
|||
|
||||
project(FreeKill VERSION 0.0.1)
|
||||
|
||||
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
include_directories(fkparse/src)
|
||||
add_subdirectory(fkparse)
|
||||
endif ()
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS
|
||||
Gui
|
||||
|
@ -31,15 +33,38 @@ include_directories(src/network)
|
|||
include_directories(src/server)
|
||||
include_directories(src/ui)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
# Fix include problem
|
||||
include_directories("/usr/include/openssl-1.1/")
|
||||
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)
|
||||
else ()
|
||||
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill.i)
|
||||
endif ()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${PROJECT_SOURCE_DIR}/src/swig/freekill-wrap.cxx
|
||||
DEPENDS ${SWIG_FILES}
|
||||
COMMENT "Generating freekill-wrap.cxx"
|
||||
COMMAND swig -c++ -lua -Wall -o
|
||||
${PROJECT_SOURCE_DIR}/src/swig/freekill-wrap.cxx
|
||||
${PROJECT_SOURCE_DIR}/src/swig/freekill.i
|
||||
${SWIG_SOURCE}
|
||||
)
|
||||
|
||||
qt_add_executable(FreeKill)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
file(GLOB_RECURSE FK_RESOURCE_FILES
|
||||
RELATIVE ${PROJECT_SOURCE_DIR}
|
||||
*.lua *.qml *.js *.png *.jpg *.mp3
|
||||
)
|
||||
list(APPEND FK_RESOURCE_FILES "fonts/FZLBGBK.ttf")
|
||||
qt_add_resources(FreeKill "qrc"
|
||||
PREFIX "/"
|
||||
FILES ${FK_RESOURCE_FILES}
|
||||
)
|
||||
endif()
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -91,3 +91,30 @@ ___
|
|||
## 编译安卓版
|
||||
|
||||
用Qt安装器装好Android库,然后配置一下android-sdk就能编译了。
|
||||
|
||||
___
|
||||
|
||||
## WASM下编译
|
||||
|
||||
WASM大概就是能在浏览器中跑C++。编译用Qt Creator即可。
|
||||
|
||||
### 1. 条件与局限性
|
||||
|
||||
如果程序运行在网页上的话,那么理应只有客户端,然后提供网页的服务器上自然也运行着一个后端服务器。所以说在编译时应该舍弃掉服务端相关的代码。因此依赖库就不再需要sqlite3。
|
||||
|
||||
总之是编译个纯客户端的FK。
|
||||
|
||||
### 2. 编译OpenSSL
|
||||
|
||||
进入OpenSSL的src目录,然后
|
||||
|
||||
$ ./config -no-asm -no-engine -no-dso
|
||||
$ emmake make -j8 build_generated libssl.a libcrypto.a
|
||||
|
||||
编译Lua的话直接emmake make就行了,总之库已经传到仓库了。
|
||||
|
||||
### 3. 部署资源文件
|
||||
|
||||
由于CMake中`file(GLOB_RECURSE)`所带来的缺陷,每当资源文件变动时,需要手动更新。
|
||||
|
||||
把构建目录中的.rcc目录删掉然后重新执行CMake->make即可。每次编译资源文件总要消耗相当多的时间。
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,4 @@
|
|||
import QtQuick
|
||||
import Qt.labs.folderlistmodel
|
||||
import "../skin-bank.js" as SkinBank
|
||||
|
||||
Item {
|
||||
|
@ -18,12 +17,8 @@ Item {
|
|||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
|
||||
FolderListModel {
|
||||
id: fileModel
|
||||
folder: SkinBank.PIXANIM_DIR + source
|
||||
nameFilters: ["*.png"]
|
||||
showDirs: false
|
||||
}
|
||||
property string folder: SkinBank.PIXANIM_DIR + source
|
||||
property int fileModel
|
||||
|
||||
Repeater {
|
||||
id: frames
|
||||
|
@ -35,7 +30,7 @@ Item {
|
|||
onStatusChanged: {
|
||||
if (status == Image.Ready) {
|
||||
loadedFrameCount++;
|
||||
if (loadedFrameCount == fileModel.count)
|
||||
if (loadedFrameCount == fileModel)
|
||||
root.loaded();
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +47,8 @@ Item {
|
|||
interval: 50
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (currentFrame >= fileModel.count) {
|
||||
frames.itemAt(fileModel.count - 1).visible = false;
|
||||
if (currentFrame >= fileModel) {
|
||||
frames.itemAt(fileModel - 1).visible = false;
|
||||
if (loop) {
|
||||
currentFrame = 0;
|
||||
} else {
|
||||
|
@ -73,7 +68,7 @@ Item {
|
|||
|
||||
function start()
|
||||
{
|
||||
if (loadedFrameCount == fileModel.count) {
|
||||
if (loadedFrameCount == fileModel) {
|
||||
timer.start();
|
||||
} else {
|
||||
root.loaded.connect(function(){
|
||||
|
@ -86,4 +81,8 @@ Item {
|
|||
{
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
fileModel = Backend.ls(folder).length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,14 @@ function moveCards(moves) {
|
|||
}
|
||||
|
||||
function setEmotion(id, emotion) {
|
||||
let path = (SkinBank.PIXANIM_DIR + emotion).replace("file://", "");
|
||||
let path;
|
||||
if (OS === "Win") {
|
||||
// Windows: file:/C:/xxx/xxxx
|
||||
path = (SkinBank.PIXANIM_DIR + emotion).replace("file:/", "");
|
||||
} else {
|
||||
path = (SkinBank.PIXANIM_DIR + emotion).replace("file://", "");
|
||||
}
|
||||
|
||||
if (!Backend.exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Item {
|
||||
id: root
|
||||
scale: 2
|
||||
|
||||
// Change this to your server's IP or domain name
|
||||
property string server_addr: "127.0.0.1:9530"
|
||||
|
||||
Frame {
|
||||
id: join_server
|
||||
anchors.centerIn: parent
|
||||
background: Rectangle {
|
||||
color: "#88888888"
|
||||
radius: 2
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
TextField {
|
||||
id: screenNameEdit
|
||||
text: "player"
|
||||
onTextChanged: {
|
||||
passwordEdit.text = "";
|
||||
let data = config.savedPassword[server_addr.editText];
|
||||
if (data) {
|
||||
if (text === data.username) {
|
||||
passwordEdit.text = data.shorten_password;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TextField {
|
||||
id: passwordEdit
|
||||
text: ""
|
||||
echoMode: TextInput.Password
|
||||
passwordCharacter: "*"
|
||||
}
|
||||
Button {
|
||||
text: "Login"
|
||||
enabled: passwordEdit.text !== ""
|
||||
onClicked: {
|
||||
config.serverAddr = server_addr;
|
||||
config.screenName = screenNameEdit.text;
|
||||
config.password = passwordEdit.text;
|
||||
mainWindow.busy = true;
|
||||
Backend.joinServer(server_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
config.loadConf();
|
||||
|
||||
let data = config.savedPassword[config.lastLoginServer];
|
||||
screenNameEdit.text = data.username;
|
||||
passwordEdit.text = data.shorten_password;
|
||||
}
|
||||
}
|
|
@ -37,11 +37,12 @@ Item {
|
|||
StackView {
|
||||
id: mainStack
|
||||
visible: !mainWindow.busy
|
||||
initialItem: init
|
||||
initialItem: OS !== "Web" ? init : webinit
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Component { id: init; Init {} }
|
||||
Component { id: webinit; WebInit {} }
|
||||
Component { id: lobby; Lobby {} }
|
||||
Component { id: generalsOverview; GeneralsOverview {} }
|
||||
Component { id: cardsOverview; CardsOverview {} }
|
||||
|
@ -152,7 +153,7 @@ Item {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!Android) {
|
||||
if (OS !== "Android" && OS !== "Web") {
|
||||
width = config.winWidth;
|
||||
height = config.winHeight;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ set(freekill_HEADERS
|
|||
"ui/qmlbackend.h"
|
||||
)
|
||||
|
||||
set(FKP_LIB fkparse)
|
||||
if (WIN32)
|
||||
set(LUA_LIB ${PROJECT_SOURCE_DIR}/lib/win/lua54.dll)
|
||||
set(SQLITE3_LIB ${PROJECT_SOURCE_DIR}/lib/win/sqlite3.dll)
|
||||
|
@ -40,6 +41,19 @@ elseif (ANDROID)
|
|||
QT_ANDROID_PACKAGE_SOURCE_DIR ${PROJECT_SOURCE_DIR}/android
|
||||
QT_ANDROID_EXTRA_LIBS "${LUA_LIB};${SQLITE3_LIB};${CRYPTO_LIB}"
|
||||
)
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
# WASM
|
||||
list(REMOVE_ITEM freekill_SRCS
|
||||
"network/server_socket.cpp"
|
||||
#"network/client_socket.cpp"
|
||||
#"network/router.cpp"
|
||||
"server/server.cpp"
|
||||
"server/serverplayer.cpp"
|
||||
"server/room.cpp"
|
||||
)
|
||||
set(FKP_LIB "")
|
||||
set(LUA_LIB ${PROJECT_SOURCE_DIR}/lib/wasm/liblua.a)
|
||||
set(CRYPTO_LIB ${PROJECT_SOURCE_DIR}/lib/wasm/libcrypto.a)
|
||||
else ()
|
||||
set(LUA_LIB lua5.4)
|
||||
set(SQLITE3_LIB sqlite3)
|
||||
|
@ -57,7 +71,7 @@ target_link_libraries(FreeKill PRIVATE
|
|||
${SQLITE3_LIB}
|
||||
${CRYPTO_LIB}
|
||||
${READLINE_LIB}
|
||||
fkparse
|
||||
${FKP_LIB}
|
||||
Qt6::Qml
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
|
|
|
@ -61,6 +61,7 @@ void Dumpstack(lua_State *L)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
sqlite3 *OpenDatabase(const QString &filename)
|
||||
{
|
||||
sqlite3 *ret;
|
||||
|
@ -151,6 +152,7 @@ RSA *InitServerRSA() {
|
|||
fclose(keyFile);
|
||||
return rsa;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void writeFileMD5(QFile &dest, const QString &fname) {
|
||||
QFile f(fname);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
lua_State *CreateLuaState();
|
||||
bool DoLuaScript(lua_State *L, const char *script);
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
sqlite3 *OpenDatabase(const QString &filename = "./server/users.db");
|
||||
QJsonObject SelectFromDatabase(sqlite3 *db, const QString &sql);
|
||||
// For Lua
|
||||
|
@ -14,6 +15,7 @@ void ExecSQL(sqlite3 *db, const QString &sql);
|
|||
void CloseDatabase(sqlite3 *db);
|
||||
|
||||
RSA *InitServerRSA();
|
||||
#endif
|
||||
|
||||
QString calcFileMD5();
|
||||
|
||||
|
|
40
src/main.cpp
40
src/main.cpp
|
@ -1,5 +1,7 @@
|
|||
#include "qmlbackend.h"
|
||||
#ifndef Q_OS_WASM
|
||||
#include "server.h"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
#include "shell.h"
|
||||
|
@ -11,8 +13,9 @@
|
|||
|
||||
#include <QSplashScreen>
|
||||
#include <QScreen>
|
||||
#include <QFileDialog>
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
|
||||
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath)
|
||||
{
|
||||
QFileInfo srcFileInfo(srcFilePath);
|
||||
|
@ -48,19 +51,19 @@ void fkMsgHandler(QtMsgType type, const QMessageLogContext &context, const QStri
|
|||
auto threadName = QThread::currentThread()->objectName().toLatin1().constData();
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
fprintf(stderr, "[%s/\e[1;30mDEBUG\e[0m] %s\n", threadName, localMsg.constData());
|
||||
fprintf(stderr, "[%s/DEBUG] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
fprintf(stderr, "[%s/\e[1;32mINFO\e[0m] %s\n", threadName, localMsg.constData());
|
||||
fprintf(stderr, "[%s/INFO] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stderr, "[%s/\e[1;33mWARNING\e[0m] %s\n", threadName, localMsg.constData());
|
||||
fprintf(stderr, "[%s/WARNING] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stderr, "[%s/\e[1;31mCRITICAL\e[0m] %s\n", threadName, localMsg.constData());
|
||||
fprintf(stderr, "[%s/CRITICAL] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stderr, "[%s/\e[1;31mFATAL\e[0m] %s\n", threadName, localMsg.constData());
|
||||
fprintf(stderr, "[%s/FATAL] %s\n", threadName, localMsg.constData());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +76,7 @@ int main(int argc, char *argv[])
|
|||
QCoreApplication::setApplicationName("FreeKill");
|
||||
QCoreApplication::setApplicationVersion("Alpha 0.0.1");
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("FreeKill server");
|
||||
parser.addHelpOption();
|
||||
|
@ -105,6 +109,9 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
return app->exec();
|
||||
}
|
||||
#else
|
||||
copyPath(":/", QDir::currentPath());
|
||||
#endif
|
||||
|
||||
app = new QApplication(argc, argv);
|
||||
|
||||
|
@ -132,19 +139,32 @@ int main(int argc, char *argv[])
|
|||
backend.setEngine(engine);
|
||||
|
||||
engine->rootContext()->setContextProperty("Backend", &backend);
|
||||
engine->rootContext()->setContextProperty("AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
bool debugging = true;
|
||||
#else
|
||||
bool debugging = false;
|
||||
#endif
|
||||
engine->rootContext()->setContextProperty("Debugging", debugging);
|
||||
#ifdef Q_OS_ANDROID
|
||||
engine->rootContext()->setContextProperty("Android", true);
|
||||
|
||||
|
||||
QString system;
|
||||
#if defined(Q_OS_ANDROID)
|
||||
system = "Android";
|
||||
#elif defined(Q_OS_WASM)
|
||||
system = "Web";
|
||||
#elif defined(Q_OS_WIN32)
|
||||
system = "Win";
|
||||
#elif defined(Q_OS_LINUX)
|
||||
system = "Linux";
|
||||
#else
|
||||
engine->rootContext()->setContextProperty("Android", false);
|
||||
system = "Other";
|
||||
#endif
|
||||
engine->rootContext()->setContextProperty("OS", system);
|
||||
|
||||
engine->rootContext()->setContextProperty("AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
||||
engine->load("qml/main.qml");
|
||||
|
||||
if (engine->rootObjects().isEmpty())
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include "router.h"
|
||||
#include "client.h"
|
||||
#include "client_socket.h"
|
||||
#ifndef Q_OS_WASM
|
||||
#include "server.h"
|
||||
#include "serverplayer.h"
|
||||
#endif
|
||||
#include "util.h"
|
||||
|
||||
Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
||||
|
@ -13,7 +15,9 @@ Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
|||
setSocket(socket);
|
||||
expectedReplyId = -1;
|
||||
replyTimeout = 0;
|
||||
#ifndef Q_OS_WASM
|
||||
extraReplyReadySemaphore = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
Router::~Router()
|
||||
|
@ -44,14 +48,17 @@ void Router::setSocket(ClientSocket *socket)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
void Router::setReplyReadySemaphore(QSemaphore *semaphore)
|
||||
{
|
||||
extraReplyReadySemaphore = semaphore;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Router::request(int type, const QString& command,
|
||||
const QString& jsonData, int timeout)
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
// In case a request is called without a following waitForReply call
|
||||
if (replyReadySemaphore.available() > 0)
|
||||
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||
|
@ -74,6 +81,7 @@ void Router::request(int type, const QString& command,
|
|||
body << timeout;
|
||||
|
||||
emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Router::reply(int type, const QString& command, const QString& jsonData)
|
||||
|
@ -106,6 +114,7 @@ int Router::getTimeout() const
|
|||
// cancel last request from the sender
|
||||
void Router::cancelRequest()
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
replyMutex.lock();
|
||||
expectedReplyId = -1;
|
||||
replyTimeout = 0;
|
||||
|
@ -114,22 +123,28 @@ void Router::cancelRequest()
|
|||
|
||||
if (replyReadySemaphore.available() > 0)
|
||||
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Router::waitForReply()
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
replyReadySemaphore.acquire();
|
||||
return m_reply;
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Router::waitForReply(int timeout)
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
replyReadySemaphore.tryAcquire(1, timeout * 1000);
|
||||
return m_reply;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Router::abortRequest()
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
replyMutex.lock();
|
||||
if (expectedReplyId != -1) {
|
||||
replyReadySemaphore.release();
|
||||
|
@ -139,10 +154,12 @@ void Router::abortRequest()
|
|||
extraReplyReadySemaphore = nullptr;
|
||||
}
|
||||
replyMutex.unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Router::handlePacket(const QByteArray& rawPacket)
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
static QMap<QString, void (*)(ServerPlayer *, const QString &)> lobby_actions;
|
||||
if (lobby_actions.size() <= 0) {
|
||||
lobby_actions["UpdateAvatar"] = [](ServerPlayer *sender, const QString &jsonData){
|
||||
|
@ -260,5 +277,28 @@ void Router::handlePacket(const QByteArray& rawPacket)
|
|||
locker.unlock();
|
||||
emit replyReady();
|
||||
}
|
||||
#else
|
||||
QJsonDocument packet = QJsonDocument::fromJson(rawPacket);
|
||||
if (packet.isNull() || !packet.isArray())
|
||||
return;
|
||||
|
||||
int requestId = packet[0].toInt();
|
||||
int type = packet[1].toInt();
|
||||
QString command = packet[2].toString();
|
||||
QString jsonData = packet[3].toString();
|
||||
|
||||
if (type & TYPE_NOTIFICATION) {
|
||||
if (type & DEST_CLIENT) {
|
||||
ClientInstance->callLua(command, jsonData);
|
||||
}
|
||||
} else if (type & TYPE_REQUEST) {
|
||||
this->requestId = requestId;
|
||||
this->requestTimeout = packet[4].toInt();
|
||||
|
||||
if (type & DEST_CLIENT) {
|
||||
qobject_cast<Client *>(parent())->callLua(command, jsonData);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,9 @@ public:
|
|||
ClientSocket *getSocket() const;
|
||||
void setSocket(ClientSocket *socket);
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
void setReplyReadySemaphore(QSemaphore *semaphore);
|
||||
#endif
|
||||
|
||||
void request(int type, const QString &command,
|
||||
const QString &jsonData, int timeout);
|
||||
|
@ -66,8 +68,10 @@ private:
|
|||
int expectedReplyId;
|
||||
int replyTimeout;
|
||||
QString m_reply; // should be json string
|
||||
#ifndef Q_OS_WASM
|
||||
QSemaphore replyReadySemaphore;
|
||||
QSemaphore *extraReplyReadySemaphore;
|
||||
#endif
|
||||
|
||||
// Two Lua global table for callbacks and interactions
|
||||
// stored in the lua_State of the sender
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
%module fk
|
||||
|
||||
%{
|
||||
#include "client.h"
|
||||
#include "serverplayer.h"
|
||||
#include "clientplayer.h"
|
||||
#include "room.h"
|
||||
#include "qmlbackend.h"
|
||||
#include "util.h"
|
||||
%}
|
||||
|
||||
%include "naturalvar.i"
|
||||
%include "qt.i"
|
||||
%include "player.i"
|
||||
%include "client.i"
|
|
@ -34,22 +34,3 @@ public:
|
|||
};
|
||||
|
||||
extern ClientPlayer *Self;
|
||||
|
||||
%nodefaultctor ServerPlayer;
|
||||
%nodefaultdtor ServerPlayer;
|
||||
class ServerPlayer : public Player {
|
||||
public:
|
||||
Server *getServer() const;
|
||||
Room *getRoom() const;
|
||||
void setRoom(Room *room);
|
||||
|
||||
void speak(const QString &message);
|
||||
|
||||
void doRequest(const QString &command,
|
||||
const QString &json_data, int timeout);
|
||||
QString waitForReply();
|
||||
QString waitForReply(int timeout);
|
||||
void doNotify(const QString &command, const QString &json_data);
|
||||
|
||||
void prepareForRequest(const QString &command, const QString &data);
|
||||
};
|
||||
|
|
|
@ -93,3 +93,21 @@ void Room::roomStart() {
|
|||
|
||||
%}
|
||||
|
||||
%nodefaultctor ServerPlayer;
|
||||
%nodefaultdtor ServerPlayer;
|
||||
class ServerPlayer : public Player {
|
||||
public:
|
||||
Server *getServer() const;
|
||||
Room *getRoom() const;
|
||||
void setRoom(Room *room);
|
||||
|
||||
void speak(const QString &message);
|
||||
|
||||
void doRequest(const QString &command,
|
||||
const QString &json_data, int timeout);
|
||||
QString waitForReply();
|
||||
QString waitForReply(int timeout);
|
||||
void doNotify(const QString &command, const QString &json_data);
|
||||
|
||||
void prepareForRequest(const QString &command, const QString &data);
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "qmlbackend.h"
|
||||
#ifndef Q_OS_WASM
|
||||
#include "server.h"
|
||||
#endif
|
||||
#include "client.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -11,14 +13,18 @@ QmlBackend::QmlBackend(QObject* parent)
|
|||
Backend = this;
|
||||
engine = nullptr;
|
||||
rsa = RSA_new();
|
||||
#ifndef Q_OS_WASM
|
||||
parser = fkp_new_parser();
|
||||
#endif
|
||||
}
|
||||
|
||||
QmlBackend::~QmlBackend()
|
||||
{
|
||||
Backend = nullptr;
|
||||
RSA_free(rsa);
|
||||
#ifndef Q_OS_WASM
|
||||
fkp_close(parser);
|
||||
#endif
|
||||
}
|
||||
|
||||
QQmlApplicationEngine *QmlBackend::getEngine() const
|
||||
|
@ -33,6 +39,7 @@ void QmlBackend::setEngine(QQmlApplicationEngine *engine)
|
|||
|
||||
void QmlBackend::startServer(ushort port)
|
||||
{
|
||||
#ifndef Q_OS_WASM
|
||||
if (!ServerInstance) {
|
||||
Server *server = new Server(this);
|
||||
|
||||
|
@ -41,6 +48,7 @@ void QmlBackend::startServer(ushort port)
|
|||
emit notifyUI("ErrorMsg", tr("Cannot start server!"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void QmlBackend::joinServer(QString address)
|
||||
|
@ -81,7 +89,7 @@ void QmlBackend::cd(const QString &path) {
|
|||
}
|
||||
|
||||
QStringList QmlBackend::ls(const QString &dir) {
|
||||
return QDir(dir).entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
return QDir(QUrl(dir).path()).entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
}
|
||||
|
||||
QString QmlBackend::pwd() {
|
||||
|
@ -169,12 +177,14 @@ QString QmlBackend::callLuaFunction(const QString &func_name,
|
|||
}
|
||||
|
||||
QString QmlBackend::pubEncrypt(const QString &key, const QString &data) {
|
||||
BIO *keyio = BIO_new_mem_buf(key.toLatin1().data(), -1);
|
||||
auto key_bytes = key.toLatin1();
|
||||
BIO *keyio = BIO_new_mem_buf(key_bytes.constData(), -1);
|
||||
PEM_read_bio_RSAPublicKey(keyio, &rsa, NULL, NULL);
|
||||
BIO_free_all(keyio);
|
||||
|
||||
auto data_bytes = data.toUtf8();
|
||||
unsigned char buf[RSA_size(rsa)];
|
||||
RSA_public_encrypt(data.length(), (const unsigned char *)data.toUtf8().data(),
|
||||
RSA_public_encrypt(data.length(), (const unsigned char *)data_bytes.constData(),
|
||||
buf, rsa, RSA_PKCS1_PADDING);
|
||||
return QByteArray::fromRawData((const char *)buf, RSA_size(rsa)).toBase64();
|
||||
}
|
||||
|
@ -209,6 +219,7 @@ void QmlBackend::saveConf(const QString &conf) {
|
|||
}
|
||||
|
||||
void QmlBackend::parseFkp(const QString &fileName) {
|
||||
#ifndef Q_OS_WASM
|
||||
if (!QFile::exists(fileName)) {
|
||||
// errorEdit->setText(tr("File does not exist!"));
|
||||
return;
|
||||
|
@ -245,8 +256,10 @@ void QmlBackend::parseFkp(const QString &fileName) {
|
|||
}
|
||||
*/
|
||||
QDir::setCurrent(cwd);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
static void copyFkpHash2QHash(QHash<QString, QString> &dst, fkp_hash *from) {
|
||||
dst.clear();
|
||||
for (size_t i = 0; i < from->capacity; i++) {
|
||||
|
@ -261,6 +274,7 @@ void QmlBackend::readHashFromParser() {
|
|||
copyFkpHash2QHash(skills, parser->skills);
|
||||
copyFkpHash2QHash(marks, parser->marks);
|
||||
}
|
||||
#endif
|
||||
|
||||
QString QmlBackend::calcFileMD5() {
|
||||
return ::calcFileMD5();
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef _QMLBACKEND_H
|
||||
#define _QMLBACKEND_H
|
||||
|
||||
#ifndef Q_OS_WASM
|
||||
#include "fkparse.h"
|
||||
#endif
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
class QmlBackend : public QObject {
|
||||
|
@ -48,7 +50,9 @@ signals:
|
|||
private:
|
||||
QQmlApplicationEngine *engine;
|
||||
RSA *rsa;
|
||||
#ifndef Q_OS_WASM
|
||||
fkp_parser *parser;
|
||||
#endif
|
||||
QHash<QString, QString> generals;
|
||||
QHash<QString, QString> skills;
|
||||
QHash<QString, QString> marks;
|
||||
|
|
Loading…
Reference in New Issue