Cppdev (#350)
- 对旁观和重连进行优化,减轻服务器CPU负担 - 加强Lua与C++交互能力,现在可以直接传const QVariant &参数 - 借助上一条,删除了客户端侧代码绝大多数冗余的json.encode/JSON.parse - 微调swig代码减少生成量,将int映射到lua integer而不是number
This commit is contained in:
parent
2be00fb3b0
commit
9d9217da2c
|
@ -31,7 +31,7 @@ find_package(Lua)
|
||||||
find_package(SQLite3)
|
find_package(SQLite3)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
set(REQUIRED_QT_VERSION "6.4")
|
set(REQUIRED_QT_VERSION "6.4")
|
||||||
|
|
||||||
|
@ -45,15 +45,8 @@ include_directories(src/network)
|
||||||
include_directories(src/server)
|
include_directories(src/server)
|
||||||
include_directories(src/ui)
|
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")
|
file(GLOB SWIG_FILES "${PROJECT_SOURCE_DIR}/src/swig/*.i")
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
if (DEFINED FK_SERVER_ONLY)
|
||||||
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)
|
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)
|
||||||
|
@ -87,54 +80,4 @@ add_custom_command(
|
||||||
COMMAND echo ${CMAKE_PROJECT_VERSION} > ${PROJECT_SOURCE_DIR}/fk_ver
|
COMMAND echo ${CMAKE_PROJECT_VERSION} > ${PROJECT_SOURCE_DIR}/fk_ver
|
||||||
)
|
)
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS ${CMAKE_MODULE_LINKER_FLAGS}
|
|
||||||
"-s INITIAL_MEMORY=64MB"
|
|
||||||
)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE FK_SCRIPT_FILES
|
|
||||||
RELATIVE ${PROJECT_SOURCE_DIR}
|
|
||||||
*.lua *.qml *.js *.fkp *.sql zh_CN.qm
|
|
||||||
)
|
|
||||||
qt_add_resources(FreeKill "scripts_qrc"
|
|
||||||
PREFIX "/"
|
|
||||||
FILES ${FK_SCRIPT_FILES}
|
|
||||||
)
|
|
||||||
|
|
||||||
qt_add_resources(FreeKill "font_qrc"
|
|
||||||
PREFIX "/"
|
|
||||||
FILES "fonts/FZLBGBK.ttf"
|
|
||||||
)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE FK_IMG_FILES
|
|
||||||
RELATIVE ${PROJECT_SOURCE_DIR}
|
|
||||||
${PROJECT_SOURCE_DIR}/image/*.jpg
|
|
||||||
${PROJECT_SOURCE_DIR}/image/*.png
|
|
||||||
)
|
|
||||||
qt_add_resources(FreeKill "img_qrc"
|
|
||||||
PREFIX "/"
|
|
||||||
FILES ${FK_IMG_FILES}
|
|
||||||
)
|
|
||||||
file(GLOB_RECURSE FK_AUDIO_FILES
|
|
||||||
RELATIVE ${PROJECT_SOURCE_DIR}
|
|
||||||
${PROJECT_SOURCE_DIR}/audio/*.mp3
|
|
||||||
)
|
|
||||||
qt_add_resources(FreeKill "audio_qrc"
|
|
||||||
PREFIX "/"
|
|
||||||
FILES ${FK_AUDIO_FILES}
|
|
||||||
)
|
|
||||||
file(GLOB_RECURSE FK_PKG_FILES
|
|
||||||
RELATIVE ${PROJECT_SOURCE_DIR}
|
|
||||||
${PROJECT_SOURCE_DIR}/packages/*.mp3
|
|
||||||
${PROJECT_SOURCE_DIR}/packages/*.jpg
|
|
||||||
${PROJECT_SOURCE_DIR}/packages/*.png
|
|
||||||
)
|
|
||||||
qt_add_resources(FreeKill "pkg_qrc"
|
|
||||||
PREFIX "/"
|
|
||||||
FILES ${FK_PKG_FILES}
|
|
||||||
)
|
|
||||||
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
16
Fk/Logic.js
16
Fk/Logic.js
|
@ -98,8 +98,7 @@ callbacks["BackToStart"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["SetServerSettings"] = (j) => {
|
callbacks["SetServerSettings"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const [ motd, hiddenPacks, enableBots ] = data;
|
const [ motd, hiddenPacks, enableBots ] = data;
|
||||||
config.serverMotd = motd;
|
config.serverMotd = motd;
|
||||||
config.serverHiddenPacks = hiddenPacks;
|
config.serverHiddenPacks = hiddenPacks;
|
||||||
|
@ -127,9 +126,8 @@ callbacks["EnterLobby"] = (jsonData) => {
|
||||||
config.saveConf();
|
config.saveConf();
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["EnterRoom"] = (jsonData) => {
|
callbacks["EnterRoom"] = (data) => {
|
||||||
// jsonData: int capacity, int timeout
|
// jsonData: int capacity, int timeout
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
config.roomCapacity = data[0];
|
config.roomCapacity = data[0];
|
||||||
config.roomTimeout = data[1] - 1;
|
config.roomTimeout = data[1] - 1;
|
||||||
const roomSettings = data[2];
|
const roomSettings = data[2];
|
||||||
|
@ -139,11 +137,11 @@ callbacks["EnterRoom"] = (jsonData) => {
|
||||||
mainWindow.busy = false;
|
mainWindow.busy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["UpdateRoomList"] = (jsonData) => {
|
callbacks["UpdateRoomList"] = (data) => {
|
||||||
const current = mainStack.currentItem; // should be lobby
|
const current = mainStack.currentItem; // should be lobby
|
||||||
if (mainStack.depth === 2) {
|
if (mainStack.depth === 2) {
|
||||||
current.roomModel.clear();
|
current.roomModel.clear();
|
||||||
JSON.parse(jsonData).forEach(room => {
|
data.forEach(room => {
|
||||||
const [roomId, roomName, gameMode, playerNum, capacity, hasPassword,
|
const [roomId, roomName, gameMode, playerNum, capacity, hasPassword,
|
||||||
outdated] = room;
|
outdated] = room;
|
||||||
current.roomModel.append({
|
current.roomModel.append({
|
||||||
|
@ -154,10 +152,9 @@ callbacks["UpdateRoomList"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["UpdatePlayerNum"] = (j) => {
|
callbacks["UpdatePlayerNum"] = (data) => {
|
||||||
const current = mainStack.currentItem; // should be lobby
|
const current = mainStack.currentItem; // should be lobby
|
||||||
if (mainStack.depth === 2) {
|
if (mainStack.depth === 2) {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const l = data[0];
|
const l = data[0];
|
||||||
const s = data[1];
|
const s = data[1];
|
||||||
current.lobbyPlayerNum = l;
|
current.lobbyPlayerNum = l;
|
||||||
|
@ -165,10 +162,9 @@ callbacks["UpdatePlayerNum"] = (j) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["Chat"] = (jsonData) => {
|
callbacks["Chat"] = (data) => {
|
||||||
// jsonData: { string userName, string general, string time, string msg }
|
// jsonData: { string userName, string general, string time, string msg }
|
||||||
const current = mainStack.currentItem; // lobby or room
|
const current = mainStack.currentItem; // lobby or room
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const pid = data.sender;
|
const pid = data.sender;
|
||||||
const userName = data.userName;
|
const userName = data.userName;
|
||||||
const general = luatr(data.general);
|
const general = luatr(data.general);
|
||||||
|
|
|
@ -421,10 +421,8 @@ function setCardFootnote(id, footnote) {
|
||||||
card.footnoteVisible = true;
|
card.footnoteVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["SetCardFootnote"] = (j) => {
|
callbacks["SetCardFootnote"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
const [id, note] = data;
|
||||||
const id = data[0];
|
|
||||||
const note = data[1];
|
|
||||||
setCardFootnote(id, note);
|
setCardFootnote(id, note);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,10 +442,8 @@ function setCardVirtName(id, name) {
|
||||||
card.virt_name = name;
|
card.virt_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["SetCardVirtName"] = (j) => {
|
callbacks["SetCardVirtName"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
const [ids, note] = data;
|
||||||
const ids = data[0];
|
|
||||||
const note = data[1];
|
|
||||||
ids.forEach(id => setCardVirtName(id, note));
|
ids.forEach(id => setCardVirtName(id, note));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,8 +504,7 @@ function processPrompt(prompt) {
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["MaxCard"] = (jsonData) => {
|
callbacks["MaxCard"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
const cardMax = data.pcardMax;
|
const cardMax = data.pcardMax;
|
||||||
const photo = getPhoto(id);
|
const photo = getPhoto(id);
|
||||||
|
@ -530,7 +525,7 @@ function changeSelf(id) {
|
||||||
dashboard.self = photos.itemAt(i);
|
dashboard.self = photos.itemAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callbacks["ArrangeSeats"](JSON.stringify(order));
|
callbacks["ArrangeSeats"](order);
|
||||||
|
|
||||||
// update dashboard
|
// update dashboard
|
||||||
dashboard.update();
|
dashboard.update();
|
||||||
|
@ -542,12 +537,11 @@ function changeSelf(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AddPlayer"] = (jsonData) => {
|
callbacks["AddPlayer"] = (data) => {
|
||||||
// jsonData: int id, string screenName, string avatar, bool ready
|
// jsonData: int id, string screenName, string avatar, bool ready
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
for (let i = 0; i < photoModel.count; i++) {
|
||||||
const item = photoModel.get(i);
|
const item = photoModel.get(i);
|
||||||
if (item.id === -1) {
|
if (item.id === -1) {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const uid = data[0];
|
const uid = data[0];
|
||||||
const name = data[1];
|
const name = data[1];
|
||||||
const avatar = data[2];
|
const avatar = data[2];
|
||||||
|
@ -740,9 +734,9 @@ function updateSelectedTargets(playerid, selected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["RemovePlayer"] = (jsonData) => {
|
callbacks["RemovePlayer"] = (data) => {
|
||||||
// jsonData: int uid
|
// jsonData: int uid
|
||||||
const uid = JSON.parse(jsonData)[0];
|
const uid = data[0];
|
||||||
const model = getPhotoModel(uid);
|
const model = getPhotoModel(uid);
|
||||||
if (typeof(model) !== "undefined") {
|
if (typeof(model) !== "undefined") {
|
||||||
model.id = -1;
|
model.id = -1;
|
||||||
|
@ -753,9 +747,9 @@ callbacks["RemovePlayer"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["RoomOwner"] = (jsonData) => {
|
callbacks["RoomOwner"] = (data) => {
|
||||||
// jsonData: int uid of the owner
|
// jsonData: int uid of the owner
|
||||||
const uid = JSON.parse(jsonData)[0];
|
const uid = data[0];
|
||||||
|
|
||||||
roomScene.isOwner = (Self.id === uid);
|
roomScene.isOwner = (Self.id === uid);
|
||||||
|
|
||||||
|
@ -777,8 +771,7 @@ function checkAllReady() {
|
||||||
roomScene.isAllReady = allReady;
|
roomScene.isAllReady = allReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["ReadyChanged"] = (j) => {
|
callbacks["ReadyChanged"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const id = data[0];
|
const id = data[0];
|
||||||
const ready = data[1];
|
const ready = data[1];
|
||||||
|
|
||||||
|
@ -793,8 +786,7 @@ callbacks["ReadyChanged"] = (j) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["NetStateChanged"] = (j) => {
|
callbacks["NetStateChanged"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const id = data[0];
|
const id = data[0];
|
||||||
let state = data[1];
|
let state = data[1];
|
||||||
|
|
||||||
|
@ -805,9 +797,8 @@ callbacks["NetStateChanged"] = (j) => {
|
||||||
model.netstate = state;
|
model.netstate = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["PropertyUpdate"] = (jsonData) => {
|
callbacks["PropertyUpdate"] = (data) => {
|
||||||
// jsonData: int id, string property_name, value
|
// jsonData: int id, string property_name, value
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const uid = data[0];
|
const uid = data[0];
|
||||||
const property_name = data[1];
|
const property_name = data[1];
|
||||||
let value = data[2];
|
let value = data[2];
|
||||||
|
@ -863,9 +854,8 @@ callbacks["StartGame"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["ArrangeSeats"] = (jsonData) => {
|
callbacks["ArrangeSeats"] = (order) => {
|
||||||
// jsonData: seat order
|
// jsonData: seat order
|
||||||
const order = JSON.parse(jsonData);
|
|
||||||
|
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
for (let i = 0; i < photoModel.count; i++) {
|
||||||
const item = photoModel.get(i);
|
const item = photoModel.get(i);
|
||||||
|
@ -895,10 +885,9 @@ function cancelAllFocus() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["MoveFocus"] = (jsonData) => {
|
callbacks["MoveFocus"] = (data) => {
|
||||||
// jsonData: int[] focuses, string command
|
// jsonData: int[] focuses, string command
|
||||||
cancelAllFocus();
|
cancelAllFocus();
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const focuses = data[0];
|
const focuses = data[0];
|
||||||
const command = data[1];
|
const command = data[1];
|
||||||
|
|
||||||
|
@ -925,9 +914,8 @@ callbacks["MoveFocus"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["PlayerRunned"] = (jsonData) => {
|
callbacks["PlayerRunned"] = (data) => {
|
||||||
// jsonData: int runner, int robot
|
// jsonData: int runner, int robot
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const runner = data[0];
|
const runner = data[0];
|
||||||
const robot = data[1];
|
const robot = data[1];
|
||||||
|
|
||||||
|
@ -937,9 +925,8 @@ callbacks["PlayerRunned"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForGeneral"] = (jsonData) => {
|
callbacks["AskForGeneral"] = (data) => {
|
||||||
// jsonData: string[] Generals
|
// jsonData: string[] Generals
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const generals = data[0];
|
const generals = data[0];
|
||||||
const n = data[1];
|
const n = data[1];
|
||||||
const convert = data[2];
|
const convert = data[2];
|
||||||
|
@ -960,9 +947,8 @@ callbacks["AskForGeneral"] = (jsonData) => {
|
||||||
box.updatePosition();
|
box.updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForSkillInvoke"] = (jsonData) => {
|
callbacks["AskForSkillInvoke"] = (data) => {
|
||||||
// jsonData: [ string name, string prompt ]
|
// jsonData: [ string name, string prompt ]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const skill = data[0];
|
const skill = data[0];
|
||||||
const prompt = data[1];
|
const prompt = data[1];
|
||||||
roomScene.promptText = prompt ? processPrompt(prompt)
|
roomScene.promptText = prompt ? processPrompt(prompt)
|
||||||
|
@ -973,8 +959,7 @@ callbacks["AskForSkillInvoke"] = (jsonData) => {
|
||||||
roomScene.cancelButton.enabled = true;
|
roomScene.cancelButton.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForGuanxing"] = (jsonData) => {
|
callbacks["AskForGuanxing"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const cards = [];
|
const cards = [];
|
||||||
const min_top_cards = data.min_top_cards;
|
const min_top_cards = data.min_top_cards;
|
||||||
const max_top_cards = data.max_top_cards;
|
const max_top_cards = data.max_top_cards;
|
||||||
|
@ -1011,8 +996,7 @@ callbacks["AskForGuanxing"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForExchange"] = (jsonData) => {
|
callbacks["AskForExchange"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const cards = [];
|
const cards = [];
|
||||||
const cards_name = [];
|
const cards_name = [];
|
||||||
const capacities = [];
|
const capacities = [];
|
||||||
|
@ -1041,10 +1025,9 @@ callbacks["AskForExchange"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForChoice"] = (jsonData) => {
|
callbacks["AskForChoice"] = (data) => {
|
||||||
// jsonData: [ string[] choices, string skill ]
|
// jsonData: [ string[] choices, string skill ]
|
||||||
// TODO: multiple choices, e.g. benxi_ol
|
// TODO: multiple choices, e.g. benxi_ol
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const choices = data[0];
|
const choices = data[0];
|
||||||
const all_choices = data[1];
|
const all_choices = data[1];
|
||||||
const skill_name = data[2];
|
const skill_name = data[2];
|
||||||
|
@ -1073,10 +1056,9 @@ callbacks["AskForChoice"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForChoices"] = (jsonData) => {
|
callbacks["AskForChoices"] = (data) => {
|
||||||
// jsonData: [ string[] choices, string skill ]
|
// jsonData: [ string[] choices, string skill ]
|
||||||
// TODO: multiple choices, e.g. benxi_ol
|
// TODO: multiple choices, e.g. benxi_ol
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const choices = data[0];
|
const choices = data[0];
|
||||||
const all_choices = data[1];
|
const all_choices = data[1];
|
||||||
const min_num = data[2][0];
|
const min_num = data[2][0];
|
||||||
|
@ -1115,10 +1097,9 @@ callbacks["AskForChoices"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForCardChosen"] = (jsonData) => {
|
callbacks["AskForCardChosen"] = (data) => {
|
||||||
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
|
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
|
||||||
// string reason ]
|
// string reason ]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const reason = data._reason;
|
const reason = data._reason;
|
||||||
const prompt = data._prompt;
|
const prompt = data._prompt;
|
||||||
if (prompt === "") {
|
if (prompt === "") {
|
||||||
|
@ -1145,10 +1126,9 @@ callbacks["AskForCardChosen"] = (jsonData) => {
|
||||||
box.cardSelected.connect(cid => replyToServer(cid));
|
box.cardSelected.connect(cid => replyToServer(cid));
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForCardsChosen"] = (jsonData) => {
|
callbacks["AskForCardsChosen"] = (data) => {
|
||||||
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
|
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
|
||||||
// int min, int max, string reason ]
|
// int min, int max, string reason ]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const min = data._min;
|
const min = data._min;
|
||||||
const max = data._max;
|
const max = data._max;
|
||||||
const reason = data._reason;
|
const reason = data._reason;
|
||||||
|
@ -1182,8 +1162,8 @@ callbacks["AskForCardsChosen"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForPoxi"] = (jsonData) => {
|
callbacks["AskForPoxi"] = (dat) => {
|
||||||
const { type, data, extra_data, cancelable } = JSON.parse(jsonData);
|
const { type, data, extra_data, cancelable } = dat;
|
||||||
|
|
||||||
roomScene.state = "replying";
|
roomScene.state = "replying";
|
||||||
roomScene.popupBox.sourceComponent =
|
roomScene.popupBox.sourceComponent =
|
||||||
|
@ -1208,8 +1188,7 @@ callbacks["AskForPoxi"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForMoveCardInBoard"] = (jsonData) => {
|
callbacks["AskForMoveCardInBoard"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const { cards, cardsPosition, generalNames, playerIds } = data;
|
const { cards, cardsPosition, generalNames, playerIds } = data;
|
||||||
|
|
||||||
roomScene.state = "replying";
|
roomScene.state = "replying";
|
||||||
|
@ -1241,15 +1220,13 @@ callbacks["AskForMoveCardInBoard"] = (jsonData) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["MoveCards"] = (jsonData) => {
|
callbacks["MoveCards"] = (moves) => {
|
||||||
// jsonData: merged moves
|
// jsonData: merged moves
|
||||||
const moves = JSON.parse(jsonData);
|
|
||||||
moveCards(moves);
|
moveCards(moves);
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["PlayCard"] = (jsonData) => {
|
callbacks["PlayCard"] = (playerId) => {
|
||||||
// jsonData: int playerId
|
// jsonData: int playerId
|
||||||
const playerId = parseInt(jsonData);
|
|
||||||
if (playerId === Self.id) {
|
if (playerId === Self.id) {
|
||||||
roomScene.setPrompt(luatr("#PlayCard"), true);
|
roomScene.setPrompt(luatr("#PlayCard"), true);
|
||||||
roomScene.state = "playing";
|
roomScene.state = "playing";
|
||||||
|
@ -1257,9 +1234,8 @@ callbacks["PlayCard"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["LoseSkill"] = (jsonData) => {
|
callbacks["LoseSkill"] = (data) => {
|
||||||
// jsonData: [ int player_id, string skill_name ]
|
// jsonData: [ int player_id, string skill_name ]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const id = data[0];
|
const id = data[0];
|
||||||
const skill_name = data[1];
|
const skill_name = data[1];
|
||||||
const prelight = data[2];
|
const prelight = data[2];
|
||||||
|
@ -1268,9 +1244,8 @@ callbacks["LoseSkill"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AddSkill"] = (jsonData) => {
|
callbacks["AddSkill"] = (data) => {
|
||||||
// jsonData: [ int player_id, string skill_name ]
|
// jsonData: [ int player_id, string skill_name ]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const id = data[0];
|
const id = data[0];
|
||||||
const skill_name = data[1];
|
const skill_name = data[1];
|
||||||
const prelight = data[2];
|
const prelight = data[2];
|
||||||
|
@ -1279,17 +1254,15 @@ callbacks["AddSkill"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["PrelightSkill"] = (jsonData) => {
|
callbacks["PrelightSkill"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const skill_name = data[0];
|
const skill_name = data[0];
|
||||||
const prelight = data[1];
|
const prelight = data[1];
|
||||||
|
|
||||||
dashboard.prelightSkill(skill_name, prelight);
|
dashboard.prelightSkill(skill_name, prelight);
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForUseActiveSkill"] = (jsonData) => {
|
callbacks["AskForUseActiveSkill"] = (data) => {
|
||||||
// jsonData: string skill_name, string prompt
|
// jsonData: string skill_name, string prompt
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const skill_name = data[0];
|
const skill_name = data[0];
|
||||||
const prompt = data[1];
|
const prompt = data[1];
|
||||||
const cancelable = data[2];
|
const cancelable = data[2];
|
||||||
|
@ -1323,9 +1296,8 @@ callbacks["GameLog"] = (jsonData) => {
|
||||||
roomScene.addToLog(jsonData)
|
roomScene.addToLog(jsonData)
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForUseCard"] = (jsonData) => {
|
callbacks["AskForUseCard"] = (data) => {
|
||||||
// jsonData: card, pattern, prompt, cancelable, {}
|
// jsonData: card, pattern, prompt, cancelable, {}
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const cardname = data[0];
|
const cardname = data[0];
|
||||||
const pattern = data[1];
|
const pattern = data[1];
|
||||||
const prompt = data[2];
|
const prompt = data[2];
|
||||||
|
@ -1355,9 +1327,8 @@ callbacks["AskForUseCard"] = (jsonData) => {
|
||||||
cancelButton.enabled = true;
|
cancelButton.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["AskForResponseCard"] = (jsonData) => {
|
callbacks["AskForResponseCard"] = (data) => {
|
||||||
// jsonData: card_name, pattern, prompt, cancelable, {}
|
// jsonData: card_name, pattern, prompt, cancelable, {}
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const cardname = data[0];
|
const cardname = data[0];
|
||||||
const pattern = data[1];
|
const pattern = data[1];
|
||||||
const prompt = data[2];
|
const prompt = data[2];
|
||||||
|
@ -1381,8 +1352,7 @@ callbacks["WaitForNullification"] = () => {
|
||||||
roomScene.state = "notactive";
|
roomScene.state = "notactive";
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["SetPlayerMark"] = (jsonData) => {
|
callbacks["SetPlayerMark"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const player = getPhoto(data[0]);
|
const player = getPhoto(data[0]);
|
||||||
const mark = data[1];
|
const mark = data[1];
|
||||||
const value = data[2] instanceof Object ? data[2] : data[2].toString();
|
const value = data[2] instanceof Object ? data[2] : data[2].toString();
|
||||||
|
@ -1394,8 +1364,7 @@ callbacks["SetPlayerMark"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["SetBanner"] = (jsonData) => {
|
callbacks["SetBanner"] = (data) => {
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
const mark = data[0];
|
const mark = data[0];
|
||||||
const value = data[1] instanceof Object ? data[1] : data[1].toString();
|
const value = data[1] instanceof Object ? data[1] : data[1].toString();
|
||||||
let area = roomScene.banner;
|
let area = roomScene.banner;
|
||||||
|
@ -1406,9 +1375,8 @@ callbacks["SetBanner"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["Animate"] = (jsonData) => {
|
callbacks["Animate"] = (data) => {
|
||||||
// jsonData: [Object object]
|
// jsonData: [Object object]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "Indicate":
|
case "Indicate":
|
||||||
data.to.forEach(item => {
|
data.to.forEach(item => {
|
||||||
|
@ -1471,9 +1439,8 @@ callbacks["Animate"] = (jsonData) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["LogEvent"] = (jsonData) => {
|
callbacks["LogEvent"] = (data) => {
|
||||||
// jsonData: [Object object]
|
// jsonData: [Object object]
|
||||||
const data = JSON.parse(jsonData);
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "Damage": {
|
case "Damage": {
|
||||||
const item = getPhotoOrDashboard(data.to);
|
const item = getPhotoOrDashboard(data.to);
|
||||||
|
@ -1557,8 +1524,7 @@ callbacks["GameOver"] = (jsonData) => {
|
||||||
// roomScene.isStarted = false;
|
// roomScene.isStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["FillAG"] = (j) => {
|
callbacks["FillAG"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const ids = data[0];
|
const ids = data[0];
|
||||||
roomScene.manualBox.sourceComponent =
|
roomScene.manualBox.sourceComponent =
|
||||||
Qt.createComponent("../RoomElement/AG.qml");
|
Qt.createComponent("../RoomElement/AG.qml");
|
||||||
|
@ -1570,9 +1536,8 @@ callbacks["AskForAG"] = (j) => {
|
||||||
roomScene.manualBox.item.interactive = true;
|
roomScene.manualBox.item.interactive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["TakeAG"] = (j) => {
|
callbacks["TakeAG"] = (data) => {
|
||||||
if (!roomScene.manualBox.item) return;
|
if (!roomScene.manualBox.item) return;
|
||||||
const data = JSON.parse(j);
|
|
||||||
const pid = data[0];
|
const pid = data[0];
|
||||||
const cid = data[1];
|
const cid = data[1];
|
||||||
const item = getPhoto(pid);
|
const item = getPhoto(pid);
|
||||||
|
@ -1584,8 +1549,7 @@ callbacks["TakeAG"] = (j) => {
|
||||||
|
|
||||||
callbacks["CloseAG"] = () => roomScene.manualBox.item.close();
|
callbacks["CloseAG"] = () => roomScene.manualBox.item.close();
|
||||||
|
|
||||||
callbacks["CustomDialog"] = (j) => {
|
callbacks["CustomDialog"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const path = data.path;
|
const path = data.path;
|
||||||
const dat = data.data;
|
const dat = data.data;
|
||||||
roomScene.state = "replying";
|
roomScene.state = "replying";
|
||||||
|
@ -1595,8 +1559,7 @@ callbacks["CustomDialog"] = (j) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["MiniGame"] = (j) => {
|
callbacks["MiniGame"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const game = data.type;
|
const game = data.type;
|
||||||
const dat = data.data;
|
const dat = data.data;
|
||||||
const gdata = lcall("GetMiniGame", game, Self.id, JSON.stringify(dat));
|
const gdata = lcall("GetMiniGame", game, Self.id, JSON.stringify(dat));
|
||||||
|
@ -1607,15 +1570,13 @@ callbacks["MiniGame"] = (j) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["UpdateMiniGame"] = (j) => {
|
callbacks["UpdateMiniGame"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
if (roomScene.popupBox.item) {
|
if (roomScene.popupBox.item) {
|
||||||
roomScene.popupBox.item.updateData(data);
|
roomScene.popupBox.item.updateData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["UpdateLimitSkill"] = (j) => {
|
callbacks["UpdateLimitSkill"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const id = data[0];
|
const id = data[0];
|
||||||
const skill = data[1];
|
const skill = data[1];
|
||||||
const time = data[2];
|
const time = data[2];
|
||||||
|
@ -1636,8 +1597,7 @@ callbacks["UpdateRoundNum"] = (j) => {
|
||||||
roomScene.miscStatus.roundNum = data;
|
roomScene.miscStatus.roundNum = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
callbacks["UpdateGameData"] = (j) => {
|
callbacks["UpdateGameData"] = (data) => {
|
||||||
const data = JSON.parse(j);
|
|
||||||
const id = data[0];
|
const id = data[0];
|
||||||
const total = data[1];
|
const total = data[1];
|
||||||
const win = data[2];
|
const win = data[2];
|
||||||
|
|
14
Fk/main.qml
14
Fk/main.qml
|
@ -261,21 +261,11 @@ Window {
|
||||||
|
|
||||||
// fake global functions
|
// fake global functions
|
||||||
function lcall(funcName, ...params) {
|
function lcall(funcName, ...params) {
|
||||||
const ret = Backend.callLuaFunction(funcName, [...params]);
|
return Backend.callLuaFunction(funcName, [...params]);
|
||||||
try {
|
|
||||||
return JSON.parse(ret);
|
|
||||||
} catch (e) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function leval(lua) {
|
function leval(lua) {
|
||||||
const ret = Backend.evalLuaExp(`return json.encode(${lua})`);
|
return Backend.evalLuaExp(`return ${lua}`);
|
||||||
try {
|
|
||||||
return JSON.parse(ret);
|
|
||||||
} catch (e) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function luatr(src) {
|
function luatr(src) {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
---@field public current ClientPlayer @ 当前回合玩家
|
---@field public current ClientPlayer @ 当前回合玩家
|
||||||
---@field public discard_pile integer[] @ 弃牌堆
|
---@field public discard_pile integer[] @ 弃牌堆
|
||||||
---@field public observing boolean
|
---@field public observing boolean
|
||||||
|
---@field public record any
|
||||||
Client = AbstractRoom:subclass('Client')
|
Client = AbstractRoom:subclass('Client')
|
||||||
|
|
||||||
-- load client classes
|
-- load client classes
|
||||||
|
@ -23,11 +24,17 @@ local pattern_refresh_commands = {
|
||||||
"AskForResponseCard",
|
"AskForResponseCard",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- 无需进行JSON.parse,但可能传入JSON字符串的command
|
||||||
|
local no_decode_commands = {
|
||||||
|
"ErrorMsg",
|
||||||
|
"Heartbeat",
|
||||||
|
}
|
||||||
|
|
||||||
function Client:initialize()
|
function Client:initialize()
|
||||||
AbstractRoom.initialize(self)
|
AbstractRoom.initialize(self)
|
||||||
self.client = fk.ClientInstance
|
self.client = fk.ClientInstance
|
||||||
self.notifyUI = function(self, command, jsonData)
|
self.notifyUI = function(self, command, data)
|
||||||
fk.Backend:emitNotifyUI(command, jsonData)
|
fk.Backend:notifyUI(command, data)
|
||||||
end
|
end
|
||||||
self.client.callback = function(_self, command, jsonData, isRequest)
|
self.client.callback = function(_self, command, jsonData, isRequest)
|
||||||
if self.recording then
|
if self.recording then
|
||||||
|
@ -35,6 +42,18 @@ function Client:initialize()
|
||||||
end
|
end
|
||||||
|
|
||||||
local cb = fk.client_callback[command]
|
local cb = fk.client_callback[command]
|
||||||
|
local data
|
||||||
|
if table.contains(no_decode_commands, command) then
|
||||||
|
data = jsonData
|
||||||
|
else
|
||||||
|
local err, ret = pcall(json.decode, jsonData)
|
||||||
|
if err == false then
|
||||||
|
-- 不关心报错
|
||||||
|
data = jsonData
|
||||||
|
else
|
||||||
|
data = ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if table.contains(pattern_refresh_commands, command) then
|
if table.contains(pattern_refresh_commands, command) then
|
||||||
Fk.currentResponsePattern = nil
|
Fk.currentResponsePattern = nil
|
||||||
|
@ -42,9 +61,9 @@ function Client:initialize()
|
||||||
end
|
end
|
||||||
|
|
||||||
if (type(cb) == "function") then
|
if (type(cb) == "function") then
|
||||||
cb(jsonData)
|
cb(data)
|
||||||
else
|
else
|
||||||
self:notifyUI(command, jsonData);
|
self:notifyUI(command, data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -58,7 +77,7 @@ function Client:initialize()
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param id integer
|
---@param id integer
|
||||||
---@return ClientPlayer?
|
---@return ClientPlayer
|
||||||
function Client:getPlayerById(id)
|
function Client:getPlayerById(id)
|
||||||
if id == Self.id then return Self end
|
if id == Self.id then return Self end
|
||||||
for _, p in ipairs(self.players) do
|
for _, p in ipairs(self.players) do
|
||||||
|
@ -95,7 +114,7 @@ function Client:moveCards(moves)
|
||||||
for _, move in ipairs(moves) do
|
for _, move in ipairs(moves) do
|
||||||
if move.from and move.fromArea then
|
if move.from and move.fromArea then
|
||||||
local from = self:getPlayerById(move.from)
|
local from = self:getPlayerById(move.from)
|
||||||
self:notifyUI("MaxCard", json.encode{
|
self:notifyUI("MaxCard", {
|
||||||
pcardMax = from:getMaxCards(),
|
pcardMax = from:getMaxCards(),
|
||||||
id = move.from,
|
id = move.from,
|
||||||
})
|
})
|
||||||
|
@ -114,7 +133,7 @@ function Client:moveCards(moves)
|
||||||
|
|
||||||
if move.to and move.toArea then
|
if move.to and move.toArea then
|
||||||
local ids = move.ids
|
local ids = move.ids
|
||||||
self:notifyUI("MaxCard", json.encode{
|
self:notifyUI("MaxCard", {
|
||||||
pcardMax = self:getPlayerById(move.to):getMaxCards(),
|
pcardMax = self:getPlayerById(move.to):getMaxCards(),
|
||||||
id = move.to,
|
id = move.to,
|
||||||
})
|
})
|
||||||
|
@ -172,6 +191,7 @@ local function parseMsg(msg, nocolor)
|
||||||
|
|
||||||
local from = getPlayerStr(data.from, "#0C8F0C")
|
local from = getPlayerStr(data.from, "#0C8F0C")
|
||||||
|
|
||||||
|
---@type any
|
||||||
local to = data.to or Util.DummyTable
|
local to = data.to or Util.DummyTable
|
||||||
local to_str = {}
|
local to_str = {}
|
||||||
for _, id in ipairs(to) do
|
for _, id in ipairs(to) do
|
||||||
|
@ -179,6 +199,7 @@ local function parseMsg(msg, nocolor)
|
||||||
end
|
end
|
||||||
to = table.concat(to_str, ", ")
|
to = table.concat(to_str, ", ")
|
||||||
|
|
||||||
|
---@type any
|
||||||
local card = data.card or Util.DummyTable
|
local card = data.card or Util.DummyTable
|
||||||
local allUnknown = true
|
local allUnknown = true
|
||||||
local unknownCount = 0
|
local unknownCount = 0
|
||||||
|
@ -238,20 +259,16 @@ end
|
||||||
function Client:setCardNote(ids, msg)
|
function Client:setCardNote(ids, msg)
|
||||||
for _, id in ipairs(ids) do
|
for _, id in ipairs(ids) do
|
||||||
if id ~= -1 then
|
if id ~= -1 then
|
||||||
self:notifyUI("SetCardFootnote", json.encode{ id, parseMsg(msg, true) })
|
self:notifyUI("SetCardFootnote", { id, parseMsg(msg, true) })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["SetCardFootnote"] = function(jsonData)
|
fk.client_callback["SetCardFootnote"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
ClientInstance:setCardNote(data[1], data[2]);
|
ClientInstance:setCardNote(data[1], data[2]);
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["Setup"] = function(jsonData)
|
local function setup(id, name, avatar)
|
||||||
-- jsonData: [ int id, string screenName, string avatar ]
|
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, name, avatar = data[1], data[2], data[3]
|
|
||||||
local self = fk.Self
|
local self = fk.Self
|
||||||
self:setId(id)
|
self:setId(id)
|
||||||
self:setScreenName(name)
|
self:setScreenName(name)
|
||||||
|
@ -259,16 +276,21 @@ fk.client_callback["Setup"] = function(jsonData)
|
||||||
Self = ClientPlayer:new(fk.Self)
|
Self = ClientPlayer:new(fk.Self)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["EnterRoom"] = function(jsonData)
|
fk.client_callback["Setup"] = function(data)
|
||||||
|
-- jsonData: [ int id, string screenName, string avatar ]
|
||||||
|
local id, name, avatar = data[1], data[2], data[3]
|
||||||
|
setup(id, name, avatar)
|
||||||
|
end
|
||||||
|
|
||||||
|
fk.client_callback["EnterRoom"] = function(_data)
|
||||||
Self = ClientPlayer:new(fk.Self)
|
Self = ClientPlayer:new(fk.Self)
|
||||||
ClientInstance = Client:new() -- clear old client data
|
ClientInstance = Client:new() -- clear old client data
|
||||||
ClientInstance.players = {Self}
|
ClientInstance.players = {Self}
|
||||||
ClientInstance.alive_players = {Self}
|
ClientInstance.alive_players = {Self}
|
||||||
ClientInstance.discard_pile = {}
|
ClientInstance.discard_pile = {}
|
||||||
|
|
||||||
local _data = json.decode(jsonData)
|
|
||||||
local data = _data[3]
|
local data = _data[3]
|
||||||
ClientInstance.enter_room_data = jsonData;
|
ClientInstance.enter_room_data = json.encode(_data);
|
||||||
ClientInstance.room_settings = data
|
ClientInstance.room_settings = data
|
||||||
table.insertTableIfNeed(
|
table.insertTableIfNeed(
|
||||||
data.disabledPack,
|
data.disabledPack,
|
||||||
|
@ -276,25 +298,23 @@ fk.client_callback["EnterRoom"] = function(jsonData)
|
||||||
)
|
)
|
||||||
ClientInstance.disabled_packs = data.disabledPack
|
ClientInstance.disabled_packs = data.disabledPack
|
||||||
ClientInstance.disabled_generals = data.disabledGenerals
|
ClientInstance.disabled_generals = data.disabledGenerals
|
||||||
ClientInstance:notifyUI("EnterRoom", jsonData)
|
ClientInstance:notifyUI("EnterRoom", _data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddPlayer"] = function(jsonData)
|
fk.client_callback["AddPlayer"] = function(data)
|
||||||
-- jsonData: [ int id, string screenName, string avatar ]
|
-- jsonData: [ int id, string screenName, string avatar ]
|
||||||
-- when other player enter the room, we create clientplayer(C and lua) for them
|
-- when other player enter the room, we create clientplayer(C and lua) for them
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, name, avatar, time = data[1], data[2], data[3], data[5]
|
local id, name, avatar, time = data[1], data[2], data[3], data[5]
|
||||||
local player = fk.ClientInstance:addPlayer(id, name, avatar)
|
local player = fk.ClientInstance:addPlayer(id, name, avatar)
|
||||||
player:addTotalGameTime(time or 0) -- 以防再次智迟
|
player:addTotalGameTime(time or 0) -- 以防再次智迟
|
||||||
local p = ClientPlayer:new(player)
|
local p = ClientPlayer:new(player)
|
||||||
table.insert(ClientInstance.players, p)
|
table.insert(ClientInstance.players, p)
|
||||||
table.insert(ClientInstance.alive_players, p)
|
table.insert(ClientInstance.alive_players, p)
|
||||||
ClientInstance:notifyUI("AddPlayer", jsonData)
|
ClientInstance:notifyUI("AddPlayer", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["RemovePlayer"] = function(jsonData)
|
fk.client_callback["RemovePlayer"] = function(data)
|
||||||
-- jsonData: [ int id ]
|
-- jsonData: [ int id ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id = data[1]
|
local id = data[1]
|
||||||
for _, p in ipairs(ClientInstance.players) do
|
for _, p in ipairs(ClientInstance.players) do
|
||||||
if p.player:getId() == id then
|
if p.player:getId() == id then
|
||||||
|
@ -305,14 +325,13 @@ fk.client_callback["RemovePlayer"] = function(jsonData)
|
||||||
end
|
end
|
||||||
if id ~= Self.id then
|
if id ~= Self.id then
|
||||||
fk.ClientInstance:removePlayer(id)
|
fk.ClientInstance:removePlayer(id)
|
||||||
ClientInstance:notifyUI("RemovePlayer", jsonData)
|
ClientInstance:notifyUI("RemovePlayer", data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddObserver"] = function(jsonData)
|
fk.client_callback["AddObserver"] = function(data)
|
||||||
-- jsonData: [ int id, string screenName, string avatar ]
|
-- jsonData: [ int id, string screenName, string avatar ]
|
||||||
-- when observer enter the room, we create lua clientplayer for them
|
-- when observer enter the room, we create lua clientplayer for them
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, name, avatar = data[1], data[2], data[3]
|
local id, name, avatar = data[1], data[2], data[3]
|
||||||
local player = {
|
local player = {
|
||||||
getId = function() return id end,
|
getId = function() return id end,
|
||||||
|
@ -323,8 +342,7 @@ fk.client_callback["AddObserver"] = function(jsonData)
|
||||||
table.insert(ClientInstance.observers, p)
|
table.insert(ClientInstance.observers, p)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["RemoveObserver"] = function(jsonData)
|
fk.client_callback["RemoveObserver"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id = data[1]
|
local id = data[1]
|
||||||
for _, p in ipairs(ClientInstance.observers) do
|
for _, p in ipairs(ClientInstance.observers) do
|
||||||
if p.player:getId() == id then
|
if p.player:getId() == id then
|
||||||
|
@ -334,8 +352,7 @@ fk.client_callback["RemoveObserver"] = function(jsonData)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["ArrangeSeats"] = function(jsonData)
|
fk.client_callback["ArrangeSeats"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local n = #ClientInstance.players
|
local n = #ClientInstance.players
|
||||||
local players = {}
|
local players = {}
|
||||||
|
|
||||||
|
@ -352,12 +369,11 @@ fk.client_callback["ArrangeSeats"] = function(jsonData)
|
||||||
|
|
||||||
ClientInstance.players = players
|
ClientInstance.players = players
|
||||||
|
|
||||||
ClientInstance:notifyUI("ArrangeSeats", jsonData)
|
ClientInstance:notifyUI("ArrangeSeats", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["PropertyUpdate"] = function(jsonData)
|
fk.client_callback["PropertyUpdate"] = function(data)
|
||||||
-- jsonData: [ int id, string property_name, value ]
|
-- jsonData: [ int id, string property_name, value ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, name, value = data[1], data[2], data[3]
|
local id, name, value = data[1], data[2], data[3]
|
||||||
local p = ClientInstance:getPlayerById(id)
|
local p = ClientInstance:getPlayerById(id)
|
||||||
p[name] = value
|
p[name] = value
|
||||||
|
@ -370,16 +386,15 @@ fk.client_callback["PropertyUpdate"] = function(jsonData)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ClientInstance:notifyUI("PropertyUpdate", jsonData)
|
ClientInstance:notifyUI("PropertyUpdate", data)
|
||||||
ClientInstance:notifyUI("MaxCard", json.encode{
|
ClientInstance:notifyUI("MaxCard", {
|
||||||
pcardMax = ClientInstance:getPlayerById(id):getMaxCards(),
|
pcardMax = ClientInstance:getPlayerById(id):getMaxCards(),
|
||||||
id = id,
|
id = id,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AskForCardChosen"] = function(jsonData)
|
fk.client_callback["AskForCardChosen"] = function(data)
|
||||||
-- jsonData: [ int target_id, string flag, int reason ]
|
-- jsonData: [ int target_id, string flag, int reason ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, flag, reason, prompt = data[1], data[2], data[3], data[4]
|
local id, flag, reason, prompt = data[1], data[2], data[3], data[4]
|
||||||
local target = ClientInstance:getPlayerById(id)
|
local target = ClientInstance:getPlayerById(id)
|
||||||
local hand = target.player_cards[Player.Hand]
|
local hand = target.player_cards[Player.Hand]
|
||||||
|
@ -411,13 +426,13 @@ fk.client_callback["AskForCardChosen"] = function(jsonData)
|
||||||
ui_data._reason = reason
|
ui_data._reason = reason
|
||||||
ui_data._prompt = prompt
|
ui_data._prompt = prompt
|
||||||
end
|
end
|
||||||
ClientInstance:notifyUI("AskForCardChosen", json.encode(ui_data))
|
ClientInstance:notifyUI("AskForCardChosen", ui_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AskForCardsChosen"] = function(jsonData)
|
fk.client_callback["AskForCardsChosen"] = function(data)
|
||||||
-- jsonData: [ int target_id, int min, int max, string flag, int reason ]
|
-- jsonData: [ int target_id, int min, int max, string flag, int reason ]
|
||||||
local data = json.decode(jsonData)
|
local id, min, max, flag, reason, prompt = table.unpack(data)
|
||||||
local id, min, max, flag, reason, prompt = data[1], data[2], data[3], data[4], data[5], data[6]
|
--data[1], data[2], data[3], data[4], data[5], data[6]
|
||||||
local target = ClientInstance:getPlayerById(id)
|
local target = ClientInstance:getPlayerById(id)
|
||||||
local hand = target.player_cards[Player.Hand]
|
local hand = target.player_cards[Player.Hand]
|
||||||
local equip = target.player_cards[Player.Equip]
|
local equip = target.player_cards[Player.Equip]
|
||||||
|
@ -452,7 +467,7 @@ fk.client_callback["AskForCardsChosen"] = function(jsonData)
|
||||||
ui_data._reason = reason
|
ui_data._reason = reason
|
||||||
ui_data._prompt = prompt
|
ui_data._prompt = prompt
|
||||||
end
|
end
|
||||||
ClientInstance:notifyUI("AskForCardsChosen", json.encode(ui_data))
|
ClientInstance:notifyUI("AskForCardsChosen", ui_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- separated moves to many moves(one card per move)
|
--- separated moves to many moves(one card per move)
|
||||||
|
@ -646,23 +661,21 @@ local function sendMoveCardLog(move)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["MoveCards"] = function(jsonData)
|
fk.client_callback["MoveCards"] = function(raw_moves)
|
||||||
-- jsonData: CardsMoveStruct[]
|
-- jsonData: CardsMoveStruct[]
|
||||||
local raw_moves = json.decode(jsonData)
|
|
||||||
local separated = separateMoves(raw_moves)
|
local separated = separateMoves(raw_moves)
|
||||||
ClientInstance:moveCards(separated)
|
ClientInstance:moveCards(separated)
|
||||||
local merged = mergeMoves(separated)
|
local merged = mergeMoves(separated)
|
||||||
ClientInstance:notifyUI("MoveCards", json.encode(merged))
|
ClientInstance:notifyUI("MoveCards", merged)
|
||||||
for _, move in ipairs(merged) do
|
for _, move in ipairs(merged) do
|
||||||
sendMoveCardLog(move)
|
sendMoveCardLog(move)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["ShowCard"] = function(jsonData)
|
fk.client_callback["ShowCard"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local from = data.from
|
local from = data.from
|
||||||
local cards = data.cards
|
local cards = data.cards
|
||||||
ClientInstance:notifyUI("MoveCards", json.encode{
|
ClientInstance:notifyUI("MoveCards", {
|
||||||
{
|
{
|
||||||
ids = cards,
|
ids = cards,
|
||||||
fromArea = Card.DrawPile,
|
fromArea = Card.DrawPile,
|
||||||
|
@ -679,15 +692,14 @@ local function updateLimitSkill(pid, skill, times)
|
||||||
if skill:isSwitchSkill() then
|
if skill:isSwitchSkill() then
|
||||||
local _times = ClientInstance:getPlayerById(pid):getSwitchSkillState(skill.switchSkillName) == fk.SwitchYang and 0 or 1
|
local _times = ClientInstance:getPlayerById(pid):getSwitchSkillState(skill.switchSkillName) == fk.SwitchYang and 0 or 1
|
||||||
if times == -1 then _times = -1 end
|
if times == -1 then _times = -1 end
|
||||||
ClientInstance:notifyUI("UpdateLimitSkill", json.encode{ pid, skill.switchSkillName, _times })
|
ClientInstance:notifyUI("UpdateLimitSkill", { pid, skill.switchSkillName, _times })
|
||||||
elseif skill.frequency == Skill.Limited or skill.frequency == Skill.Wake or skill.frequency == Skill.Quest then
|
elseif skill.frequency == Skill.Limited or skill.frequency == Skill.Wake or skill.frequency == Skill.Quest then
|
||||||
ClientInstance:notifyUI("UpdateLimitSkill", json.encode{ pid, skill.name, times })
|
ClientInstance:notifyUI("UpdateLimitSkill", { pid, skill.name, times })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["LoseSkill"] = function(jsonData)
|
fk.client_callback["LoseSkill"] = function(data)
|
||||||
-- jsonData: [ int player_id, string skill_name ]
|
-- jsonData: [ int player_id, string skill_name ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, skill_name, fake = data[1], data[2], data[3]
|
local id, skill_name, fake = data[1], data[2], data[3]
|
||||||
local target = ClientInstance:getPlayerById(id)
|
local target = ClientInstance:getPlayerById(id)
|
||||||
local skill = Fk.skills[skill_name]
|
local skill = Fk.skills[skill_name]
|
||||||
|
@ -695,7 +707,7 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
||||||
if not fake then
|
if not fake then
|
||||||
target:loseSkill(skill)
|
target:loseSkill(skill)
|
||||||
if skill.visible then
|
if skill.visible then
|
||||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
ClientInstance:notifyUI("LoseSkill", data)
|
||||||
end
|
end
|
||||||
elseif skill.visible then
|
elseif skill.visible then
|
||||||
-- 按理说能弄得更好的但还是复制粘贴舒服
|
-- 按理说能弄得更好的但还是复制粘贴舒服
|
||||||
|
@ -711,7 +723,7 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
||||||
|
|
||||||
if table.find(sks, function(s) return s:isInstanceOf(TriggerSkill) end) then
|
if table.find(sks, function(s) return s:isInstanceOf(TriggerSkill) end) then
|
||||||
chk = true
|
chk = true
|
||||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
ClientInstance:notifyUI("LoseSkill", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
local active = table.filter(sks, function(s)
|
local active = table.filter(sks, function(s)
|
||||||
|
@ -720,13 +732,13 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
||||||
|
|
||||||
if #active > 0 then
|
if #active > 0 then
|
||||||
chk = true
|
chk = true
|
||||||
ClientInstance:notifyUI("LoseSkill", json.encode {
|
ClientInstance:notifyUI("LoseSkill", {
|
||||||
id, skill_name,
|
id, skill_name,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
if not chk then
|
if not chk then
|
||||||
ClientInstance:notifyUI("LoseSkill", json.encode {
|
ClientInstance:notifyUI("LoseSkill", {
|
||||||
id, skill_name,
|
id, skill_name,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -735,9 +747,8 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
||||||
updateLimitSkill(id, skill, -1)
|
updateLimitSkill(id, skill, -1)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddSkill"] = function(jsonData)
|
fk.client_callback["AddSkill"] = function(data)
|
||||||
-- jsonData: [ int player_id, string skill_name ]
|
-- jsonData: [ int player_id, string skill_name ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, skill_name, fake = data[1], data[2], data[3]
|
local id, skill_name, fake = data[1], data[2], data[3]
|
||||||
local target = ClientInstance:getPlayerById(id)
|
local target = ClientInstance:getPlayerById(id)
|
||||||
local skill = Fk.skills[skill_name]
|
local skill = Fk.skills[skill_name]
|
||||||
|
@ -745,7 +756,7 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
||||||
if not fake then
|
if not fake then
|
||||||
target:addSkill(skill)
|
target:addSkill(skill)
|
||||||
if skill.visible then
|
if skill.visible then
|
||||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
ClientInstance:notifyUI("AddSkill", data)
|
||||||
end
|
end
|
||||||
elseif skill.visible then
|
elseif skill.visible then
|
||||||
-- 添加假技能:服务器只会传一个主技能来。
|
-- 添加假技能:服务器只会传一个主技能来。
|
||||||
|
@ -758,7 +769,7 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
||||||
|
|
||||||
if table.find(sks, function(s) return s:isInstanceOf(TriggerSkill) end) then
|
if table.find(sks, function(s) return s:isInstanceOf(TriggerSkill) end) then
|
||||||
chk = true
|
chk = true
|
||||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
ClientInstance:notifyUI("AddSkill", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
local active = table.filter(sks, function(s)
|
local active = table.filter(sks, function(s)
|
||||||
|
@ -767,14 +778,14 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
||||||
|
|
||||||
if #active > 0 then
|
if #active > 0 then
|
||||||
chk = true
|
chk = true
|
||||||
ClientInstance:notifyUI("AddSkill", json.encode {
|
ClientInstance:notifyUI("AddSkill", {
|
||||||
id, skill_name,
|
id, skill_name,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 面板上总得有点啥东西表明自己有技能吧 = =
|
-- 面板上总得有点啥东西表明自己有技能吧 = =
|
||||||
if not chk then
|
if not chk then
|
||||||
ClientInstance:notifyUI("AddSkill", json.encode {
|
ClientInstance:notifyUI("AddSkill", {
|
||||||
id, skill_name,
|
id, skill_name,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -787,30 +798,28 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
||||||
updateLimitSkill(id, skill, target:usedSkillTimes(skill_name, Player.HistoryGame))
|
updateLimitSkill(id, skill, target:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AskForUseActiveSkill"] = function(jsonData)
|
fk.client_callback["AskForUseActiveSkill"] = function(data)
|
||||||
-- jsonData: [ string skill_name, string prompt, bool cancelable. json extra_data ]
|
-- jsonData: [ string skill_name, string prompt, bool cancelable. json extra_data ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local skill = Fk.skills[data[1]]
|
local skill = Fk.skills[data[1]]
|
||||||
local extra_data = data[4]
|
local extra_data = data[4]
|
||||||
skill._extra_data = extra_data
|
skill._extra_data = extra_data
|
||||||
|
|
||||||
Fk.currentResponseReason = extra_data.skillName
|
Fk.currentResponseReason = extra_data.skillName
|
||||||
ClientInstance:notifyUI("AskForUseActiveSkill", jsonData)
|
ClientInstance:notifyUI("AskForUseActiveSkill", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AskForUseCard"] = function(jsonData)
|
fk.client_callback["AskForUseCard"] = function(data)
|
||||||
Fk.currentResponsePattern = json.decode(jsonData)[2]
|
Fk.currentResponsePattern = data[2]
|
||||||
ClientInstance:notifyUI("AskForUseCard", jsonData)
|
ClientInstance:notifyUI("AskForUseCard", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AskForResponseCard"] = function(jsonData)
|
fk.client_callback["AskForResponseCard"] = function(data)
|
||||||
Fk.currentResponsePattern = json.decode(jsonData)[2]
|
Fk.currentResponsePattern = data[2]
|
||||||
ClientInstance:notifyUI("AskForResponseCard", jsonData)
|
ClientInstance:notifyUI("AskForResponseCard", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["SetPlayerMark"] = function(jsonData)
|
fk.client_callback["SetPlayerMark"] = function(data)
|
||||||
-- jsonData: [ int id, string mark, int value ]
|
-- jsonData: [ int id, string mark, int value ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local player, mark, value = data[1], data[2], data[3]
|
local player, mark, value = data[1], data[2], data[3]
|
||||||
local p = ClientInstance:getPlayerById(player)
|
local p = ClientInstance:getPlayerById(player)
|
||||||
p:setMark(mark, value)
|
p:setMark(mark, value)
|
||||||
|
@ -825,37 +834,34 @@ fk.client_callback["SetPlayerMark"] = function(jsonData)
|
||||||
if text == "#hidden" then return end
|
if text == "#hidden" then return end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ClientInstance:notifyUI("SetPlayerMark", jsonData)
|
ClientInstance:notifyUI("SetPlayerMark", data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["SetBanner"] = function(jsonData)
|
fk.client_callback["SetBanner"] = function(data)
|
||||||
-- jsonData: [ int id, string mark, int value ]
|
-- jsonData: [ int id, string mark, int value ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local mark, value = data[1], data[2]
|
local mark, value = data[1], data[2]
|
||||||
ClientInstance:setBanner(mark, value)
|
ClientInstance:setBanner(mark, value)
|
||||||
|
|
||||||
if string.sub(mark, 1, 1) == "@" then
|
if string.sub(mark, 1, 1) == "@" then
|
||||||
ClientInstance:notifyUI("SetBanner", jsonData)
|
ClientInstance:notifyUI("SetBanner", data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["SetCardMark"] = function(jsonData)
|
fk.client_callback["SetCardMark"] = function(data)
|
||||||
-- jsonData: [ int id, string mark, int value ]
|
-- jsonData: [ int id, string mark, int value ]
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local card, mark, value = data[1], data[2], data[3]
|
local card, mark, value = data[1], data[2], data[3]
|
||||||
Fk:getCardById(card):setMark(mark, value)
|
Fk:getCardById(card):setMark(mark, value)
|
||||||
|
|
||||||
ClientInstance:notifyUI("UpdateCard", tostring(card))
|
ClientInstance:notifyUI("UpdateCard", card)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["Chat"] = function(jsonData)
|
fk.client_callback["Chat"] = function(data)
|
||||||
-- jsonData: { int type, int sender, string msg }
|
-- jsonData: { int type, int sender, string msg }
|
||||||
local data = json.decode(jsonData)
|
|
||||||
if data.type == 1 then
|
if data.type == 1 then
|
||||||
data.general = ""
|
data.general = ""
|
||||||
data.time = os.date("%H:%M:%S")
|
data.time = os.date("%H:%M:%S")
|
||||||
ClientInstance:notifyUI("Chat", json.encode(data))
|
ClientInstance:notifyUI("Chat", data)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -873,37 +879,32 @@ fk.client_callback["Chat"] = function(jsonData)
|
||||||
end
|
end
|
||||||
data.userName = p.player:getScreenName()
|
data.userName = p.player:getScreenName()
|
||||||
data.time = os.date("%H:%M:%S")
|
data.time = os.date("%H:%M:%S")
|
||||||
ClientInstance:notifyUI("Chat", json.encode(data))
|
ClientInstance:notifyUI("Chat", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["GameLog"] = function(jsonData)
|
fk.client_callback["GameLog"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
ClientInstance:appendLog(data)
|
ClientInstance:appendLog(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["LogEvent"] = function(jsonData)
|
fk.client_callback["LogEvent"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
if data.type == "Death" then
|
if data.type == "Death" then
|
||||||
table.removeOne(
|
table.removeOne(
|
||||||
ClientInstance.alive_players,
|
ClientInstance.alive_players,
|
||||||
ClientInstance:getPlayerById(data.to)
|
ClientInstance:getPlayerById(data.to)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
ClientInstance:notifyUI("LogEvent", jsonData)
|
ClientInstance:notifyUI("LogEvent", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddCardUseHistory"] = function(jsonData)
|
fk.client_callback["AddCardUseHistory"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
Self:addCardUseHistory(data[1], data[2])
|
Self:addCardUseHistory(data[1], data[2])
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["SetCardUseHistory"] = function(jsonData)
|
fk.client_callback["SetCardUseHistory"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
Self:setCardUseHistory(data[1], data[2], data[3])
|
Self:setCardUseHistory(data[1], data[2], data[3])
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddSkillUseHistory"] = function(jsonData)
|
fk.client_callback["AddSkillUseHistory"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local playerid, skill_name, time = data[1], data[2], data[3]
|
local playerid, skill_name, time = data[1], data[2], data[3]
|
||||||
local player = ClientInstance:getPlayerById(playerid)
|
local player = ClientInstance:getPlayerById(playerid)
|
||||||
player:addSkillUseHistory(skill_name, time)
|
player:addSkillUseHistory(skill_name, time)
|
||||||
|
@ -913,8 +914,7 @@ fk.client_callback["AddSkillUseHistory"] = function(jsonData)
|
||||||
updateLimitSkill(playerid, Fk.skills[skill_name], player:usedSkillTimes(skill_name, Player.HistoryGame))
|
updateLimitSkill(playerid, Fk.skills[skill_name], player:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["SetSkillUseHistory"] = function(jsonData)
|
fk.client_callback["SetSkillUseHistory"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local id, skill_name, time, scope = data[1], data[2], data[3], data[4]
|
local id, skill_name, time, scope = data[1], data[2], data[3], data[4]
|
||||||
local player = ClientInstance:getPlayerById(id)
|
local player = ClientInstance:getPlayerById(id)
|
||||||
player:setSkillUseHistory(skill_name, time, scope)
|
player:setSkillUseHistory(skill_name, time, scope)
|
||||||
|
@ -924,8 +924,7 @@ fk.client_callback["SetSkillUseHistory"] = function(jsonData)
|
||||||
updateLimitSkill(id, Fk.skills[skill_name], player:usedSkillTimes(skill_name, Player.HistoryGame))
|
updateLimitSkill(id, Fk.skills[skill_name], player:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddVirtualEquip"] = function(jsonData)
|
fk.client_callback["AddVirtualEquip"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local cname = data.name
|
local cname = data.name
|
||||||
local player = ClientInstance:getPlayerById(data.player)
|
local player = ClientInstance:getPlayerById(data.player)
|
||||||
local subcards = data.subcards
|
local subcards = data.subcards
|
||||||
|
@ -934,8 +933,7 @@ fk.client_callback["AddVirtualEquip"] = function(jsonData)
|
||||||
player:addVirtualEquip(c)
|
player:addVirtualEquip(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["RemoveVirtualEquip"] = function(jsonData)
|
fk.client_callback["RemoveVirtualEquip"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local player = ClientInstance:getPlayerById(data.player)
|
local player = ClientInstance:getPlayerById(data.player)
|
||||||
player:removeVirtualEquip(data.id)
|
player:removeVirtualEquip(data.id)
|
||||||
end
|
end
|
||||||
|
@ -944,38 +942,35 @@ fk.client_callback["Heartbeat"] = function()
|
||||||
ClientInstance.client:notifyServer("Heartbeat", "")
|
ClientInstance.client:notifyServer("Heartbeat", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["ChangeSelf"] = function(jsonData)
|
fk.client_callback["ChangeSelf"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
local p = ClientInstance:getPlayerById(data.id)
|
||||||
ClientInstance:getPlayerById(data.id).player_cards[Player.Hand] = data.handcards
|
p.player_cards[Player.Hand] = data.handcards
|
||||||
ClientInstance:getPlayerById(data.id).special_cards = data.special_cards
|
p.special_cards = data.special_cards
|
||||||
ClientInstance:notifyUI("ChangeSelf", data.id)
|
ClientInstance:notifyUI("ChangeSelf", data.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["UpdateQuestSkillUI"] = function(jsonData)
|
fk.client_callback["UpdateQuestSkillUI"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local player, skillName, usedTimes = data[1], data[2], data[3]
|
local player, skillName, usedTimes = data[1], data[2], data[3]
|
||||||
updateLimitSkill(player, Fk.skills[skillName], usedTimes)
|
updateLimitSkill(player, Fk.skills[skillName], usedTimes)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["UpdateGameData"] = function(jsonData)
|
fk.client_callback["UpdateGameData"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local player, total, win, run = data[1], data[2], data[3], data[4]
|
local player, total, win, run = data[1], data[2], data[3], data[4]
|
||||||
player = ClientInstance:getPlayerById(player)
|
player = ClientInstance:getPlayerById(player)
|
||||||
if player then
|
if player then
|
||||||
player.player:setGameData(total, win, run)
|
player.player:setGameData(total, win, run)
|
||||||
end
|
end
|
||||||
|
|
||||||
ClientInstance:notifyUI("UpdateGameData", jsonData)
|
ClientInstance:notifyUI("UpdateGameData", data)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddTotalGameTime"] = function(jsonData)
|
fk.client_callback["AddTotalGameTime"] = function(data)
|
||||||
local data = json.decode(jsonData)
|
|
||||||
local player, time = data[1], data[2]
|
local player, time = data[1], data[2]
|
||||||
player = ClientInstance:getPlayerById(player)
|
player = ClientInstance:getPlayerById(player)
|
||||||
if player then
|
if player then
|
||||||
player.player:addTotalGameTime(time)
|
player.player:addTotalGameTime(time)
|
||||||
if player == Self then
|
if player == Self then
|
||||||
ClientInstance:notifyUI("AddTotalGameTime", jsonData)
|
ClientInstance:notifyUI("AddTotalGameTime", data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1051,30 +1046,184 @@ fk.client_callback["EnterLobby"] = function(jsonData)
|
||||||
c:notifyUI("EnterLobby", jsonData)
|
c:notifyUI("EnterLobby", jsonData)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["PrintCard"] = function(j)
|
fk.client_callback["PrintCard"] = function(data)
|
||||||
local data = json.decode(j)
|
|
||||||
local n, s, num = table.unpack(data)
|
local n, s, num = table.unpack(data)
|
||||||
local cd = Fk:cloneCard(n, s, num)
|
local cd = Fk:cloneCard(n, s, num)
|
||||||
Fk:_addPrintedCard(cd)
|
Fk:_addPrintedCard(cd)
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["AddBuddy"] = function(j)
|
fk.client_callback["AddBuddy"] = function(data)
|
||||||
local c = ClientInstance
|
local c = ClientInstance
|
||||||
local data = json.decode(j)
|
|
||||||
local id, hand = table.unpack(data)
|
local id, hand = table.unpack(data)
|
||||||
local to = c:getPlayerById(id)
|
local to = c:getPlayerById(id)
|
||||||
Self:addBuddy(to)
|
Self:addBuddy(to)
|
||||||
to.player_cards[Player.Hand] = hand
|
to.player_cards[Player.Hand] = hand
|
||||||
end
|
end
|
||||||
|
|
||||||
fk.client_callback["RmBuddy"] = function(j)
|
fk.client_callback["RmBuddy"] = function(data)
|
||||||
local c = ClientInstance
|
local c = ClientInstance
|
||||||
local id = tonumber(j)
|
local id = data
|
||||||
local to = c:getPlayerById(id)
|
local to = c:getPlayerById(id)
|
||||||
Self:removeBuddy(to)
|
Self:removeBuddy(to)
|
||||||
to.player_cards[Player.Hand] = table.map(to.player_cards, function() return -1 end)
|
to.player_cards[Player.Hand] = table.map(to.player_cards, function() return -1 end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function loadPlayerSummary(pdata)
|
||||||
|
local f = fk.client_callback["PropertyUpdate"]
|
||||||
|
local id = pdata.d[1]
|
||||||
|
local properties = {
|
||||||
|
"general", "deputyGeneral", "maxHp", "hp", "shield", "gender", "kingdom",
|
||||||
|
"dead", "role", "rest", "seat", "phase", "faceup", "chained",
|
||||||
|
"sealedSlots",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, k in ipairs(properties) do
|
||||||
|
if pdata.p[k] ~= nil then
|
||||||
|
f{ id, k, pdata.p[k] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local card_moves = {}
|
||||||
|
local cards = pdata.c
|
||||||
|
if #cards[Player.Hand] ~= 0 then
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(cards[Player.Hand]) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = { moveInfo = info, to = id, toArea = Card.PlayerHand }
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
if #cards[Player.Equip] ~= 0 then
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(cards[Player.Equip]) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = { moveInfo = info, to = id, toArea = Card.PlayerEquip }
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
if #cards[Player.Judge] ~= 0 then
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(cards[Player.Judge]) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = { moveInfo = info, to = id, toArea = Card.PlayerJudge }
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(pdata.sc) do
|
||||||
|
local info = {}
|
||||||
|
for _, i in ipairs(v) do
|
||||||
|
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
||||||
|
end
|
||||||
|
local move = {
|
||||||
|
moveInfo = info,
|
||||||
|
to = id,
|
||||||
|
toArea = Card.PlayerSpecial,
|
||||||
|
specialName = k,
|
||||||
|
specialVisible = Self.id == id,
|
||||||
|
}
|
||||||
|
table.insert(card_moves, move)
|
||||||
|
end
|
||||||
|
|
||||||
|
if #card_moves > 0 then
|
||||||
|
-- TODO: visibility
|
||||||
|
fk.client_callback["MoveCards"](card_moves)
|
||||||
|
end
|
||||||
|
|
||||||
|
f = fk.client_callback["SetPlayerMark"]
|
||||||
|
for k, v in pairs(pdata.m) do
|
||||||
|
f{ id, k, v }
|
||||||
|
end
|
||||||
|
|
||||||
|
f = fk.client_callback["AddSkill"]
|
||||||
|
for _, v in pairs(pdata.s) do
|
||||||
|
f{ id, v }
|
||||||
|
end
|
||||||
|
|
||||||
|
f = fk.client_callback["AddCardUseHistory"]
|
||||||
|
for k, v in pairs(pdata.ch) do
|
||||||
|
if v[1] > 0 then
|
||||||
|
f{ k, v[1] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
f = fk.client_callback["SetSkillUseHistory"]
|
||||||
|
for k, v in pairs(pdata.sh) do
|
||||||
|
if v[4] > 0 then
|
||||||
|
f{ id, k, v[1], 1 }
|
||||||
|
f{ id, k, v[2], 2 }
|
||||||
|
f{ id, k, v[3], 3 }
|
||||||
|
f{ id, k, v[4], 4 }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function loadRoomSummary(data)
|
||||||
|
local players = data.p
|
||||||
|
|
||||||
|
fk.client_callback["StartGame"]("")
|
||||||
|
|
||||||
|
for _, pid in ipairs(data.circle) do
|
||||||
|
if pid ~= data.you then
|
||||||
|
fk.client_callback["AddPlayer"](players[tostring(pid)].d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fk.client_callback["ArrangeSeats"](data.circle)
|
||||||
|
|
||||||
|
for _, d in ipairs(data.pc) do
|
||||||
|
local cd = Fk:cloneCard(table.unpack(d))
|
||||||
|
Fk:_addPrintedCard(cd)
|
||||||
|
end
|
||||||
|
|
||||||
|
for cid, marks in pairs(data.cm) do
|
||||||
|
for k, v in pairs(marks) do
|
||||||
|
Fk:getCardById(tonumber(cid)):setMark(k, v)
|
||||||
|
ClientInstance:notifyUI("UpdateCard", cid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(data.b) do
|
||||||
|
fk.client_callback["SetBanner"]{ k, v }
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, pid in ipairs(data.circle) do
|
||||||
|
local pdata = data.p[tostring(pid)]
|
||||||
|
loadPlayerSummary(pdata)
|
||||||
|
end
|
||||||
|
|
||||||
|
ClientInstance:notifyUI("UpdateDrawPile", data.dp)
|
||||||
|
ClientInstance:notifyUI("UpdateRoundNum", data.rnd)
|
||||||
|
end
|
||||||
|
|
||||||
|
fk.client_callback["Reconnect"] = function(data)
|
||||||
|
local players = data.p
|
||||||
|
local setup_data = players[tostring(data.you)].d
|
||||||
|
setup(setup_data[1], setup_data[2], setup_data[3])
|
||||||
|
fk.client_callback["AddTotalGameTime"]{ setup_data[1], setup_data[5] }
|
||||||
|
|
||||||
|
local enter_room_data = data.d
|
||||||
|
table.insert(enter_room_data, 1, #data.circle)
|
||||||
|
fk.client_callback["EnterLobby"]("")
|
||||||
|
fk.client_callback["EnterRoom"](enter_room_data)
|
||||||
|
|
||||||
|
loadRoomSummary(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
fk.client_callback["Observe"] = function(data)
|
||||||
|
local players = data.p
|
||||||
|
|
||||||
|
local setup_data = players[tostring(data.you)].d
|
||||||
|
setup(setup_data[1], setup_data[2], setup_data[3])
|
||||||
|
|
||||||
|
local enter_room_data = data.d
|
||||||
|
table.insert(enter_room_data, 1, #data.circle)
|
||||||
|
fk.client_callback["EnterRoom"](enter_room_data)
|
||||||
|
fk.client_callback["StartGame"]("")
|
||||||
|
|
||||||
|
loadRoomSummary(data)
|
||||||
|
end
|
||||||
|
|
||||||
-- Create ClientInstance (used by Lua)
|
-- Create ClientInstance (used by Lua)
|
||||||
ClientInstance = Client:new()
|
ClientInstance = Client:new()
|
||||||
dofile "lua/client/client_util.lua"
|
dofile "lua/client/client_util.lua"
|
||||||
|
|
|
@ -9,7 +9,7 @@ end
|
||||||
function GetGeneralData(name)
|
function GetGeneralData(name)
|
||||||
local general = Fk.generals[name]
|
local general = Fk.generals[name]
|
||||||
if general == nil then general = Fk.generals["diaochan"] end
|
if general == nil then general = Fk.generals["diaochan"] end
|
||||||
return json.encode {
|
return {
|
||||||
package = general.package.name,
|
package = general.package.name,
|
||||||
extension = general.package.extensionName,
|
extension = general.package.extensionName,
|
||||||
kingdom = general.kingdom,
|
kingdom = general.kingdom,
|
||||||
|
@ -65,16 +65,16 @@ function GetGeneralDetail(name)
|
||||||
table.insertIfNeed(ret.companions, g.name)
|
table.insertIfNeed(ret.companions, g.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetSameGenerals(name)
|
function GetSameGenerals(name)
|
||||||
return json.encode(Fk:getSameGenerals(name))
|
return Fk:getSameGenerals(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
function IsCompanionWith(general, general2)
|
function IsCompanionWith(general, general2)
|
||||||
local _general, _general2 = Fk.generals[general], Fk.generals[general2]
|
local _general, _general2 = Fk.generals[general], Fk.generals[general2]
|
||||||
return json.encode(_general:isCompanionWith(_general2))
|
return _general:isCompanionWith(_general2)
|
||||||
end
|
end
|
||||||
|
|
||||||
local cardSubtypeStrings = {
|
local cardSubtypeStrings = {
|
||||||
|
@ -89,7 +89,7 @@ local cardSubtypeStrings = {
|
||||||
|
|
||||||
function GetCardData(id, virtualCardForm)
|
function GetCardData(id, virtualCardForm)
|
||||||
local card = Fk:getCardById(id)
|
local card = Fk:getCardById(id)
|
||||||
if card == nil then return json.encode{
|
if card == nil then return {
|
||||||
cid = id,
|
cid = id,
|
||||||
known = false
|
known = false
|
||||||
} end
|
} end
|
||||||
|
@ -124,7 +124,7 @@ function GetCardData(id, virtualCardForm)
|
||||||
ret.subtype = cardSubtypeStrings[virtualCard.sub_type]
|
ret.subtype = cardSubtypeStrings[virtualCard.sub_type]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetCardExtensionByName(cardName)
|
function GetCardExtensionByName(cardName)
|
||||||
|
@ -133,11 +133,11 @@ function GetCardExtensionByName(cardName)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetAllMods()
|
function GetAllMods()
|
||||||
return json.encode(Fk.extensions)
|
return Fk.extensions
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetAllModNames()
|
function GetAllModNames()
|
||||||
return json.encode(Fk.extension_names)
|
return Fk.extension_names
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetAllGeneralPack()
|
function GetAllGeneralPack()
|
||||||
|
@ -147,28 +147,28 @@ function GetAllGeneralPack()
|
||||||
table.insert(ret, name)
|
table.insert(ret, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetGenerals(pack_name)
|
function GetGenerals(pack_name)
|
||||||
if not Fk.packages[pack_name] then return "[]" end
|
if not Fk.packages[pack_name] then return {} end
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for _, g in ipairs(Fk.packages[pack_name].generals) do
|
for _, g in ipairs(Fk.packages[pack_name].generals) do
|
||||||
if not g.total_hidden then
|
if not g.total_hidden then
|
||||||
table.insert(ret, g.name)
|
table.insert(ret, g.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function SearchAllGenerals(word)
|
function SearchAllGenerals(word)
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for _, name in ipairs(Fk.package_names) do
|
for _, name in ipairs(Fk.package_names) do
|
||||||
if Fk.packages[name].type == Package.GeneralPack then
|
if Fk.packages[name].type == Package.GeneralPack then
|
||||||
table.insertTable(ret, json.decode(SearchGenerals(name, word)))
|
table.insertTable(ret, SearchGenerals(name, word))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function SearchGenerals(pack_name, word)
|
function SearchGenerals(pack_name, word)
|
||||||
|
@ -179,7 +179,7 @@ function SearchGenerals(pack_name, word)
|
||||||
table.insert(ret, g.name)
|
table.insert(ret, g.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function UpdatePackageEnable(pkg, enabled)
|
function UpdatePackageEnable(pkg, enabled)
|
||||||
|
@ -220,7 +220,7 @@ function GetAllCardPack()
|
||||||
table.insert(ret, name)
|
table.insert(ret, name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetCards(pack_name)
|
function GetCards(pack_name)
|
||||||
|
@ -228,7 +228,7 @@ function GetCards(pack_name)
|
||||||
for _, c in ipairs(Fk.packages[pack_name].cards) do
|
for _, c in ipairs(Fk.packages[pack_name].cards) do
|
||||||
table.insert(ret, c.id)
|
table.insert(ret, c.id)
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetCardSkill(cid)
|
function GetCardSkill(cid)
|
||||||
|
@ -236,7 +236,7 @@ function GetCardSkill(cid)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetCardSpecialSkills(cid)
|
function GetCardSpecialSkills(cid)
|
||||||
return json.encode(Fk:getCardById(cid).special_skills or Util.DummyTable)
|
return Fk:getCardById(cid).special_skills or Util.DummyTable
|
||||||
end
|
end
|
||||||
|
|
||||||
function DistanceTo(from, to)
|
function DistanceTo(from, to)
|
||||||
|
@ -246,21 +246,21 @@ function DistanceTo(from, to)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPile(id, name)
|
function GetPile(id, name)
|
||||||
return json.encode(ClientInstance:getPlayerById(id):getPile(name) or {})
|
return ClientInstance:getPlayerById(id):getPile(name) or Util.DummyTable
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetAllPiles(id)
|
function GetAllPiles(id)
|
||||||
return json.encode(ClientInstance:getPlayerById(id).special_cards or Util.DummyTable)
|
return ClientInstance:getPlayerById(id).special_cards or Util.DummyTable
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPlayerSkills(id)
|
function GetPlayerSkills(id)
|
||||||
local p = ClientInstance:getPlayerById(id)
|
local p = ClientInstance:getPlayerById(id)
|
||||||
return json.encode(table.map(p.player_skills, function(s)
|
return table.map(p.player_skills, function(s)
|
||||||
return s.visible and {
|
return s.visible and {
|
||||||
name = s.name,
|
name = s.name,
|
||||||
description = Fk:getDescription(s.name),
|
description = Fk:getDescription(s.name),
|
||||||
} or nil
|
} or nil
|
||||||
end))
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param card string | integer
|
---@param card string | integer
|
||||||
|
@ -278,11 +278,11 @@ function CanUseCard(card, player, extra_data_str)
|
||||||
if skill:isInstanceOf(ViewAsSkill) then
|
if skill:isInstanceOf(ViewAsSkill) then
|
||||||
c = skill:viewAs(selected_cards)
|
c = skill:viewAs(selected_cards)
|
||||||
if not c then
|
if not c then
|
||||||
return "false"
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- ActiveSkill should return true here
|
-- ActiveSkill should return true here
|
||||||
return "true"
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -294,13 +294,13 @@ function CanUseCard(card, player, extra_data_str)
|
||||||
if min_target > 0 then
|
if min_target > 0 then
|
||||||
for _, p in ipairs(ClientInstance.players) do
|
for _, p in ipairs(ClientInstance.players) do
|
||||||
if c.skill:targetFilter(p.id, {}, {}, c, extra_data) then
|
if c.skill:targetFilter(p.id, {}, {}, c, extra_data) then
|
||||||
return "true"
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return "false"
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function CardProhibitedUse(card)
|
function CardProhibitedUse(card)
|
||||||
|
@ -317,11 +317,11 @@ function CardProhibitedUse(card)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if c == nil then
|
if c == nil then
|
||||||
return "true"
|
return true
|
||||||
else
|
else
|
||||||
ret = Self:prohibitUse(c)
|
ret = Self:prohibitUse(c)
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param card string | integer
|
---@param card string | integer
|
||||||
|
@ -331,7 +331,7 @@ end
|
||||||
function CanUseCardToTarget(card, to_select, selected, extra_data_str)
|
function CanUseCardToTarget(card, to_select, selected, extra_data_str)
|
||||||
local extra_data = extra_data_str == "" and nil or json.decode(extra_data_str)
|
local extra_data = extra_data_str == "" and nil or json.decode(extra_data_str)
|
||||||
if ClientInstance:getPlayerById(to_select).dead then
|
if ClientInstance:getPlayerById(to_select).dead then
|
||||||
return "false"
|
return false
|
||||||
end
|
end
|
||||||
local c ---@type Card
|
local c ---@type Card
|
||||||
local selected_cards
|
local selected_cards
|
||||||
|
@ -345,7 +345,7 @@ function CanUseCardToTarget(card, to_select, selected, extra_data_str)
|
||||||
|
|
||||||
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c, extra_data)
|
local ret = c.skill:targetFilter(to_select, selected, selected_cards, c, extra_data)
|
||||||
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), c)
|
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), c)
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param card string | integer
|
---@param card string | integer
|
||||||
|
@ -362,7 +362,7 @@ function CanSelectCardForSkill(card, to_select, selected_targets)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = c.skill:cardFilter(to_select, selected_cards, selected_targets)
|
local ret = c.skill:cardFilter(to_select, selected_cards, selected_targets)
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param card string | integer
|
---@param card string | integer
|
||||||
|
@ -379,14 +379,14 @@ function CardFeasible(card, selected_targets)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = c.skill:feasible(selected_targets, selected_cards, Self, c)
|
local ret = c.skill:feasible(selected_targets, selected_cards, Self, c)
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handle skills
|
-- Handle skills
|
||||||
|
|
||||||
function GetSkillData(skill_name)
|
function GetSkillData(skill_name)
|
||||||
local skill = Fk.skills[skill_name]
|
local skill = Fk.skills[skill_name]
|
||||||
if not skill then return "null" end
|
if not skill then return nil end
|
||||||
local freq = "notactive"
|
local freq = "notactive"
|
||||||
if skill:isInstanceOf(ActiveSkill) or skill:isInstanceOf(ViewAsSkill) then
|
if skill:isInstanceOf(ActiveSkill) or skill:isInstanceOf(ViewAsSkill) then
|
||||||
freq = "active"
|
freq = "active"
|
||||||
|
@ -399,7 +399,7 @@ function GetSkillData(skill_name)
|
||||||
elseif skill.frequency == Skill.Quest then
|
elseif skill.frequency == Skill.Quest then
|
||||||
frequency = "quest"
|
frequency = "quest"
|
||||||
end
|
end
|
||||||
return json.encode{
|
return {
|
||||||
skill = Fk:translate(skill_name),
|
skill = Fk:translate(skill_name),
|
||||||
orig_skill = skill_name,
|
orig_skill = skill_name,
|
||||||
extension = skill.package.extensionName,
|
extension = skill.package.extensionName,
|
||||||
|
@ -439,7 +439,7 @@ function ActiveCanUse(skill_name, extra_data_str)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function ActiveSkillPrompt(skill_name, selected, selected_targets)
|
function ActiveSkillPrompt(skill_name, selected, selected_targets)
|
||||||
|
@ -452,7 +452,7 @@ function ActiveSkillPrompt(skill_name, selected, selected_targets)
|
||||||
ret = skill.prompt
|
ret = skill.prompt
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret or "")
|
return ret or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
function ActiveCardFilter(skill_name, to_select, selected, selected_targets)
|
function ActiveCardFilter(skill_name, to_select, selected, selected_targets)
|
||||||
|
@ -465,7 +465,7 @@ function ActiveCardFilter(skill_name, to_select, selected, selected_targets)
|
||||||
ret = skill:cardFilter(to_select, selected)
|
ret = skill:cardFilter(to_select, selected)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function ActiveTargetFilter(skill_name, to_select, selected, selected_cards, extra_data)
|
function ActiveTargetFilter(skill_name, to_select, selected, selected_cards, extra_data)
|
||||||
|
@ -482,7 +482,7 @@ function ActiveTargetFilter(skill_name, to_select, selected, selected_cards, ext
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function ActiveFeasible(skill_name, selected, selected_cards)
|
function ActiveFeasible(skill_name, selected, selected_cards)
|
||||||
|
@ -498,7 +498,7 @@ function ActiveFeasible(skill_name, selected, selected_cards)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function CanViewAs(skill_name, card_ids)
|
function CanViewAs(skill_name, card_ids)
|
||||||
|
@ -511,7 +511,7 @@ function CanViewAs(skill_name, card_ids)
|
||||||
ret = true
|
ret = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
-- card_name may be id, name of card, or json string
|
-- card_name may be id, name of card, or json string
|
||||||
|
@ -532,12 +532,12 @@ function CardFitPattern(card_name, pattern)
|
||||||
ret = exp:match(c)
|
ret = exp:match(c)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
return "true"
|
return true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
ret = exp:matchExp(card_name)
|
ret = exp:matchExp(card_name)
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function SkillFitPattern(skill_name, pattern)
|
function SkillFitPattern(skill_name, pattern)
|
||||||
|
@ -547,7 +547,7 @@ function SkillFitPattern(skill_name, pattern)
|
||||||
local exp = Exppattern:Parse(pattern)
|
local exp = Exppattern:Parse(pattern)
|
||||||
ret = exp:matchExp(skill.pattern)
|
ret = exp:matchExp(skill.pattern)
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function CardProhibitedResponse(card)
|
function CardProhibitedResponse(card)
|
||||||
|
@ -564,11 +564,11 @@ function CardProhibitedResponse(card)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if c == nil then
|
if c == nil then
|
||||||
return "true"
|
return true
|
||||||
else
|
else
|
||||||
ret = Self:prohibitResponse(c)
|
ret = Self:prohibitResponse(c)
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function SkillCanResponse(skill_name, cardResponsing)
|
function SkillCanResponse(skill_name, cardResponsing)
|
||||||
|
@ -577,13 +577,13 @@ function SkillCanResponse(skill_name, cardResponsing)
|
||||||
if skill and skill:isInstanceOf(ViewAsSkill) then
|
if skill and skill:isInstanceOf(ViewAsSkill) then
|
||||||
ret = skill:enabledAtResponse(Self, cardResponsing)
|
ret = skill:enabledAtResponse(Self, cardResponsing)
|
||||||
end
|
end
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetVirtualEquip(player, cid)
|
function GetVirtualEquip(player, cid)
|
||||||
local c = ClientInstance:getPlayerById(player):getVirualEquip(cid)
|
local c = ClientInstance:getPlayerById(player):getVirualEquip(cid)
|
||||||
if not c then return "null" end
|
if not c then return nil end
|
||||||
return json.encode{
|
return {
|
||||||
name = c.name,
|
name = c.name,
|
||||||
cid = c.subcards[1],
|
cid = c.subcards[1],
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,7 @@ function GetExpandPileOfSkill(skillName)
|
||||||
end
|
end
|
||||||
|
|
||||||
if type(e) == "table" then
|
if type(e) == "table" then
|
||||||
return json.encode(e)
|
return e
|
||||||
else
|
else
|
||||||
return e or ""
|
return e or ""
|
||||||
end
|
end
|
||||||
|
@ -615,15 +615,15 @@ function GetGameModes()
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
table.sort(ret, function(a, b) return a.name > b.name end)
|
table.sort(ret, function(a, b) return a.name > b.name end)
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetInteractionOfSkill(skill_name)
|
function GetInteractionOfSkill(skill_name)
|
||||||
local skill = Fk.skills[skill_name]
|
local skill = Fk.skills[skill_name]
|
||||||
if skill and skill.interaction then
|
if skill and skill.interaction then
|
||||||
return json.encode(skill:interaction())
|
return skill:interaction()
|
||||||
end
|
end
|
||||||
return "null"
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function SetInteractionDataOfSkill(skill_name, data)
|
function SetInteractionDataOfSkill(skill_name, data)
|
||||||
|
@ -642,13 +642,13 @@ end
|
||||||
function GetPlayerHandcards(pid)
|
function GetPlayerHandcards(pid)
|
||||||
local c = ClientInstance
|
local c = ClientInstance
|
||||||
local p = c:getPlayerById(pid)
|
local p = c:getPlayerById(pid)
|
||||||
return p and json.encode(p.player_cards[Player.Hand]) or ""
|
return p and p.player_cards[Player.Hand] or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPlayerEquips(pid)
|
function GetPlayerEquips(pid)
|
||||||
local c = ClientInstance
|
local c = ClientInstance
|
||||||
local p = c:getPlayerById(pid)
|
local p = c:getPlayerById(pid)
|
||||||
return json.encode(p.player_cards[Player.Equip])
|
return p.player_cards[Player.Equip]
|
||||||
end
|
end
|
||||||
|
|
||||||
function ResetClientLua()
|
function ResetClientLua()
|
||||||
|
@ -673,20 +673,20 @@ function ResetAddPlayer(j)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetRoomConfig()
|
function GetRoomConfig()
|
||||||
return json.encode(ClientInstance.room_settings)
|
return ClientInstance.room_settings
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPlayerGameData(pid)
|
function GetPlayerGameData(pid)
|
||||||
local c = ClientInstance
|
local c = ClientInstance
|
||||||
local p = c:getPlayerById(pid)
|
local p = c:getPlayerById(pid)
|
||||||
if not p then return "[0, 0, 0, 0]" end
|
if not p then return {0, 0, 0, 0} end
|
||||||
local raw = p.player:getGameData()
|
local raw = p.player:getGameData()
|
||||||
local ret = {}
|
local ret = {}
|
||||||
for _, i in fk.qlist(raw) do
|
for _, i in fk.qlist(raw) do
|
||||||
table.insert(ret, i)
|
table.insert(ret, i)
|
||||||
end
|
end
|
||||||
table.insert(ret, p.player:getTotalGameTime())
|
table.insert(ret, p.player:getTotalGameTime())
|
||||||
return json.encode(ret)
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function SetPlayerGameData(pid, data)
|
function SetPlayerGameData(pid, data)
|
||||||
|
@ -708,7 +708,7 @@ end
|
||||||
|
|
||||||
function CheckSurrenderAvailable(playedTime)
|
function CheckSurrenderAvailable(playedTime)
|
||||||
local curMode = ClientInstance.room_settings.gameMode
|
local curMode = ClientInstance.room_settings.gameMode
|
||||||
return json.encode(Fk.game_modes[curMode]:surrenderFunc(playedTime))
|
return Fk.game_modes[curMode]:surrenderFunc(playedTime)
|
||||||
end
|
end
|
||||||
|
|
||||||
function SaveRecord()
|
function SaveRecord()
|
||||||
|
@ -756,22 +756,22 @@ end
|
||||||
|
|
||||||
function PoxiFilter(poxi_type, to_select, selected, data, extra_data)
|
function PoxiFilter(poxi_type, to_select, selected, data, extra_data)
|
||||||
local poxi = Fk.poxi_methods[poxi_type]
|
local poxi = Fk.poxi_methods[poxi_type]
|
||||||
if not poxi then return "false" end
|
if not poxi then return false end
|
||||||
return json.encode(poxi.card_filter(to_select, selected, data, extra_data))
|
return poxi.card_filter(to_select, selected, data, extra_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PoxiFeasible(poxi_type, selected, data, extra_data)
|
function PoxiFeasible(poxi_type, selected, data, extra_data)
|
||||||
local poxi = Fk.poxi_methods[poxi_type]
|
local poxi = Fk.poxi_methods[poxi_type]
|
||||||
if not poxi then return "false" end
|
if not poxi then return false end
|
||||||
return json.encode(poxi.feasible(selected, data, extra_data))
|
return poxi.feasible(selected, data, extra_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetQmlMark(mtype, name, value, p)
|
function GetQmlMark(mtype, name, value, p)
|
||||||
local spec = Fk.qml_marks[mtype]
|
local spec = Fk.qml_marks[mtype]
|
||||||
if not spec then return "{}" end
|
if not spec then return {} end
|
||||||
p = ClientInstance:getPlayerById(p)
|
p = ClientInstance:getPlayerById(p)
|
||||||
value = json.decode(value)
|
value = json.decode(value)
|
||||||
return json.encode {
|
return {
|
||||||
qml_path = type(spec.qml_path) == "function" and spec.qml_path(name, value, p) or spec.qml_path,
|
qml_path = type(spec.qml_path) == "function" and spec.qml_path(name, value, p) or spec.qml_path,
|
||||||
text = spec.how_to_show(name, value, p)
|
text = spec.how_to_show(name, value, p)
|
||||||
}
|
}
|
||||||
|
@ -781,7 +781,7 @@ function GetMiniGame(gtype, p, data)
|
||||||
local spec = Fk.mini_games[gtype]
|
local spec = Fk.mini_games[gtype]
|
||||||
p = ClientInstance:getPlayerById(p)
|
p = ClientInstance:getPlayerById(p)
|
||||||
data = json.decode(data)
|
data = json.decode(data)
|
||||||
return json.encode {
|
return {
|
||||||
qml_path = type(spec.qml_path) == "function" and spec.qml_path(p, data) or spec.qml_path,
|
qml_path = type(spec.qml_path) == "function" and spec.qml_path(p, data) or spec.qml_path,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,7 +38,7 @@ function AbstractRoom:getPlayerById(id) end
|
||||||
--- 获取一张牌所处的区域。
|
--- 获取一张牌所处的区域。
|
||||||
---@param cardId integer | Card @ 要获得区域的那张牌,可以是Card或者一个id
|
---@param cardId integer | Card @ 要获得区域的那张牌,可以是Card或者一个id
|
||||||
---@return CardArea @ 这张牌的区域
|
---@return CardArea @ 这张牌的区域
|
||||||
function AbstractRoom:getCardArea(cardId) end
|
function AbstractRoom:getCardArea(cardId) return Card.Unknown end
|
||||||
|
|
||||||
function AbstractRoom:setBanner(name, value)
|
function AbstractRoom:setBanner(name, value)
|
||||||
if value == 0 then value = nil end
|
if value == 0 then value = nil end
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
---@class Matcher
|
---@class Matcher
|
||||||
---@field public trueName string[]
|
---@field public trueName? string[]
|
||||||
---@field public number integer[]
|
---@field public number? integer[]
|
||||||
---@field public suit string[]
|
---@field public suit? string[]
|
||||||
---@field public place string[]
|
---@field public place? string[]
|
||||||
---@field public name string[]
|
---@field public name? string[]
|
||||||
---@field public cardType string[]
|
---@field public cardType? string[]
|
||||||
---@field public id integer[]
|
---@field public id? integer[]
|
||||||
|
|
||||||
-- v0.2.6改动: cardType会被解析为trueName数组和name数组,而不是自己单独成立
|
-- v0.2.6改动: cardType会被解析为trueName数组和name数组,而不是自己单独成立
|
||||||
|
|
||||||
|
|
|
@ -449,11 +449,14 @@ end
|
||||||
|
|
||||||
-- override default string.len
|
-- override default string.len
|
||||||
string.rawlen = string.len
|
string.rawlen = string.len
|
||||||
|
|
||||||
|
---@param self string
|
||||||
---@diagnostic disable-next-line: duplicate-set-field
|
---@diagnostic disable-next-line: duplicate-set-field
|
||||||
function string:len()
|
function string:len()
|
||||||
return utf8.len(self)
|
return utf8.len(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param self string
|
||||||
---@param delimiter string
|
---@param delimiter string
|
||||||
---@return string[]
|
---@return string[]
|
||||||
function string:split(delimiter)
|
function string:split(delimiter)
|
||||||
|
@ -470,16 +473,20 @@ function string:split(delimiter)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param self string
|
||||||
function string:startsWith(start)
|
function string:startsWith(start)
|
||||||
return self:sub(1, #start) == start
|
return self:sub(1, #start) == start
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param self string
|
||||||
function string:endsWith(e)
|
function string:endsWith(e)
|
||||||
return e == "" or self:sub(-#e) == e
|
return e == "" or self:sub(-#e) == e
|
||||||
end
|
end
|
||||||
|
|
||||||
FileIO = {
|
FileIO = {
|
||||||
pwd = fk.QmlBackend_pwd,
|
pwd = fk.QmlBackend_pwd,
|
||||||
|
|
||||||
|
---@return string[]
|
||||||
ls = function(filename)
|
ls = function(filename)
|
||||||
if filename == nil then
|
if filename == nil then
|
||||||
return fk.QmlBackend_ls(".")
|
return fk.QmlBackend_ls(".")
|
||||||
|
|
|
@ -11,7 +11,30 @@ package.path = package.path .. ";./lua/lib/?.lua"
|
||||||
class = require "middleclass"
|
class = require "middleclass"
|
||||||
|
|
||||||
-- json: 提供json处理支持,能解析JSON和生成JSON
|
-- json: 提供json处理支持,能解析JSON和生成JSON
|
||||||
json = require "json"
|
-- 仍借助luajson处理简单类型。
|
||||||
|
local luajson = require "json"
|
||||||
|
json = {
|
||||||
|
encode = function(val, t)
|
||||||
|
if type(val) ~= "table" then return luajson.encode(val) end
|
||||||
|
t = t or 1 -- Compact
|
||||||
|
---@diagnostic disable-next-line
|
||||||
|
local doc = fk.QJsonDocument_fromVariant(val)
|
||||||
|
local ret = doc:toJson(t)
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
decode = function(str)
|
||||||
|
if str == "null" then return nil end
|
||||||
|
local start = str:sub(1, 1)
|
||||||
|
if start ~= "[" and start ~= "{" then
|
||||||
|
return luajson.decode(str)
|
||||||
|
end
|
||||||
|
---@diagnostic disable-next-line
|
||||||
|
local doc = fk.QJsonDocument_fromJson(str)
|
||||||
|
local ret = doc:toVariant()
|
||||||
|
-- if ret == "" then ret = luajson.decode(str) end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
-- 初始化随机数种子
|
-- 初始化随机数种子
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
|
|
|
@ -24,10 +24,6 @@ SPlayerList = {}
|
||||||
---@return integer microsecond
|
---@return integer microsecond
|
||||||
function fk:GetMicroSecond()end
|
function fk:GetMicroSecond()end
|
||||||
|
|
||||||
--- construct a QList<ServerPlayer *>.
|
|
||||||
---@return fk.SPlayerList
|
|
||||||
function fk:SPlayerList()end
|
|
||||||
|
|
||||||
function fk.QmlBackend_pwd()end
|
function fk.QmlBackend_pwd()end
|
||||||
|
|
||||||
---@return string[]
|
---@return string[]
|
||||||
|
@ -44,3 +40,5 @@ function fk.qCritical(msg) end
|
||||||
function fk.qInfo(msg) end
|
function fk.qInfo(msg) end
|
||||||
function fk.qDebug(msg) end
|
function fk.qDebug(msg) end
|
||||||
function fk.qWarning(msg) end
|
function fk.qWarning(msg) end
|
||||||
|
|
||||||
|
fk.FK_VER = '0.0.0'
|
||||||
|
|
|
@ -5,41 +5,21 @@
|
||||||
---@class fk.Player
|
---@class fk.Player
|
||||||
FPlayer = {}
|
FPlayer = {}
|
||||||
|
|
||||||
---@return integer id
|
|
||||||
function FPlayer:getId()end
|
function FPlayer:getId()end
|
||||||
|
|
||||||
---@return string name
|
|
||||||
function FPlayer:getScreenName()end
|
function FPlayer:getScreenName()end
|
||||||
|
|
||||||
---@return string avatar
|
|
||||||
function FPlayer:getAvatar()end
|
function FPlayer:getAvatar()end
|
||||||
|
|
||||||
---@class fk.ServerPlayer : fk.Player
|
---@class fk.ServerPlayer : fk.Player
|
||||||
FServerPlayer = {}
|
FServerPlayer = {}
|
||||||
|
|
||||||
--- Send a request to client, and allow client to reply within *timeout* seconds.
|
|
||||||
---
|
|
||||||
--- *timeout* must not be negative or **nil**.
|
|
||||||
---@param command string
|
|
||||||
---@param jsonData string
|
|
||||||
---@param timeout integer
|
|
||||||
function FServerPlayer:doRequest(command,jsonData,timeout)end
|
function FServerPlayer:doRequest(command,jsonData,timeout)end
|
||||||
|
|
||||||
--- Wait for at most *timeout* seconds for reply from client.
|
|
||||||
---
|
|
||||||
--- If *timeout* is negative or **nil**, the function will wait forever until get reply.
|
|
||||||
---@param timeout integer @ seconds to wait
|
|
||||||
---@return string @ JSON data
|
|
||||||
---@overload fun()
|
|
||||||
function FServerPlayer:waitForReply(timeout)end
|
function FServerPlayer:waitForReply(timeout)end
|
||||||
|
|
||||||
--- Notice the client.
|
|
||||||
---@param command string
|
|
||||||
---@param jsonData string
|
|
||||||
function FServerPlayer:doNotify(command,jsonData)end
|
function FServerPlayer:doNotify(command,jsonData)end
|
||||||
|
|
||||||
function FServerPlayer:setBusy(_) end
|
function FServerPlayer:setBusy(_) end
|
||||||
function FServerPlayer:isBusy(_) end
|
function FServerPlayer:isBusy(_) end
|
||||||
function FServerPlayer:setThinking(_) end
|
function FServerPlayer:setThinking(_) end
|
||||||
|
|
||||||
function FServerPlayer:getState() end
|
function FServerPlayer:getState() end
|
||||||
|
|
||||||
|
---@type any
|
||||||
|
fk.Self = nil
|
||||||
|
|
|
@ -1 +1,14 @@
|
||||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
---@diagnostic disable
|
||||||
|
|
||||||
|
---@class fk.Room
|
||||||
|
local Room = {}
|
||||||
|
|
||||||
|
function Room:getId() return 1 end
|
||||||
|
|
||||||
|
---@return fk.SPlayerList
|
||||||
|
function Room:getPlayers() end
|
||||||
|
|
||||||
|
---@return fk.SPlayerList
|
||||||
|
function Room:getObservers() end
|
||||||
|
|
|
@ -1 +1,22 @@
|
||||||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
-- 暂且用来当client.lua用了,别在意
|
||||||
|
|
||||||
|
---@class fk.Client
|
||||||
|
---@field callback fun(s: fk.Client, c: string, j: string, r: boolean)
|
||||||
|
local C = {}
|
||||||
|
|
||||||
|
function C:replyToServer(c, j) end
|
||||||
|
function C:notifyServer(c, j) end
|
||||||
|
function C:addPlayer(id, name, avatar) end
|
||||||
|
function C:removePlayer(id) end
|
||||||
|
function C:changeSelf(id) end
|
||||||
|
function C:saveRecord(j, fname) end
|
||||||
|
|
||||||
|
fk.ClientInstance = C
|
||||||
|
|
||||||
|
---@class fk.QmlBackend
|
||||||
|
local B = {}
|
||||||
|
|
||||||
|
function B:emitNotifyUI(c, j) end
|
||||||
|
|
||||||
|
fk.Backend = B
|
||||||
|
|
|
@ -2,60 +2,8 @@
|
||||||
|
|
||||||
local function tellRoomToObserver(self, player)
|
local function tellRoomToObserver(self, player)
|
||||||
local observee = self.players[1]
|
local observee = self.players[1]
|
||||||
player:doNotify("Setup", json.encode{
|
local summary = self:getSummary(observee, true)
|
||||||
observee.id,
|
player:doNotify("Observe", json.encode(summary))
|
||||||
observee._splayer:getScreenName(),
|
|
||||||
observee._splayer:getAvatar(),
|
|
||||||
})
|
|
||||||
player:doNotify("EnterRoom", json.encode{
|
|
||||||
#self.players, self.timeout, self.settings
|
|
||||||
})
|
|
||||||
player:doNotify("StartGame", "")
|
|
||||||
|
|
||||||
-- send player data
|
|
||||||
for _, p in ipairs(self:getOtherPlayers(observee, false, true)) do
|
|
||||||
player:doNotify("AddPlayer", json.encode{
|
|
||||||
p.id,
|
|
||||||
p._splayer:getScreenName(),
|
|
||||||
p._splayer:getAvatar(),
|
|
||||||
false,
|
|
||||||
p._splayer:getTotalGameTime(),
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local player_circle = {}
|
|
||||||
for i = 1, #self.players do
|
|
||||||
table.insert(player_circle, self.players[i].id)
|
|
||||||
end
|
|
||||||
player:doNotify("ArrangeSeats", json.encode(player_circle))
|
|
||||||
|
|
||||||
-- send printed_cards
|
|
||||||
for i = -2, -math.huge, -1 do
|
|
||||||
local c = Fk.printed_cards[i]
|
|
||||||
if not c then break end
|
|
||||||
player:doNotify("PrintCard", json.encode{ c.name, c.suit, c.number })
|
|
||||||
end
|
|
||||||
|
|
||||||
-- send card marks
|
|
||||||
for id, marks in pairs(self.card_marks) do
|
|
||||||
for k, v in pairs(marks) do
|
|
||||||
player:doNotify("SetCardMark", json.encode{ id, k, v })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- send banners
|
|
||||||
for k, v in pairs(self.banners) do
|
|
||||||
player:doNotify("SetBanner", json.encode{ k, v })
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, p in ipairs(self.players) do
|
|
||||||
self:notifyProperty(player, p, "general")
|
|
||||||
self:notifyProperty(player, p, "deputyGeneral")
|
|
||||||
p:marshal(player, true)
|
|
||||||
end
|
|
||||||
|
|
||||||
player:doNotify("UpdateDrawPile", #self.draw_pile)
|
|
||||||
player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0)
|
|
||||||
|
|
||||||
table.insert(self.observers, {observee.id, player, player:getId()})
|
table.insert(self.observers, {observee.id, player, player:getId()})
|
||||||
end
|
end
|
||||||
|
|
|
@ -655,6 +655,45 @@ function Room:changeKingdom(player, kingdom, sendLog)
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- 房间信息摘要,返回房间的大致信息
|
||||||
|
--- 用于旁观和重连,但也可用于debug
|
||||||
|
function Room:getSummary(player, observe)
|
||||||
|
local printed_cards = {}
|
||||||
|
for i = -2, -math.huge, -1 do
|
||||||
|
local c = Fk.printed_cards[i]
|
||||||
|
if not c then break end
|
||||||
|
table.insert(printed_cards, { c.name, c.suit, c.number })
|
||||||
|
end
|
||||||
|
|
||||||
|
local players = {}
|
||||||
|
for _, p in ipairs(self.players) do
|
||||||
|
players[tostring(p.id)] = p:getSummary(player, observe)
|
||||||
|
end
|
||||||
|
|
||||||
|
local cmarks = {}
|
||||||
|
for k, v in pairs(self.card_marks) do
|
||||||
|
cmarks[tostring(k)] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
you = player.id or player:getId(),
|
||||||
|
-- data for EnterRoom
|
||||||
|
d = {
|
||||||
|
-- #self.players, 留给客户端自己思考
|
||||||
|
self.timeout,
|
||||||
|
self.settings,
|
||||||
|
},
|
||||||
|
pc = printed_cards,
|
||||||
|
cm = cmarks,
|
||||||
|
b = self.banners,
|
||||||
|
|
||||||
|
circle = table.map(self.players, Util.IdMapper),
|
||||||
|
p = players,
|
||||||
|
rnd = self:getTag("RoundCount") or 0,
|
||||||
|
dp = #self.draw_pile,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- 网络通信有关
|
-- 网络通信有关
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
|
@ -192,199 +192,95 @@ function ServerPlayer:waitForReply(timeout)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function assign(t1, t2, k)
|
||||||
|
t1[k] = t2[k]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 获取摘要信息。供重连/旁观使用
|
||||||
|
-- 根据参数,返回一个大表保存自己的信息,客户端自行分析
|
||||||
---@param player ServerPlayer
|
---@param player ServerPlayer
|
||||||
---@param observe? boolean
|
---@param observe? boolean
|
||||||
function ServerPlayer:marshal(player, observe)
|
function ServerPlayer:getSummary(player, observe)
|
||||||
local room = self.room
|
local room = self.room
|
||||||
if not room.game_started then
|
if not room.game_started then
|
||||||
|
local ret = { p = {} }
|
||||||
-- If game does not starts, that mean we are entering room that
|
-- If game does not starts, that mean we are entering room that
|
||||||
-- all players are choosing their generals.
|
-- all players are choosing their generals.
|
||||||
-- Note that when we are in this function, the main thread must be
|
-- Note that when we are in this function, the main thread must be
|
||||||
-- calling delay() or waiting for reply.
|
-- calling delay() or waiting for reply.
|
||||||
if self.role_shown then
|
if self.role_shown then
|
||||||
room:notifyProperty(player, self, "role")
|
-- room:notifyProperty(player, self, "role")
|
||||||
|
ret.p.general = self.general
|
||||||
|
ret.p.deputyGeneral = self.deputyGeneral
|
||||||
|
ret.p.role = self.role
|
||||||
end
|
end
|
||||||
return
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
room:notifyProperty(player, self, "maxHp")
|
local properties = {}
|
||||||
room:notifyProperty(player, self, "hp")
|
|
||||||
room:notifyProperty(player, self, "shield")
|
assign(properties, self, "general")
|
||||||
room:notifyProperty(player, self, "gender")
|
assign(properties, self, "deputyGeneral")
|
||||||
room:notifyProperty(player, self, "kingdom")
|
assign(properties, self, "maxHp")
|
||||||
|
assign(properties, self, "hp")
|
||||||
|
assign(properties, self, "shield")
|
||||||
|
assign(properties, self, "gender")
|
||||||
|
assign(properties, self, "kingdom")
|
||||||
|
|
||||||
if self.dead then
|
if self.dead then
|
||||||
room:notifyProperty(player, self, "dead")
|
assign(properties, self, "dead")
|
||||||
room:notifyProperty(player, self, self.rest > 0 and "rest" or "role")
|
assign(properties, self, self.rest > 0 and "rest" or "role")
|
||||||
else
|
else
|
||||||
room:notifyProperty(player, self, "seat")
|
assign(properties, self, "seat")
|
||||||
room:notifyProperty(player, self, "phase")
|
assign(properties, self, "phase")
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self.faceup then
|
if not self.faceup then
|
||||||
room:notifyProperty(player, self, "faceup")
|
assign(properties, self, "faceup")
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.chained then
|
if self.chained then
|
||||||
room:notifyProperty(player, self, "chained")
|
assign(properties, self, "chained")
|
||||||
end
|
|
||||||
|
|
||||||
local card_moves = {}
|
|
||||||
if #self.player_cards[Player.Hand] ~= 0 then
|
|
||||||
local info = {}
|
|
||||||
for _, i in ipairs(self.player_cards[Player.Hand]) do
|
|
||||||
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
|
||||||
end
|
|
||||||
local move = {
|
|
||||||
moveInfo = info,
|
|
||||||
to = self.id,
|
|
||||||
toArea = Card.PlayerHand
|
|
||||||
}
|
|
||||||
table.insert(card_moves, move)
|
|
||||||
end
|
|
||||||
if #self.player_cards[Player.Equip] ~= 0 then
|
|
||||||
local info = {}
|
|
||||||
for _, i in ipairs(self.player_cards[Player.Equip]) do
|
|
||||||
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
|
||||||
end
|
|
||||||
local move = {
|
|
||||||
moveInfo = info,
|
|
||||||
to = self.id,
|
|
||||||
toArea = Card.PlayerEquip
|
|
||||||
}
|
|
||||||
table.insert(card_moves, move)
|
|
||||||
end
|
|
||||||
if #self.player_cards[Player.Judge] ~= 0 then
|
|
||||||
local info = {}
|
|
||||||
for _, i in ipairs(self.player_cards[Player.Judge]) do
|
|
||||||
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
|
||||||
end
|
|
||||||
local move = {
|
|
||||||
moveInfo = info,
|
|
||||||
to = self.id,
|
|
||||||
toArea = Card.PlayerJudge
|
|
||||||
}
|
|
||||||
table.insert(card_moves, move)
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(self.special_cards) do
|
|
||||||
local info = {}
|
|
||||||
for _, i in ipairs(v) do
|
|
||||||
table.insert(info, { cardId = i, fromArea = Card.DrawPile })
|
|
||||||
end
|
|
||||||
local move = {
|
|
||||||
moveInfo = info,
|
|
||||||
to = self.id,
|
|
||||||
toArea = Card.PlayerSpecial,
|
|
||||||
specialName = k,
|
|
||||||
specialVisible = self == player,
|
|
||||||
}
|
|
||||||
table.insert(card_moves, move)
|
|
||||||
end
|
|
||||||
|
|
||||||
if #card_moves > 0 then
|
|
||||||
room:notifyMoveCards({ player }, card_moves, observe and self.seat == 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(self.mark) do
|
|
||||||
player:doNotify("SetPlayerMark", json.encode{self.id, k, v})
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, s in ipairs(self.player_skills) do
|
|
||||||
player:doNotify("AddSkill", json.encode{self.id, s.name})
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(self.cardUsedHistory) do
|
|
||||||
if v[1] > 0 then
|
|
||||||
player:doNotify("AddCardUseHistory", json.encode{k, v[1]})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(self.skillUsedHistory) do
|
|
||||||
if v[4] > 0 then
|
|
||||||
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[1], 1})
|
|
||||||
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[2], 2})
|
|
||||||
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[3], 3})
|
|
||||||
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[4], 4})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.role_shown then
|
if self.role_shown then
|
||||||
room:notifyProperty(player, self, "role")
|
assign(properties, self, "role")
|
||||||
end
|
end
|
||||||
|
|
||||||
if #self.sealedSlots > 0 then
|
if #self.sealedSlots > 0 then
|
||||||
room:notifyProperty(player, self, "sealedSlots")
|
assign(properties, self, "sealedSlots")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local sp = self._splayer
|
||||||
|
|
||||||
|
return {
|
||||||
|
-- data for Setup/AddPlayer
|
||||||
|
d = {
|
||||||
|
self.id,
|
||||||
|
sp:getScreenName(),
|
||||||
|
sp:getAvatar(),
|
||||||
|
false,
|
||||||
|
sp:getTotalGameTime(),
|
||||||
|
},
|
||||||
|
p = properties,
|
||||||
|
ch = self.cardUsedHistory,
|
||||||
|
sh = self.skillUsedHistory,
|
||||||
|
m = self.mark,
|
||||||
|
s = table.map(self.player_skills, Util.NameMapper),
|
||||||
|
c = self.player_cards,
|
||||||
|
sc = self.special_cards,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function ServerPlayer:reconnect()
|
function ServerPlayer:reconnect()
|
||||||
local room = self.room
|
local room = self.room
|
||||||
self.serverplayer:setState(fk.Player_Online)
|
self.serverplayer:setState(fk.Player_Online)
|
||||||
|
|
||||||
self:doNotify("Setup", json.encode{
|
local summary = room:getSummary(self, false)
|
||||||
self.id,
|
self:doNotify("Reconnect", json.encode(summary))
|
||||||
self._splayer:getScreenName(),
|
|
||||||
self._splayer:getAvatar(),
|
|
||||||
})
|
|
||||||
self:doNotify("AddTotalGameTime", json.encode {
|
|
||||||
self.id,
|
|
||||||
self._splayer:getTotalGameTime(),
|
|
||||||
})
|
|
||||||
|
|
||||||
self:doNotify("EnterLobby", "")
|
|
||||||
self:doNotify("EnterRoom", json.encode{
|
|
||||||
#room.players, room.timeout, room.settings,
|
|
||||||
})
|
|
||||||
self:doNotify("StartGame", "")
|
|
||||||
room:notifyProperty(self, self, "role")
|
room:notifyProperty(self, self, "role")
|
||||||
|
|
||||||
-- send player data
|
|
||||||
for _, p in ipairs(room:getOtherPlayers(self, false, true)) do
|
|
||||||
self:doNotify("AddPlayer", json.encode{
|
|
||||||
p.id,
|
|
||||||
p._splayer:getScreenName(),
|
|
||||||
p._splayer:getAvatar(),
|
|
||||||
false,
|
|
||||||
p._splayer:getTotalGameTime(),
|
|
||||||
})
|
|
||||||
end
|
|
||||||
self:doNotify("RoomOwner", json.encode{ room.room:getOwner():getId() })
|
self:doNotify("RoomOwner", json.encode{ room.room:getOwner():getId() })
|
||||||
|
|
||||||
local player_circle = {}
|
|
||||||
for i = 1, #room.players do
|
|
||||||
table.insert(player_circle, room.players[i].id)
|
|
||||||
end
|
|
||||||
self:doNotify("ArrangeSeats", json.encode(player_circle))
|
|
||||||
|
|
||||||
-- send printed_cards
|
|
||||||
for i = -2, -math.huge, -1 do
|
|
||||||
local c = Fk.printed_cards[i]
|
|
||||||
if not c then break end
|
|
||||||
self:doNotify("PrintCard", json.encode{ c.name, c.suit, c.number })
|
|
||||||
end
|
|
||||||
|
|
||||||
-- send card marks
|
|
||||||
for id, marks in pairs(room.card_marks) do
|
|
||||||
for k, v in pairs(marks) do
|
|
||||||
self:doNotify("SetCardMark", json.encode{ id, k, v })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- send banners
|
|
||||||
for k, v in pairs(room.banners) do
|
|
||||||
self:doNotify("SetBanner", json.encode{ k, v })
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, p in ipairs(room.players) do
|
|
||||||
room:notifyProperty(self, p, "general")
|
|
||||||
room:notifyProperty(self, p, "deputyGeneral")
|
|
||||||
p:marshal(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:doNotify("UpdateDrawPile", #room.draw_pile)
|
|
||||||
self:doNotify("UpdateRoundNum", room:getTag("RoundCount") or 0)
|
|
||||||
|
|
||||||
-- send fake skills
|
-- send fake skills
|
||||||
for _, s in ipairs(self._manually_fake_skills) do
|
for _, s in ipairs(self._manually_fake_skills) do
|
||||||
self:doNotify("AddSkill", json.encode{ self.id, s.name, true })
|
self:doNotify("AddSkill", json.encode{ self.id, s.name, true })
|
||||||
|
|
|
@ -58,21 +58,6 @@ elseif (ANDROID)
|
||||||
QT_ANDROID_EXTRA_LIBS "${LUA_LIB};${SQLITE3_LIB};${CRYPTO_LIB};${SSL_LIB};${SSH_LIB};${GIT_LIB}"
|
QT_ANDROID_EXTRA_LIBS "${LUA_LIB};${SQLITE3_LIB};${CRYPTO_LIB};${SSL_LIB};${SSH_LIB};${GIT_LIB}"
|
||||||
)
|
)
|
||||||
list(REMOVE_ITEM QT_LIB Qt6::QuickControls2)
|
list(REMOVE_ITEM QT_LIB Qt6::QuickControls2)
|
||||||
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(LUA_LIB ${PROJECT_SOURCE_DIR}/lib/wasm/liblua.a)
|
|
||||||
# set(CRYPTO_LIB ${PROJECT_SOURCE_DIR}/lib/wasm/libcrypto.a)
|
|
||||||
# set other libs by yourself
|
|
||||||
set(IDBFS_LIB idbfs.js)
|
|
||||||
include(${FK_WASM_TOOLCHAIN})
|
|
||||||
else ()
|
else ()
|
||||||
set(LUA_LIB lua5.4)
|
set(LUA_LIB lua5.4)
|
||||||
set(SQLITE3_LIB sqlite3)
|
set(SQLITE3_LIB sqlite3)
|
||||||
|
|
|
@ -95,7 +95,7 @@ void PackMan::loadSummary(const QString &jsonData, bool useThread) {
|
||||||
connect(thread, &QThread::finished, [=]() {
|
connect(thread, &QThread::finished, [=]() {
|
||||||
thread->deleteLater();
|
thread->deleteLater();
|
||||||
#ifndef FK_SERVER_ONLY
|
#ifndef FK_SERVER_ONLY
|
||||||
Backend->emitNotifyUI("DownloadComplete", "");
|
Backend->notifyUI("DownloadComplete", "");
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -135,7 +135,7 @@ void PackMan::downloadNewPack(const QString &url, bool useThread) {
|
||||||
connect(thread, &QThread::finished, [=]() {
|
connect(thread, &QThread::finished, [=]() {
|
||||||
thread->deleteLater();
|
thread->deleteLater();
|
||||||
#ifndef FK_SERVER_ONLY
|
#ifndef FK_SERVER_ONLY
|
||||||
Backend->emitNotifyUI("DownloadComplete", "");
|
Backend->notifyUI("DownloadComplete", "");
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -252,14 +252,14 @@ static int transfer_progress_cb(const git_indexer_progress *stats,
|
||||||
auto msg = QString("Resolving deltas %1/%2")
|
auto msg = QString("Resolving deltas %1/%2")
|
||||||
.arg(stats->indexed_deltas)
|
.arg(stats->indexed_deltas)
|
||||||
.arg(stats->total_deltas);
|
.arg(stats->total_deltas);
|
||||||
Backend->emitNotifyUI("UpdateBusyText", msg);
|
Backend->notifyUI("UpdateBusyText", msg);
|
||||||
} else if (stats->total_objects > 0) {
|
} else if (stats->total_objects > 0) {
|
||||||
auto msg = QString("Received %1/%2 objects (%3) in %4 KiB")
|
auto msg = QString("Received %1/%2 objects (%3) in %4 KiB")
|
||||||
.arg(stats->received_objects)
|
.arg(stats->received_objects)
|
||||||
.arg(stats->total_objects)
|
.arg(stats->total_objects)
|
||||||
.arg(stats->indexed_objects)
|
.arg(stats->indexed_objects)
|
||||||
.arg(stats->received_bytes / 1024);
|
.arg(stats->received_bytes / 1024);
|
||||||
Backend->emitNotifyUI("UpdateBusyText", msg);
|
Backend->notifyUI("UpdateBusyText", msg);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,11 @@
|
||||||
#define _PACKMAN_H
|
#define _PACKMAN_H
|
||||||
|
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
// 管理拓展包所需的类,本质上是libgit2接口的再封装。
|
||||||
class PackMan : public QObject {
|
class PackMan : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PackMan(QObject *parent = nullptr);
|
PackMan(QObject *parent = nullptr);
|
||||||
~PackMan();
|
~PackMan();
|
||||||
|
@ -20,6 +23,7 @@ public:
|
||||||
Q_INVOKABLE void upgradePack(const QString &pack);
|
Q_INVOKABLE void upgradePack(const QString &pack);
|
||||||
Q_INVOKABLE void removePack(const QString &pack);
|
Q_INVOKABLE void removePack(const QString &pack);
|
||||||
Q_INVOKABLE QString listPackages();
|
Q_INVOKABLE QString listPackages();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
|
|
||||||
|
|
53
src/main.cpp
53
src/main.cpp
|
@ -5,11 +5,7 @@
|
||||||
using namespace fkShell;
|
using namespace fkShell;
|
||||||
|
|
||||||
#include "packman.h"
|
#include "packman.h"
|
||||||
#ifndef Q_OS_WASM
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#else
|
|
||||||
#include <emscripten.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
@ -29,7 +25,7 @@ using namespace fkShell;
|
||||||
#include "qmlbackend.h"
|
#include "qmlbackend.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
|
#if defined(Q_OS_ANDROID)
|
||||||
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath) {
|
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath) {
|
||||||
QFileInfo srcFileInfo(srcFilePath);
|
QFileInfo srcFileInfo(srcFilePath);
|
||||||
if (srcFileInfo.isDir()) {
|
if (srcFileInfo.isDir()) {
|
||||||
|
@ -196,7 +192,6 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
// 分析命令行,如果有 -s 或者 --server 就在命令行直接开服务器
|
// 分析命令行,如果有 -s 或者 --server 就在命令行直接开服务器
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription("FreeKill server");
|
parser.setApplicationDescription("FreeKill server");
|
||||||
|
@ -244,7 +239,6 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
return app->exec();
|
return app->exec();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FK_SERVER_ONLY
|
#ifdef FK_SERVER_ONLY
|
||||||
// 根本没编译 GUI 相关的功能,直接在此退出
|
// 根本没编译 GUI 相关的功能,直接在此退出
|
||||||
|
@ -252,17 +246,6 @@ int main(int argc, char *argv[]) {
|
||||||
Please use ./FreeKill -s to start a server in command line.");
|
Please use ./FreeKill -s to start a server in command line.");
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef Q_OS_WASM
|
|
||||||
EM_ASM (
|
|
||||||
FS.mkdir('/assets');
|
|
||||||
FS.mount(IDBFS, {}, '/assets');
|
|
||||||
FS.chdir('/assets');
|
|
||||||
FS.syncfs(true, function(err) {
|
|
||||||
});
|
|
||||||
);
|
|
||||||
copyPath(":/", QDir::currentPath());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
app = new QApplication(argc, argv);
|
app = new QApplication(argc, argv);
|
||||||
#ifdef DESKTOP_BUILD
|
#ifdef DESKTOP_BUILD
|
||||||
((QApplication *)app)->setWindowIcon(QIcon("image/icon.png"));
|
((QApplication *)app)->setWindowIcon(QIcon("image/icon.png"));
|
||||||
|
@ -328,11 +311,12 @@ int main(int argc, char *argv[]) {
|
||||||
Pacman = new PackMan;
|
Pacman = new PackMan;
|
||||||
|
|
||||||
// 向 Qml 中先定义几个全局变量
|
// 向 Qml 中先定义几个全局变量
|
||||||
engine->rootContext()->setContextProperty("FkVersion", FK_VERSION);
|
auto root = engine->rootContext();
|
||||||
engine->rootContext()->setContextProperty("Backend", &backend);
|
root->setContextProperty("FkVersion", FK_VERSION);
|
||||||
engine->rootContext()->setContextProperty("ModBackend", nullptr);
|
root->setContextProperty("Backend", &backend);
|
||||||
engine->rootContext()->setContextProperty("Pacman", Pacman);
|
root->setContextProperty("ModBackend", nullptr);
|
||||||
engine->rootContext()->setContextProperty("SysLocale", localeName);
|
root->setContextProperty("Pacman", Pacman);
|
||||||
|
root->setContextProperty("SysLocale", localeName);
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
bool debugging = true;
|
bool debugging = true;
|
||||||
|
@ -344,9 +328,6 @@ int main(int argc, char *argv[]) {
|
||||||
QString system;
|
QString system;
|
||||||
#if defined(Q_OS_ANDROID)
|
#if defined(Q_OS_ANDROID)
|
||||||
system = "Android";
|
system = "Android";
|
||||||
#elif defined(Q_OS_WASM)
|
|
||||||
system = "Web";
|
|
||||||
engine->rootContext()->setContextProperty("ServerAddr", "127.0.0.1:9527");
|
|
||||||
#elif defined(Q_OS_WIN32)
|
#elif defined(Q_OS_WIN32)
|
||||||
system = "Win";
|
system = "Win";
|
||||||
::system("chcp 65001");
|
::system("chcp 65001");
|
||||||
|
@ -355,9 +336,9 @@ int main(int argc, char *argv[]) {
|
||||||
#else
|
#else
|
||||||
system = "Other";
|
system = "Other";
|
||||||
#endif
|
#endif
|
||||||
engine->rootContext()->setContextProperty("OS", system);
|
root->setContextProperty("OS", system);
|
||||||
|
|
||||||
engine->rootContext()->setContextProperty(
|
root->setContextProperty(
|
||||||
"AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
"AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
||||||
|
|
||||||
engine->addImportPath(QDir::currentPath());
|
engine->addImportPath(QDir::currentPath());
|
||||||
|
@ -378,20 +359,8 @@ int main(int argc, char *argv[]) {
|
||||||
delete engine;
|
delete engine;
|
||||||
delete Pacman;
|
delete Pacman;
|
||||||
|
|
||||||
#ifdef Q_OS_WASM
|
if (info_log) fclose(info_log);
|
||||||
EM_ASM (
|
if (err_log) fclose(err_log);
|
||||||
FS.syncfs(function(err) {});
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (info_log) {
|
|
||||||
fclose(info_log);
|
|
||||||
info_log = nullptr;
|
|
||||||
}
|
|
||||||
if (err_log) {
|
|
||||||
fclose(err_log);
|
|
||||||
info_log = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
#include "client_socket.h"
|
#include "client_socket.h"
|
||||||
#include "roomthread.h"
|
#include "roomthread.h"
|
||||||
#include <qjsondocument.h>
|
#include <qjsondocument.h>
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "serverplayer.h"
|
#include "serverplayer.h"
|
||||||
#endif
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
||||||
|
@ -18,9 +16,7 @@ Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
||||||
setSocket(socket);
|
setSocket(socket);
|
||||||
expectedReplyId = -1;
|
expectedReplyId = -1;
|
||||||
replyTimeout = 0;
|
replyTimeout = 0;
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
extraReplyReadySemaphore = nullptr;
|
extraReplyReadySemaphore = nullptr;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Router::~Router() { abortRequest(); }
|
Router::~Router() { abortRequest(); }
|
||||||
|
@ -57,15 +53,12 @@ bool Router::isConsoleStart() const {
|
||||||
return socket->peerAddress() == "127.0.0.1";
|
return socket->peerAddress() == "127.0.0.1";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
void Router::setReplyReadySemaphore(QSemaphore *semaphore) {
|
void Router::setReplyReadySemaphore(QSemaphore *semaphore) {
|
||||||
extraReplyReadySemaphore = semaphore;
|
extraReplyReadySemaphore = semaphore;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void Router::request(int type, const QString &command, const QString &jsonData,
|
void Router::request(int type, const QString &command, const QString &jsonData,
|
||||||
int timeout) {
|
int timeout) {
|
||||||
#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());
|
||||||
|
@ -88,7 +81,6 @@ void Router::request(int type, const QString &command, const QString &jsonData,
|
||||||
body << timeout;
|
body << timeout;
|
||||||
|
|
||||||
emit messageReady(JsonArray2Bytes(body));
|
emit messageReady(JsonArray2Bytes(body));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Router::reply(int type, const QString &command, const QString &jsonData) {
|
void Router::reply(int type, const QString &command, const QString &jsonData) {
|
||||||
|
@ -115,7 +107,6 @@ int Router::getTimeout() const { return requestTimeout; }
|
||||||
|
|
||||||
// cancel last request from the sender
|
// cancel last request from the sender
|
||||||
void Router::cancelRequest() {
|
void Router::cancelRequest() {
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
replyMutex.lock();
|
replyMutex.lock();
|
||||||
expectedReplyId = -1;
|
expectedReplyId = -1;
|
||||||
replyTimeout = 0;
|
replyTimeout = 0;
|
||||||
|
@ -124,22 +115,18 @@ void Router::cancelRequest() {
|
||||||
|
|
||||||
if (replyReadySemaphore.available() > 0)
|
if (replyReadySemaphore.available() > 0)
|
||||||
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Router::waitForReply(int timeout) {
|
QString Router::waitForReply(int timeout) {
|
||||||
QString ret;
|
QString ret;
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
replyReadySemaphore.tryAcquire(1, timeout * 1000);
|
replyReadySemaphore.tryAcquire(1, timeout * 1000);
|
||||||
replyMutex.lock();
|
replyMutex.lock();
|
||||||
ret = m_reply;
|
ret = m_reply;
|
||||||
replyMutex.unlock();
|
replyMutex.unlock();
|
||||||
#endif
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Router::abortRequest() {
|
void Router::abortRequest() {
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
replyMutex.lock();
|
replyMutex.lock();
|
||||||
if (expectedReplyId != -1) {
|
if (expectedReplyId != -1) {
|
||||||
replyReadySemaphore.release();
|
replyReadySemaphore.release();
|
||||||
|
@ -149,7 +136,6 @@ void Router::abortRequest() {
|
||||||
extraReplyReadySemaphore = nullptr;
|
extraReplyReadySemaphore = nullptr;
|
||||||
}
|
}
|
||||||
replyMutex.unlock();
|
replyMutex.unlock();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Router::handlePacket(const QByteArray &rawPacket) {
|
void Router::handlePacket(const QByteArray &rawPacket) {
|
||||||
|
@ -167,9 +153,7 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
||||||
#ifndef FK_SERVER_ONLY
|
#ifndef FK_SERVER_ONLY
|
||||||
ClientInstance->callLua(command, jsonData, false);
|
ClientInstance->callLua(command, jsonData, false);
|
||||||
#endif
|
#endif
|
||||||
}
|
} else {
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
else {
|
|
||||||
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
||||||
if (command == "Heartbeat") {
|
if (command == "Heartbeat") {
|
||||||
player->alive = true;
|
player->alive = true;
|
||||||
|
@ -179,7 +163,6 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
||||||
Room *room = player->getRoom();
|
Room *room = player->getRoom();
|
||||||
room->handlePacket(player, command, jsonData);
|
room->handlePacket(player, command, jsonData);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} else if (type & TYPE_REQUEST) {
|
} else if (type & TYPE_REQUEST) {
|
||||||
this->requestId = requestId;
|
this->requestId = requestId;
|
||||||
this->requestTimeout = packet[4].toInt();
|
this->requestTimeout = packet[4].toInt();
|
||||||
|
@ -192,9 +175,7 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
||||||
// requesting server is not allowed
|
// requesting server is not allowed
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
} else if (type & TYPE_REPLY) {
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
else if (type & TYPE_REPLY) {
|
|
||||||
QMutexLocker locker(&replyMutex);
|
QMutexLocker locker(&replyMutex);
|
||||||
|
|
||||||
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
||||||
|
@ -226,5 +207,4 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
emit replyReady();
|
emit replyReady();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,7 @@ public:
|
||||||
void installAESKey(const QByteArray &key);
|
void installAESKey(const QByteArray &key);
|
||||||
bool isConsoleStart() const;
|
bool isConsoleStart() const;
|
||||||
|
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
void setReplyReadySemaphore(QSemaphore *semaphore);
|
void setReplyReadySemaphore(QSemaphore *semaphore);
|
||||||
#endif
|
|
||||||
|
|
||||||
void request(int type, const QString &command,
|
void request(int type, const QString &command,
|
||||||
const QString &jsonData, int timeout);
|
const QString &jsonData, int timeout);
|
||||||
|
@ -72,10 +70,8 @@ private:
|
||||||
int expectedReplyId;
|
int expectedReplyId;
|
||||||
int replyTimeout;
|
int replyTimeout;
|
||||||
QString m_reply; // should be json string
|
QString m_reply; // should be json string
|
||||||
#ifndef FK_CLIENT_ONLY
|
|
||||||
QSemaphore replyReadySemaphore;
|
QSemaphore replyReadySemaphore;
|
||||||
QSemaphore *extraReplyReadySemaphore;
|
QSemaphore *extraReplyReadySemaphore;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Two Lua global table for callbacks and interactions
|
// Two Lua global table for callbacks and interactions
|
||||||
// stored in the lua_State of the sender
|
// stored in the lua_State of the sender
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
class ClientSocket;
|
class ClientSocket;
|
||||||
|
|
||||||
|
// 只是对QTcpServer的简单封装
|
||||||
class ServerSocket : public QObject {
|
class ServerSocket : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ signals:
|
||||||
void new_connection(ClientSocket *socket);
|
void new_connection(ClientSocket *socket);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
// 新建一个ClientSocket,然后立刻交给Server相关函数处理。
|
||||||
void processNewConnection();
|
void processNewConnection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -17,14 +17,10 @@ typedef int LuaFunction;
|
||||||
#include "sqlite3.h"
|
#include "sqlite3.h"
|
||||||
#define OPENSSL_API_COMPAT 0x10101000L
|
#define OPENSSL_API_COMPAT 0x10101000L
|
||||||
|
|
||||||
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_WASM)
|
#if !defined (Q_OS_ANDROID)
|
||||||
#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...
|
// You may define FK_SERVER_ONLY with cmake .. -D...
|
||||||
#ifndef FK_SERVER_ONLY
|
#ifndef FK_SERVER_ONLY
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
%nodefaultdtor QmlBackend;
|
%nodefaultdtor QmlBackend;
|
||||||
class QmlBackend : public QObject {
|
class QmlBackend : public QObject {
|
||||||
public:
|
public:
|
||||||
void emitNotifyUI(const QString &command, const QString &json_data);
|
void notifyUI(const QString &command, const QVariant &data);
|
||||||
|
|
||||||
static void cd(const QString &path);
|
static void cd(const QString &path);
|
||||||
static QStringList ls(const QString &dir);
|
static QStringList ls(const QString &dir);
|
||||||
static QString pwd();
|
static QString pwd();
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
%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"
|
|
||||||
|
|
||||||
QString GetDisabledPacks();
|
|
|
@ -4,6 +4,17 @@
|
||||||
// type bindings
|
// type bindings
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
%{
|
||||||
|
#include <qmlbackend.h>
|
||||||
|
%}
|
||||||
|
|
||||||
|
// Lua 5.4 特有的不能pushnumber, swig迟迟不更只好手动调教
|
||||||
|
%typemap(out) int
|
||||||
|
%{
|
||||||
|
lua_pushinteger(L, $1);
|
||||||
|
SWIG_arg ++;
|
||||||
|
%}
|
||||||
|
|
||||||
// LuaFunction(int) and lua function
|
// LuaFunction(int) and lua function
|
||||||
%naturalvar LuaFunction;
|
%naturalvar LuaFunction;
|
||||||
%typemap(in) LuaFunction
|
%typemap(in) LuaFunction
|
||||||
|
@ -65,6 +76,7 @@ SWIG_arg ++;
|
||||||
// QStringList
|
// QStringList
|
||||||
%naturalvar QStringList;
|
%naturalvar QStringList;
|
||||||
|
|
||||||
|
/* 没有从lua传入QStringList的情况,注释!
|
||||||
%typemap(in, checkfn = "lua_istable") QStringList
|
%typemap(in, checkfn = "lua_istable") QStringList
|
||||||
%{
|
%{
|
||||||
for (size_t i = 0; i < lua_rawlen(L, $input); ++i) {
|
for (size_t i = 0; i < lua_rawlen(L, $input); ++i) {
|
||||||
|
@ -74,6 +86,7 @@ for (size_t i = 0; i < lua_rawlen(L, $input); ++i) {
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
*/
|
||||||
|
|
||||||
%typemap(out) QStringList
|
%typemap(out) QStringList
|
||||||
%{
|
%{
|
||||||
|
@ -94,4 +107,37 @@ SWIG_arg++;
|
||||||
$1 = lua_istable(L, $input) ? 1 : 0;
|
$1 = lua_istable(L, $input) ? 1 : 0;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// QByteArray: 仅out
|
||||||
|
|
||||||
|
%typemap(out) QByteArray
|
||||||
|
%{
|
||||||
|
lua_pushstring(L, $1.constData());
|
||||||
|
SWIG_arg++;
|
||||||
|
%}
|
||||||
|
|
||||||
|
// const QByteArray &: 仅in
|
||||||
|
%typemap(arginit) QByteArray const &
|
||||||
|
"QByteArray $1_str;"
|
||||||
|
|
||||||
|
%typemap(in, checkfn = "lua_isstring") QByteArray const &
|
||||||
|
%{
|
||||||
|
$1_str = QByteArray(lua_tostring(L, $input));
|
||||||
|
$1 = &$1_str;
|
||||||
|
%}
|
||||||
|
|
||||||
|
// QVariant: 用于json,out
|
||||||
|
%typemap(out) QVariant
|
||||||
|
%{
|
||||||
|
QmlBackend::pushLuaValue(L, $1);
|
||||||
|
SWIG_arg++;
|
||||||
|
%}
|
||||||
|
|
||||||
|
// const QVariant &: 用于json,in
|
||||||
|
%typemap(arginit) QVariant const &
|
||||||
|
"QVariant $1_var;"
|
||||||
|
|
||||||
|
%typemap(in) QVariant const &
|
||||||
|
%{
|
||||||
|
$1_var = QmlBackend::readLuaValue(L, $input);
|
||||||
|
$1 = &$1_var;
|
||||||
|
%}
|
||||||
|
|
|
@ -1,44 +1,26 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// Make the base classes look like "complete"
|
// Make the base classes look like "complete"
|
||||||
class QObject {};
|
|
||||||
class QThread {
|
|
||||||
public:
|
|
||||||
static void msleep(long msec);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
%nodefaultctor QObject;
|
||||||
|
%nodefaultdtor QObject;
|
||||||
|
class QObject {};
|
||||||
|
|
||||||
|
%nodefaultctor QThread;
|
||||||
|
%nodefaultdtor QThread;
|
||||||
|
class QThread {};
|
||||||
|
|
||||||
|
%nodefaultctor QList;
|
||||||
|
%nodefaultdtor QList;
|
||||||
template <class T>
|
template <class T>
|
||||||
class QList {
|
class QList {
|
||||||
public:
|
public:
|
||||||
QList();
|
|
||||||
~QList();
|
|
||||||
int length() const;
|
int length() const;
|
||||||
void append(const T &elem);
|
T at(int i) const;
|
||||||
void prepend(const T &elem);
|
|
||||||
bool isEmpty() const;
|
|
||||||
bool contains(const T &value) const;
|
|
||||||
T first() const;
|
|
||||||
T last() const;
|
|
||||||
void removeAt(int i);
|
|
||||||
int removeAll(const T &value);
|
|
||||||
bool removeOne(const T &value);
|
|
||||||
QList<T> mid(int pos, int length = -1) const;
|
|
||||||
int indexOf(const T &value, int from = 0);
|
|
||||||
void replace(int i, const T &value);
|
|
||||||
void swapItemsAt(int i, int j);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
%extend QList {
|
|
||||||
T at(int i) const
|
|
||||||
{
|
|
||||||
return $self->value(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
%template(SPlayerList) QList<ServerPlayer *>;
|
%template(SPlayerList) QList<ServerPlayer *>;
|
||||||
%template(PlayerList) QList<const Player *>;
|
|
||||||
%template(IntList) QList<int>;
|
%template(IntList) QList<int>;
|
||||||
%template(BoolList) QList<bool>;
|
|
||||||
|
|
||||||
%native(GetMicroSecond) int GetMicroSecond(lua_State *L);
|
%native(GetMicroSecond) int GetMicroSecond(lua_State *L);
|
||||||
%{
|
%{
|
||||||
|
@ -56,3 +38,15 @@ void qDebug(const char *msg, ...);
|
||||||
void qInfo(const char *msg, ...);
|
void qInfo(const char *msg, ...);
|
||||||
void qWarning(const char *msg, ...);
|
void qWarning(const char *msg, ...);
|
||||||
void qCritical(const char *msg, ...);
|
void qCritical(const char *msg, ...);
|
||||||
|
|
||||||
|
class QJsonDocument {
|
||||||
|
public:
|
||||||
|
enum JsonFormat {
|
||||||
|
Indented,
|
||||||
|
Compact,
|
||||||
|
};
|
||||||
|
static QJsonDocument fromJson(const QByteArray &json);
|
||||||
|
static QJsonDocument fromVariant(const QVariant &variant);
|
||||||
|
QByteArray toJson(QJsonDocument::JsonFormat format = 1) const;
|
||||||
|
QVariant toVariant() const;
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include "qmlbackend.h"
|
#include "qmlbackend.h"
|
||||||
|
#include <lua.h>
|
||||||
#include <qjsondocument.h>
|
#include <qjsondocument.h>
|
||||||
|
#include <qvariant.h>
|
||||||
|
|
||||||
#ifndef FK_SERVER_ONLY
|
#ifndef FK_SERVER_ONLY
|
||||||
#include <qaudiooutput.h>
|
#include <qaudiooutput.h>
|
||||||
|
@ -16,9 +18,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#ifndef Q_OS_WASM
|
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#endif
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "replayer.h"
|
#include "replayer.h"
|
||||||
|
@ -81,7 +81,6 @@ void QmlBackend::setEngine(QQmlApplicationEngine *engine) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlBackend::startServer(ushort port) {
|
void QmlBackend::startServer(ushort port) {
|
||||||
#ifndef Q_OS_WASM
|
|
||||||
if (!ServerInstance) {
|
if (!ServerInstance) {
|
||||||
Server *server = new Server(this);
|
Server *server = new Server(this);
|
||||||
|
|
||||||
|
@ -90,7 +89,6 @@ void QmlBackend::startServer(ushort port) {
|
||||||
emit notifyUI("ErrorMsg", tr("Cannot start server!"));
|
emit notifyUI("ErrorMsg", tr("Cannot start server!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlBackend::joinServer(QString address) {
|
void QmlBackend::joinServer(QString address) {
|
||||||
|
@ -144,10 +142,6 @@ void QmlBackend::quitLobby(bool close) {
|
||||||
// ServerInstance->deleteLater();
|
// ServerInstance->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlBackend::emitNotifyUI(const QString &command, const QString &jsonData) {
|
|
||||||
emit notifyUI(command, jsonData);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QmlBackend::translate(const QString &src) {
|
QString QmlBackend::translate(const QString &src) {
|
||||||
if (!ClientInstance)
|
if (!ClientInstance)
|
||||||
return src;
|
return src;
|
||||||
|
@ -179,6 +173,9 @@ void QmlBackend::pushLuaValue(lua_State *L, QVariant v) {
|
||||||
case QMetaType::UInt:
|
case QMetaType::UInt:
|
||||||
lua_pushinteger(L, v.toInt());
|
lua_pushinteger(L, v.toInt());
|
||||||
break;
|
break;
|
||||||
|
case QMetaType::LongLong:
|
||||||
|
lua_pushinteger(L, v.toLongLong());
|
||||||
|
break;
|
||||||
case QMetaType::Double:
|
case QMetaType::Double:
|
||||||
lua_pushnumber(L, v.toDouble());
|
lua_pushnumber(L, v.toDouble());
|
||||||
break;
|
break;
|
||||||
|
@ -217,9 +214,79 @@ void QmlBackend::pushLuaValue(lua_State *L, QVariant v) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlBackend::callLuaFunction(const QString &func_name,
|
// 要求返回一个QVariant而不对栈产生影响
|
||||||
|
QVariant QmlBackend::readLuaValue(lua_State *L, int index,
|
||||||
|
QHash<const void *, bool> stack) {
|
||||||
|
|
||||||
|
if (index == 0) index = lua_gettop(L);
|
||||||
|
auto tp = lua_type(L, index);
|
||||||
|
switch (tp) {
|
||||||
|
case LUA_TNIL:
|
||||||
|
return QVariant::fromValue(nullptr);
|
||||||
|
case LUA_TBOOLEAN:
|
||||||
|
return QVariant((bool)lua_toboolean(L, index));
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
return QVariant(lua_tonumber(L, index));
|
||||||
|
case LUA_TSTRING:
|
||||||
|
return QVariant(lua_tostring(L, index));
|
||||||
|
case LUA_TTABLE: {
|
||||||
|
auto p = lua_topointer(L, index);
|
||||||
|
if (stack[p]) {
|
||||||
|
luaL_error(L, "circular reference detected");
|
||||||
|
return QVariant(); // won't return
|
||||||
|
}
|
||||||
|
stack[p] = true;
|
||||||
|
|
||||||
|
lua_len(L, index);
|
||||||
|
int length = lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
bool empty = true;
|
||||||
|
QVariantMap map;
|
||||||
|
|
||||||
|
lua_pushnil(L);
|
||||||
|
while (lua_next(L, index) != 0) {
|
||||||
|
if (lua_type(L, -2) != LUA_TSTRING) {
|
||||||
|
luaL_error(L, "key of object must be string");
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *key = lua_tostring(L, -2);
|
||||||
|
auto value = readLuaValue(L, lua_gettop(L), stack);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
map[key] = value;
|
||||||
|
empty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
return QVariantList();
|
||||||
|
} else {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QVariantList arr;
|
||||||
|
for (int i = 1; i <= length; i++) {
|
||||||
|
lua_rawgeti(L, index, i);
|
||||||
|
arr << readLuaValue(L, lua_gettop(L), stack);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore function, userdata and thread
|
||||||
|
default:
|
||||||
|
luaL_error(L, "unexpected value type %s", lua_typename(L, tp));
|
||||||
|
}
|
||||||
|
return QVariant(); // won't return
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QmlBackend::callLuaFunction(const QString &func_name,
|
||||||
QVariantList params) {
|
QVariantList params) {
|
||||||
if (!ClientInstance) return "{}";
|
if (!ClientInstance) return QVariantMap();
|
||||||
|
|
||||||
lua_State *L = ClientInstance->getLuaState();
|
lua_State *L = ClientInstance->getLuaState();
|
||||||
lua_getglobal(L, func_name.toLatin1().data());
|
lua_getglobal(L, func_name.toLatin1().data());
|
||||||
|
@ -229,19 +296,19 @@ QString QmlBackend::callLuaFunction(const QString &func_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = lua_pcall(L, params.length(), 1, 0);
|
int err = lua_pcall(L, params.length(), 1, 0);
|
||||||
const char *result = lua_tostring(L, -1);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
qCritical() << result;
|
qCritical() << lua_tostring(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return "";
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
auto result = readLuaValue(L);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
return QString(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlBackend::evalLuaExp(const QString &lua) {
|
QVariant QmlBackend::evalLuaExp(const QString &lua) {
|
||||||
if (!ClientInstance) return "{}";
|
if (!ClientInstance) return QVariantMap();
|
||||||
|
|
||||||
lua_State *L = ClientInstance->getLuaState();
|
lua_State *L = ClientInstance->getLuaState();
|
||||||
int err;
|
int err;
|
||||||
|
@ -252,15 +319,15 @@ QString QmlBackend::evalLuaExp(const QString &lua) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
err = lua_pcall(L, 0, 1, 0);
|
err = lua_pcall(L, 0, 1, 0);
|
||||||
const char *result = luaL_tolstring(L, -1, NULL);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
qCritical() << result;
|
qCritical() << lua_tostring(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
return "";
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
auto result = readLuaValue(L);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
return QString(result);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlBackend::pubEncrypt(const QString &key, const QString &data) {
|
QString QmlBackend::pubEncrypt(const QString &key, const QString &data) {
|
||||||
|
@ -505,13 +572,13 @@ void QmlBackend::setReplayer(Replayer *rep) {
|
||||||
replayer = rep;
|
replayer = rep;
|
||||||
if (rep) {
|
if (rep) {
|
||||||
connect(rep, &Replayer::duration_set, this, [this](int sec) {
|
connect(rep, &Replayer::duration_set, this, [this](int sec) {
|
||||||
this->emitNotifyUI("ReplayerDurationSet", QString::number(sec));
|
this->notifyUI("ReplayerDurationSet", QString::number(sec));
|
||||||
});
|
});
|
||||||
connect(rep, &Replayer::elasped, this, [this](int sec) {
|
connect(rep, &Replayer::elasped, this, [this](int sec) {
|
||||||
this->emitNotifyUI("ReplayerElapsedChange", QString::number(sec));
|
this->notifyUI("ReplayerElapsedChange", QString::number(sec));
|
||||||
});
|
});
|
||||||
connect(rep, &Replayer::speed_changed, this, [this](qreal speed) {
|
connect(rep, &Replayer::speed_changed, this, [this](qreal speed) {
|
||||||
this->emitNotifyUI("ReplayerSpeedChange", QString::number(speed));
|
this->notifyUI("ReplayerSpeedChange", QString::number(speed));
|
||||||
});
|
});
|
||||||
connect(this, &QmlBackend::replayerToggle, rep, &Replayer::toggle);
|
connect(this, &QmlBackend::replayerToggle, rep, &Replayer::toggle);
|
||||||
connect(this, &QmlBackend::replayerSlowDown, rep, &Replayer::slowDown);
|
connect(this, &QmlBackend::replayerSlowDown, rep, &Replayer::slowDown);
|
||||||
|
|
|
@ -23,6 +23,11 @@ public:
|
||||||
static Q_INVOKABLE bool exists(const QString &file);
|
static Q_INVOKABLE bool exists(const QString &file);
|
||||||
static Q_INVOKABLE bool isDir(const QString &file);
|
static Q_INVOKABLE bool isDir(const QString &file);
|
||||||
|
|
||||||
|
// 这俩函数为啥要写在这。。
|
||||||
|
static void pushLuaValue(lua_State *L, QVariant v);
|
||||||
|
static QVariant readLuaValue(lua_State *L, int index = 0,
|
||||||
|
QHash<const void *, bool> stack = QHash<const void *, bool>());
|
||||||
|
|
||||||
#ifndef FK_SERVER_ONLY
|
#ifndef FK_SERVER_ONLY
|
||||||
QQmlApplicationEngine *getEngine() const;
|
QQmlApplicationEngine *getEngine() const;
|
||||||
void setEngine(QQmlApplicationEngine *engine);
|
void setEngine(QQmlApplicationEngine *engine);
|
||||||
|
@ -33,14 +38,11 @@ public:
|
||||||
// Lobby
|
// Lobby
|
||||||
Q_INVOKABLE void quitLobby(bool close = true);
|
Q_INVOKABLE void quitLobby(bool close = true);
|
||||||
|
|
||||||
// lua --> qml
|
|
||||||
void emitNotifyUI(const QString &command, const QString &jsonData);
|
|
||||||
|
|
||||||
// read data from lua, call lua functions
|
// read data from lua, call lua functions
|
||||||
Q_INVOKABLE QString translate(const QString &src);
|
Q_INVOKABLE QString translate(const QString &src);
|
||||||
Q_INVOKABLE QString callLuaFunction(const QString &func_name,
|
Q_INVOKABLE QVariant callLuaFunction(const QString &func_name,
|
||||||
QVariantList params);
|
QVariantList params);
|
||||||
Q_INVOKABLE QString evalLuaExp(const QString &lua);
|
Q_INVOKABLE QVariant evalLuaExp(const QString &lua);
|
||||||
|
|
||||||
Q_INVOKABLE QString pubEncrypt(const QString &key, const QString &data);
|
Q_INVOKABLE QString pubEncrypt(const QString &key, const QString &data);
|
||||||
Q_INVOKABLE QString loadConf();
|
Q_INVOKABLE QString loadConf();
|
||||||
|
@ -74,7 +76,7 @@ public:
|
||||||
Q_INVOKABLE void controlReplayer(QString type);
|
Q_INVOKABLE void controlReplayer(QString type);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void notifyUI(const QString &command, const QString &jsonData);
|
void notifyUI(const QString &command, const QVariant &data);
|
||||||
void volumeChanged(qreal);
|
void volumeChanged(qreal);
|
||||||
void replayerToggle();
|
void replayerToggle();
|
||||||
void replayerSpeedUp();
|
void replayerSpeedUp();
|
||||||
|
@ -96,8 +98,6 @@ private:
|
||||||
qreal m_volume;
|
qreal m_volume;
|
||||||
|
|
||||||
Replayer *replayer;
|
Replayer *replayer;
|
||||||
|
|
||||||
void pushLuaValue(lua_State *L, QVariant v);
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue