mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-15 19:22:25 +08:00
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)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(REQUIRED_QT_VERSION "6.4")
|
||||
|
||||
|
@ -45,15 +45,8 @@ include_directories(src/network)
|
|||
include_directories(src/server)
|
||||
include_directories(src/ui)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
# Fix include problem
|
||||
include_directories("/usr/include/openssl-1.1/")
|
||||
endif()
|
||||
|
||||
file(GLOB SWIG_FILES "${PROJECT_SOURCE_DIR}/src/swig/*.i")
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill-wasm.i)
|
||||
elseif (DEFINED FK_SERVER_ONLY)
|
||||
if (DEFINED FK_SERVER_ONLY)
|
||||
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill-nogui.i)
|
||||
else ()
|
||||
set(SWIG_SOURCE ${PROJECT_SOURCE_DIR}/src/swig/freekill.i)
|
||||
|
@ -87,54 +80,4 @@ add_custom_command(
|
|||
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)
|
||||
|
|
16
Fk/Logic.js
16
Fk/Logic.js
|
@ -98,8 +98,7 @@ callbacks["BackToStart"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["SetServerSettings"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["SetServerSettings"] = (data) => {
|
||||
const [ motd, hiddenPacks, enableBots ] = data;
|
||||
config.serverMotd = motd;
|
||||
config.serverHiddenPacks = hiddenPacks;
|
||||
|
@ -127,9 +126,8 @@ callbacks["EnterLobby"] = (jsonData) => {
|
|||
config.saveConf();
|
||||
}
|
||||
|
||||
callbacks["EnterRoom"] = (jsonData) => {
|
||||
callbacks["EnterRoom"] = (data) => {
|
||||
// jsonData: int capacity, int timeout
|
||||
const data = JSON.parse(jsonData);
|
||||
config.roomCapacity = data[0];
|
||||
config.roomTimeout = data[1] - 1;
|
||||
const roomSettings = data[2];
|
||||
|
@ -139,11 +137,11 @@ callbacks["EnterRoom"] = (jsonData) => {
|
|||
mainWindow.busy = false;
|
||||
}
|
||||
|
||||
callbacks["UpdateRoomList"] = (jsonData) => {
|
||||
callbacks["UpdateRoomList"] = (data) => {
|
||||
const current = mainStack.currentItem; // should be lobby
|
||||
if (mainStack.depth === 2) {
|
||||
current.roomModel.clear();
|
||||
JSON.parse(jsonData).forEach(room => {
|
||||
data.forEach(room => {
|
||||
const [roomId, roomName, gameMode, playerNum, capacity, hasPassword,
|
||||
outdated] = room;
|
||||
current.roomModel.append({
|
||||
|
@ -154,10 +152,9 @@ callbacks["UpdateRoomList"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["UpdatePlayerNum"] = (j) => {
|
||||
callbacks["UpdatePlayerNum"] = (data) => {
|
||||
const current = mainStack.currentItem; // should be lobby
|
||||
if (mainStack.depth === 2) {
|
||||
const data = JSON.parse(j);
|
||||
const l = data[0];
|
||||
const s = data[1];
|
||||
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 }
|
||||
const current = mainStack.currentItem; // lobby or room
|
||||
const data = JSON.parse(jsonData);
|
||||
const pid = data.sender;
|
||||
const userName = data.userName;
|
||||
const general = luatr(data.general);
|
||||
|
|
|
@ -421,10 +421,8 @@ function setCardFootnote(id, footnote) {
|
|||
card.footnoteVisible = true;
|
||||
}
|
||||
|
||||
callbacks["SetCardFootnote"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
const id = data[0];
|
||||
const note = data[1];
|
||||
callbacks["SetCardFootnote"] = (data) => {
|
||||
const [id, note] = data;
|
||||
setCardFootnote(id, note);
|
||||
}
|
||||
|
||||
|
@ -444,10 +442,8 @@ function setCardVirtName(id, name) {
|
|||
card.virt_name = name;
|
||||
}
|
||||
|
||||
callbacks["SetCardVirtName"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
const ids = data[0];
|
||||
const note = data[1];
|
||||
callbacks["SetCardVirtName"] = (data) => {
|
||||
const [ids, note] = data;
|
||||
ids.forEach(id => setCardVirtName(id, note));
|
||||
}
|
||||
|
||||
|
@ -508,8 +504,7 @@ function processPrompt(prompt) {
|
|||
return raw;
|
||||
}
|
||||
|
||||
callbacks["MaxCard"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["MaxCard"] = (data) => {
|
||||
const id = data.id;
|
||||
const cardMax = data.pcardMax;
|
||||
const photo = getPhoto(id);
|
||||
|
@ -530,7 +525,7 @@ function changeSelf(id) {
|
|||
dashboard.self = photos.itemAt(i);
|
||||
}
|
||||
}
|
||||
callbacks["ArrangeSeats"](JSON.stringify(order));
|
||||
callbacks["ArrangeSeats"](order);
|
||||
|
||||
// update dashboard
|
||||
dashboard.update();
|
||||
|
@ -542,12 +537,11 @@ function changeSelf(id) {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["AddPlayer"] = (jsonData) => {
|
||||
callbacks["AddPlayer"] = (data) => {
|
||||
// jsonData: int id, string screenName, string avatar, bool ready
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
const item = photoModel.get(i);
|
||||
if (item.id === -1) {
|
||||
const data = JSON.parse(jsonData);
|
||||
const uid = data[0];
|
||||
const name = data[1];
|
||||
const avatar = data[2];
|
||||
|
@ -740,9 +734,9 @@ function updateSelectedTargets(playerid, selected) {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["RemovePlayer"] = (jsonData) => {
|
||||
callbacks["RemovePlayer"] = (data) => {
|
||||
// jsonData: int uid
|
||||
const uid = JSON.parse(jsonData)[0];
|
||||
const uid = data[0];
|
||||
const model = getPhotoModel(uid);
|
||||
if (typeof(model) !== "undefined") {
|
||||
model.id = -1;
|
||||
|
@ -753,9 +747,9 @@ callbacks["RemovePlayer"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["RoomOwner"] = (jsonData) => {
|
||||
callbacks["RoomOwner"] = (data) => {
|
||||
// jsonData: int uid of the owner
|
||||
const uid = JSON.parse(jsonData)[0];
|
||||
const uid = data[0];
|
||||
|
||||
roomScene.isOwner = (Self.id === uid);
|
||||
|
||||
|
@ -777,8 +771,7 @@ function checkAllReady() {
|
|||
roomScene.isAllReady = allReady;
|
||||
}
|
||||
|
||||
callbacks["ReadyChanged"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["ReadyChanged"] = (data) => {
|
||||
const id = data[0];
|
||||
const ready = data[1];
|
||||
|
||||
|
@ -793,8 +786,7 @@ callbacks["ReadyChanged"] = (j) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["NetStateChanged"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["NetStateChanged"] = (data) => {
|
||||
const id = data[0];
|
||||
let state = data[1];
|
||||
|
||||
|
@ -805,9 +797,8 @@ callbacks["NetStateChanged"] = (j) => {
|
|||
model.netstate = state;
|
||||
}
|
||||
|
||||
callbacks["PropertyUpdate"] = (jsonData) => {
|
||||
callbacks["PropertyUpdate"] = (data) => {
|
||||
// jsonData: int id, string property_name, value
|
||||
const data = JSON.parse(jsonData);
|
||||
const uid = data[0];
|
||||
const property_name = data[1];
|
||||
let value = data[2];
|
||||
|
@ -863,9 +854,8 @@ callbacks["StartGame"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["ArrangeSeats"] = (jsonData) => {
|
||||
callbacks["ArrangeSeats"] = (order) => {
|
||||
// jsonData: seat order
|
||||
const order = JSON.parse(jsonData);
|
||||
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
const item = photoModel.get(i);
|
||||
|
@ -895,10 +885,9 @@ function cancelAllFocus() {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["MoveFocus"] = (jsonData) => {
|
||||
callbacks["MoveFocus"] = (data) => {
|
||||
// jsonData: int[] focuses, string command
|
||||
cancelAllFocus();
|
||||
const data = JSON.parse(jsonData);
|
||||
const focuses = data[0];
|
||||
const command = data[1];
|
||||
|
||||
|
@ -925,9 +914,8 @@ callbacks["MoveFocus"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["PlayerRunned"] = (jsonData) => {
|
||||
callbacks["PlayerRunned"] = (data) => {
|
||||
// jsonData: int runner, int robot
|
||||
const data = JSON.parse(jsonData);
|
||||
const runner = data[0];
|
||||
const robot = data[1];
|
||||
|
||||
|
@ -937,9 +925,8 @@ callbacks["PlayerRunned"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["AskForGeneral"] = (jsonData) => {
|
||||
callbacks["AskForGeneral"] = (data) => {
|
||||
// jsonData: string[] Generals
|
||||
const data = JSON.parse(jsonData);
|
||||
const generals = data[0];
|
||||
const n = data[1];
|
||||
const convert = data[2];
|
||||
|
@ -960,9 +947,8 @@ callbacks["AskForGeneral"] = (jsonData) => {
|
|||
box.updatePosition();
|
||||
}
|
||||
|
||||
callbacks["AskForSkillInvoke"] = (jsonData) => {
|
||||
callbacks["AskForSkillInvoke"] = (data) => {
|
||||
// jsonData: [ string name, string prompt ]
|
||||
const data = JSON.parse(jsonData);
|
||||
const skill = data[0];
|
||||
const prompt = data[1];
|
||||
roomScene.promptText = prompt ? processPrompt(prompt)
|
||||
|
@ -973,8 +959,7 @@ callbacks["AskForSkillInvoke"] = (jsonData) => {
|
|||
roomScene.cancelButton.enabled = true;
|
||||
}
|
||||
|
||||
callbacks["AskForGuanxing"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["AskForGuanxing"] = (data) => {
|
||||
const cards = [];
|
||||
const min_top_cards = data.min_top_cards;
|
||||
const max_top_cards = data.max_top_cards;
|
||||
|
@ -1011,8 +996,7 @@ callbacks["AskForGuanxing"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForExchange"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["AskForExchange"] = (data) => {
|
||||
const cards = [];
|
||||
const cards_name = [];
|
||||
const capacities = [];
|
||||
|
@ -1041,10 +1025,9 @@ callbacks["AskForExchange"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForChoice"] = (jsonData) => {
|
||||
callbacks["AskForChoice"] = (data) => {
|
||||
// jsonData: [ string[] choices, string skill ]
|
||||
// TODO: multiple choices, e.g. benxi_ol
|
||||
const data = JSON.parse(jsonData);
|
||||
const choices = data[0];
|
||||
const all_choices = data[1];
|
||||
const skill_name = data[2];
|
||||
|
@ -1073,10 +1056,9 @@ callbacks["AskForChoice"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForChoices"] = (jsonData) => {
|
||||
callbacks["AskForChoices"] = (data) => {
|
||||
// jsonData: [ string[] choices, string skill ]
|
||||
// TODO: multiple choices, e.g. benxi_ol
|
||||
const data = JSON.parse(jsonData);
|
||||
const choices = data[0];
|
||||
const all_choices = data[1];
|
||||
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,
|
||||
// string reason ]
|
||||
const data = JSON.parse(jsonData);
|
||||
const reason = data._reason;
|
||||
const prompt = data._prompt;
|
||||
if (prompt === "") {
|
||||
|
@ -1145,10 +1126,9 @@ callbacks["AskForCardChosen"] = (jsonData) => {
|
|||
box.cardSelected.connect(cid => replyToServer(cid));
|
||||
}
|
||||
|
||||
callbacks["AskForCardsChosen"] = (jsonData) => {
|
||||
callbacks["AskForCardsChosen"] = (data) => {
|
||||
// jsonData: [ int[] handcards, int[] equips, int[] delayedtricks,
|
||||
// int min, int max, string reason ]
|
||||
const data = JSON.parse(jsonData);
|
||||
const min = data._min;
|
||||
const max = data._max;
|
||||
const reason = data._reason;
|
||||
|
@ -1182,8 +1162,8 @@ callbacks["AskForCardsChosen"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForPoxi"] = (jsonData) => {
|
||||
const { type, data, extra_data, cancelable } = JSON.parse(jsonData);
|
||||
callbacks["AskForPoxi"] = (dat) => {
|
||||
const { type, data, extra_data, cancelable } = dat;
|
||||
|
||||
roomScene.state = "replying";
|
||||
roomScene.popupBox.sourceComponent =
|
||||
|
@ -1208,8 +1188,7 @@ callbacks["AskForPoxi"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["AskForMoveCardInBoard"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["AskForMoveCardInBoard"] = (data) => {
|
||||
const { cards, cardsPosition, generalNames, playerIds } = data;
|
||||
|
||||
roomScene.state = "replying";
|
||||
|
@ -1241,15 +1220,13 @@ callbacks["AskForMoveCardInBoard"] = (jsonData) => {
|
|||
});
|
||||
}
|
||||
|
||||
callbacks["MoveCards"] = (jsonData) => {
|
||||
callbacks["MoveCards"] = (moves) => {
|
||||
// jsonData: merged moves
|
||||
const moves = JSON.parse(jsonData);
|
||||
moveCards(moves);
|
||||
}
|
||||
|
||||
callbacks["PlayCard"] = (jsonData) => {
|
||||
callbacks["PlayCard"] = (playerId) => {
|
||||
// jsonData: int playerId
|
||||
const playerId = parseInt(jsonData);
|
||||
if (playerId === Self.id) {
|
||||
roomScene.setPrompt(luatr("#PlayCard"), true);
|
||||
roomScene.state = "playing";
|
||||
|
@ -1257,9 +1234,8 @@ callbacks["PlayCard"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["LoseSkill"] = (jsonData) => {
|
||||
callbacks["LoseSkill"] = (data) => {
|
||||
// jsonData: [ int player_id, string skill_name ]
|
||||
const data = JSON.parse(jsonData);
|
||||
const id = data[0];
|
||||
const skill_name = data[1];
|
||||
const prelight = data[2];
|
||||
|
@ -1268,9 +1244,8 @@ callbacks["LoseSkill"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["AddSkill"] = (jsonData) => {
|
||||
callbacks["AddSkill"] = (data) => {
|
||||
// jsonData: [ int player_id, string skill_name ]
|
||||
const data = JSON.parse(jsonData);
|
||||
const id = data[0];
|
||||
const skill_name = data[1];
|
||||
const prelight = data[2];
|
||||
|
@ -1279,17 +1254,15 @@ callbacks["AddSkill"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["PrelightSkill"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["PrelightSkill"] = (data) => {
|
||||
const skill_name = data[0];
|
||||
const prelight = data[1];
|
||||
|
||||
dashboard.prelightSkill(skill_name, prelight);
|
||||
}
|
||||
|
||||
callbacks["AskForUseActiveSkill"] = (jsonData) => {
|
||||
callbacks["AskForUseActiveSkill"] = (data) => {
|
||||
// jsonData: string skill_name, string prompt
|
||||
const data = JSON.parse(jsonData);
|
||||
const skill_name = data[0];
|
||||
const prompt = data[1];
|
||||
const cancelable = data[2];
|
||||
|
@ -1323,9 +1296,8 @@ callbacks["GameLog"] = (jsonData) => {
|
|||
roomScene.addToLog(jsonData)
|
||||
}
|
||||
|
||||
callbacks["AskForUseCard"] = (jsonData) => {
|
||||
callbacks["AskForUseCard"] = (data) => {
|
||||
// jsonData: card, pattern, prompt, cancelable, {}
|
||||
const data = JSON.parse(jsonData);
|
||||
const cardname = data[0];
|
||||
const pattern = data[1];
|
||||
const prompt = data[2];
|
||||
|
@ -1355,9 +1327,8 @@ callbacks["AskForUseCard"] = (jsonData) => {
|
|||
cancelButton.enabled = true;
|
||||
}
|
||||
|
||||
callbacks["AskForResponseCard"] = (jsonData) => {
|
||||
callbacks["AskForResponseCard"] = (data) => {
|
||||
// jsonData: card_name, pattern, prompt, cancelable, {}
|
||||
const data = JSON.parse(jsonData);
|
||||
const cardname = data[0];
|
||||
const pattern = data[1];
|
||||
const prompt = data[2];
|
||||
|
@ -1381,8 +1352,7 @@ callbacks["WaitForNullification"] = () => {
|
|||
roomScene.state = "notactive";
|
||||
}
|
||||
|
||||
callbacks["SetPlayerMark"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["SetPlayerMark"] = (data) => {
|
||||
const player = getPhoto(data[0]);
|
||||
const mark = data[1];
|
||||
const value = data[2] instanceof Object ? data[2] : data[2].toString();
|
||||
|
@ -1394,8 +1364,7 @@ callbacks["SetPlayerMark"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["SetBanner"] = (jsonData) => {
|
||||
const data = JSON.parse(jsonData);
|
||||
callbacks["SetBanner"] = (data) => {
|
||||
const mark = data[0];
|
||||
const value = data[1] instanceof Object ? data[1] : data[1].toString();
|
||||
let area = roomScene.banner;
|
||||
|
@ -1406,9 +1375,8 @@ callbacks["SetBanner"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["Animate"] = (jsonData) => {
|
||||
callbacks["Animate"] = (data) => {
|
||||
// jsonData: [Object object]
|
||||
const data = JSON.parse(jsonData);
|
||||
switch (data.type) {
|
||||
case "Indicate":
|
||||
data.to.forEach(item => {
|
||||
|
@ -1471,9 +1439,8 @@ callbacks["Animate"] = (jsonData) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["LogEvent"] = (jsonData) => {
|
||||
callbacks["LogEvent"] = (data) => {
|
||||
// jsonData: [Object object]
|
||||
const data = JSON.parse(jsonData);
|
||||
switch (data.type) {
|
||||
case "Damage": {
|
||||
const item = getPhotoOrDashboard(data.to);
|
||||
|
@ -1557,8 +1524,7 @@ callbacks["GameOver"] = (jsonData) => {
|
|||
// roomScene.isStarted = false;
|
||||
}
|
||||
|
||||
callbacks["FillAG"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["FillAG"] = (data) => {
|
||||
const ids = data[0];
|
||||
roomScene.manualBox.sourceComponent =
|
||||
Qt.createComponent("../RoomElement/AG.qml");
|
||||
|
@ -1570,9 +1536,8 @@ callbacks["AskForAG"] = (j) => {
|
|||
roomScene.manualBox.item.interactive = true;
|
||||
}
|
||||
|
||||
callbacks["TakeAG"] = (j) => {
|
||||
callbacks["TakeAG"] = (data) => {
|
||||
if (!roomScene.manualBox.item) return;
|
||||
const data = JSON.parse(j);
|
||||
const pid = data[0];
|
||||
const cid = data[1];
|
||||
const item = getPhoto(pid);
|
||||
|
@ -1584,8 +1549,7 @@ callbacks["TakeAG"] = (j) => {
|
|||
|
||||
callbacks["CloseAG"] = () => roomScene.manualBox.item.close();
|
||||
|
||||
callbacks["CustomDialog"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["CustomDialog"] = (data) => {
|
||||
const path = data.path;
|
||||
const dat = data.data;
|
||||
roomScene.state = "replying";
|
||||
|
@ -1595,8 +1559,7 @@ callbacks["CustomDialog"] = (j) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["MiniGame"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["MiniGame"] = (data) => {
|
||||
const game = data.type;
|
||||
const dat = data.data;
|
||||
const gdata = lcall("GetMiniGame", game, Self.id, JSON.stringify(dat));
|
||||
|
@ -1607,15 +1570,13 @@ callbacks["MiniGame"] = (j) => {
|
|||
}
|
||||
}
|
||||
|
||||
callbacks["UpdateMiniGame"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["UpdateMiniGame"] = (data) => {
|
||||
if (roomScene.popupBox.item) {
|
||||
roomScene.popupBox.item.updateData(data);
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["UpdateLimitSkill"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["UpdateLimitSkill"] = (data) => {
|
||||
const id = data[0];
|
||||
const skill = data[1];
|
||||
const time = data[2];
|
||||
|
@ -1636,8 +1597,7 @@ callbacks["UpdateRoundNum"] = (j) => {
|
|||
roomScene.miscStatus.roundNum = data;
|
||||
}
|
||||
|
||||
callbacks["UpdateGameData"] = (j) => {
|
||||
const data = JSON.parse(j);
|
||||
callbacks["UpdateGameData"] = (data) => {
|
||||
const id = data[0];
|
||||
const total = data[1];
|
||||
const win = data[2];
|
||||
|
|
14
Fk/main.qml
14
Fk/main.qml
|
@ -261,21 +261,11 @@ Window {
|
|||
|
||||
// fake global functions
|
||||
function lcall(funcName, ...params) {
|
||||
const ret = Backend.callLuaFunction(funcName, [...params]);
|
||||
try {
|
||||
return JSON.parse(ret);
|
||||
} catch (e) {
|
||||
return ret;
|
||||
}
|
||||
return Backend.callLuaFunction(funcName, [...params]);
|
||||
}
|
||||
|
||||
function leval(lua) {
|
||||
const ret = Backend.evalLuaExp(`return json.encode(${lua})`);
|
||||
try {
|
||||
return JSON.parse(ret);
|
||||
} catch (e) {
|
||||
return ret;
|
||||
}
|
||||
return Backend.evalLuaExp(`return ${lua}`);
|
||||
}
|
||||
|
||||
function luatr(src) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
---@field public current ClientPlayer @ 当前回合玩家
|
||||
---@field public discard_pile integer[] @ 弃牌堆
|
||||
---@field public observing boolean
|
||||
---@field public record any
|
||||
Client = AbstractRoom:subclass('Client')
|
||||
|
||||
-- load client classes
|
||||
|
@ -23,11 +24,17 @@ local pattern_refresh_commands = {
|
|||
"AskForResponseCard",
|
||||
}
|
||||
|
||||
-- 无需进行JSON.parse,但可能传入JSON字符串的command
|
||||
local no_decode_commands = {
|
||||
"ErrorMsg",
|
||||
"Heartbeat",
|
||||
}
|
||||
|
||||
function Client:initialize()
|
||||
AbstractRoom.initialize(self)
|
||||
self.client = fk.ClientInstance
|
||||
self.notifyUI = function(self, command, jsonData)
|
||||
fk.Backend:emitNotifyUI(command, jsonData)
|
||||
self.notifyUI = function(self, command, data)
|
||||
fk.Backend:notifyUI(command, data)
|
||||
end
|
||||
self.client.callback = function(_self, command, jsonData, isRequest)
|
||||
if self.recording then
|
||||
|
@ -35,6 +42,18 @@ function Client:initialize()
|
|||
end
|
||||
|
||||
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
|
||||
Fk.currentResponsePattern = nil
|
||||
|
@ -42,9 +61,9 @@ function Client:initialize()
|
|||
end
|
||||
|
||||
if (type(cb) == "function") then
|
||||
cb(jsonData)
|
||||
cb(data)
|
||||
else
|
||||
self:notifyUI(command, jsonData);
|
||||
self:notifyUI(command, data)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -58,7 +77,7 @@ function Client:initialize()
|
|||
end
|
||||
|
||||
---@param id integer
|
||||
---@return ClientPlayer?
|
||||
---@return ClientPlayer
|
||||
function Client:getPlayerById(id)
|
||||
if id == Self.id then return Self end
|
||||
for _, p in ipairs(self.players) do
|
||||
|
@ -95,7 +114,7 @@ function Client:moveCards(moves)
|
|||
for _, move in ipairs(moves) do
|
||||
if move.from and move.fromArea then
|
||||
local from = self:getPlayerById(move.from)
|
||||
self:notifyUI("MaxCard", json.encode{
|
||||
self:notifyUI("MaxCard", {
|
||||
pcardMax = from:getMaxCards(),
|
||||
id = move.from,
|
||||
})
|
||||
|
@ -114,7 +133,7 @@ function Client:moveCards(moves)
|
|||
|
||||
if move.to and move.toArea then
|
||||
local ids = move.ids
|
||||
self:notifyUI("MaxCard", json.encode{
|
||||
self:notifyUI("MaxCard", {
|
||||
pcardMax = self:getPlayerById(move.to):getMaxCards(),
|
||||
id = move.to,
|
||||
})
|
||||
|
@ -172,6 +191,7 @@ local function parseMsg(msg, nocolor)
|
|||
|
||||
local from = getPlayerStr(data.from, "#0C8F0C")
|
||||
|
||||
---@type any
|
||||
local to = data.to or Util.DummyTable
|
||||
local to_str = {}
|
||||
for _, id in ipairs(to) do
|
||||
|
@ -179,6 +199,7 @@ local function parseMsg(msg, nocolor)
|
|||
end
|
||||
to = table.concat(to_str, ", ")
|
||||
|
||||
---@type any
|
||||
local card = data.card or Util.DummyTable
|
||||
local allUnknown = true
|
||||
local unknownCount = 0
|
||||
|
@ -238,20 +259,16 @@ end
|
|||
function Client:setCardNote(ids, msg)
|
||||
for _, id in ipairs(ids) do
|
||||
if id ~= -1 then
|
||||
self:notifyUI("SetCardFootnote", json.encode{ id, parseMsg(msg, true) })
|
||||
self:notifyUI("SetCardFootnote", { id, parseMsg(msg, true) })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["SetCardFootnote"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["SetCardFootnote"] = function(data)
|
||||
ClientInstance:setCardNote(data[1], data[2]);
|
||||
end
|
||||
|
||||
fk.client_callback["Setup"] = function(jsonData)
|
||||
-- jsonData: [ int id, string screenName, string avatar ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, name, avatar = data[1], data[2], data[3]
|
||||
local function setup(id, name, avatar)
|
||||
local self = fk.Self
|
||||
self:setId(id)
|
||||
self:setScreenName(name)
|
||||
|
@ -259,16 +276,21 @@ fk.client_callback["Setup"] = function(jsonData)
|
|||
Self = ClientPlayer:new(fk.Self)
|
||||
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)
|
||||
ClientInstance = Client:new() -- clear old client data
|
||||
ClientInstance.players = {Self}
|
||||
ClientInstance.alive_players = {Self}
|
||||
ClientInstance.discard_pile = {}
|
||||
|
||||
local _data = json.decode(jsonData)
|
||||
local data = _data[3]
|
||||
ClientInstance.enter_room_data = jsonData;
|
||||
ClientInstance.enter_room_data = json.encode(_data);
|
||||
ClientInstance.room_settings = data
|
||||
table.insertTableIfNeed(
|
||||
data.disabledPack,
|
||||
|
@ -276,25 +298,23 @@ fk.client_callback["EnterRoom"] = function(jsonData)
|
|||
)
|
||||
ClientInstance.disabled_packs = data.disabledPack
|
||||
ClientInstance.disabled_generals = data.disabledGenerals
|
||||
ClientInstance:notifyUI("EnterRoom", jsonData)
|
||||
ClientInstance:notifyUI("EnterRoom", _data)
|
||||
end
|
||||
|
||||
fk.client_callback["AddPlayer"] = function(jsonData)
|
||||
fk.client_callback["AddPlayer"] = function(data)
|
||||
-- jsonData: [ int id, string screenName, string avatar ]
|
||||
-- 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 player = fk.ClientInstance:addPlayer(id, name, avatar)
|
||||
player:addTotalGameTime(time or 0) -- 以防再次智迟
|
||||
local p = ClientPlayer:new(player)
|
||||
table.insert(ClientInstance.players, p)
|
||||
table.insert(ClientInstance.alive_players, p)
|
||||
ClientInstance:notifyUI("AddPlayer", jsonData)
|
||||
ClientInstance:notifyUI("AddPlayer", data)
|
||||
end
|
||||
|
||||
fk.client_callback["RemovePlayer"] = function(jsonData)
|
||||
fk.client_callback["RemovePlayer"] = function(data)
|
||||
-- jsonData: [ int id ]
|
||||
local data = json.decode(jsonData)
|
||||
local id = data[1]
|
||||
for _, p in ipairs(ClientInstance.players) do
|
||||
if p.player:getId() == id then
|
||||
|
@ -305,14 +325,13 @@ fk.client_callback["RemovePlayer"] = function(jsonData)
|
|||
end
|
||||
if id ~= Self.id then
|
||||
fk.ClientInstance:removePlayer(id)
|
||||
ClientInstance:notifyUI("RemovePlayer", jsonData)
|
||||
ClientInstance:notifyUI("RemovePlayer", data)
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["AddObserver"] = function(jsonData)
|
||||
fk.client_callback["AddObserver"] = function(data)
|
||||
-- jsonData: [ int id, string screenName, string avatar ]
|
||||
-- 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 player = {
|
||||
getId = function() return id end,
|
||||
|
@ -323,8 +342,7 @@ fk.client_callback["AddObserver"] = function(jsonData)
|
|||
table.insert(ClientInstance.observers, p)
|
||||
end
|
||||
|
||||
fk.client_callback["RemoveObserver"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["RemoveObserver"] = function(data)
|
||||
local id = data[1]
|
||||
for _, p in ipairs(ClientInstance.observers) do
|
||||
if p.player:getId() == id then
|
||||
|
@ -334,8 +352,7 @@ fk.client_callback["RemoveObserver"] = function(jsonData)
|
|||
end
|
||||
end
|
||||
|
||||
fk.client_callback["ArrangeSeats"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["ArrangeSeats"] = function(data)
|
||||
local n = #ClientInstance.players
|
||||
local players = {}
|
||||
|
||||
|
@ -352,12 +369,11 @@ fk.client_callback["ArrangeSeats"] = function(jsonData)
|
|||
|
||||
ClientInstance.players = players
|
||||
|
||||
ClientInstance:notifyUI("ArrangeSeats", jsonData)
|
||||
ClientInstance:notifyUI("ArrangeSeats", data)
|
||||
end
|
||||
|
||||
fk.client_callback["PropertyUpdate"] = function(jsonData)
|
||||
fk.client_callback["PropertyUpdate"] = function(data)
|
||||
-- jsonData: [ int id, string property_name, value ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, name, value = data[1], data[2], data[3]
|
||||
local p = ClientInstance:getPlayerById(id)
|
||||
p[name] = value
|
||||
|
@ -370,16 +386,15 @@ fk.client_callback["PropertyUpdate"] = function(jsonData)
|
|||
end
|
||||
end
|
||||
|
||||
ClientInstance:notifyUI("PropertyUpdate", jsonData)
|
||||
ClientInstance:notifyUI("MaxCard", json.encode{
|
||||
ClientInstance:notifyUI("PropertyUpdate", data)
|
||||
ClientInstance:notifyUI("MaxCard", {
|
||||
pcardMax = ClientInstance:getPlayerById(id):getMaxCards(),
|
||||
id = id,
|
||||
})
|
||||
end
|
||||
|
||||
fk.client_callback["AskForCardChosen"] = function(jsonData)
|
||||
fk.client_callback["AskForCardChosen"] = function(data)
|
||||
-- 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 target = ClientInstance:getPlayerById(id)
|
||||
local hand = target.player_cards[Player.Hand]
|
||||
|
@ -411,13 +426,13 @@ fk.client_callback["AskForCardChosen"] = function(jsonData)
|
|||
ui_data._reason = reason
|
||||
ui_data._prompt = prompt
|
||||
end
|
||||
ClientInstance:notifyUI("AskForCardChosen", json.encode(ui_data))
|
||||
ClientInstance:notifyUI("AskForCardChosen", ui_data)
|
||||
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 ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, min, max, flag, reason, prompt = data[1], data[2], data[3], data[4], data[5], data[6]
|
||||
local id, min, max, flag, reason, prompt = table.unpack(data)
|
||||
--data[1], data[2], data[3], data[4], data[5], data[6]
|
||||
local target = ClientInstance:getPlayerById(id)
|
||||
local hand = target.player_cards[Player.Hand]
|
||||
local equip = target.player_cards[Player.Equip]
|
||||
|
@ -452,7 +467,7 @@ fk.client_callback["AskForCardsChosen"] = function(jsonData)
|
|||
ui_data._reason = reason
|
||||
ui_data._prompt = prompt
|
||||
end
|
||||
ClientInstance:notifyUI("AskForCardsChosen", json.encode(ui_data))
|
||||
ClientInstance:notifyUI("AskForCardsChosen", ui_data)
|
||||
end
|
||||
|
||||
--- separated moves to many moves(one card per move)
|
||||
|
@ -646,23 +661,21 @@ local function sendMoveCardLog(move)
|
|||
end
|
||||
end
|
||||
|
||||
fk.client_callback["MoveCards"] = function(jsonData)
|
||||
fk.client_callback["MoveCards"] = function(raw_moves)
|
||||
-- jsonData: CardsMoveStruct[]
|
||||
local raw_moves = json.decode(jsonData)
|
||||
local separated = separateMoves(raw_moves)
|
||||
ClientInstance:moveCards(separated)
|
||||
local merged = mergeMoves(separated)
|
||||
ClientInstance:notifyUI("MoveCards", json.encode(merged))
|
||||
ClientInstance:notifyUI("MoveCards", merged)
|
||||
for _, move in ipairs(merged) do
|
||||
sendMoveCardLog(move)
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["ShowCard"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["ShowCard"] = function(data)
|
||||
local from = data.from
|
||||
local cards = data.cards
|
||||
ClientInstance:notifyUI("MoveCards", json.encode{
|
||||
ClientInstance:notifyUI("MoveCards", {
|
||||
{
|
||||
ids = cards,
|
||||
fromArea = Card.DrawPile,
|
||||
|
@ -679,15 +692,14 @@ local function updateLimitSkill(pid, skill, times)
|
|||
if skill:isSwitchSkill() then
|
||||
local _times = ClientInstance:getPlayerById(pid):getSwitchSkillState(skill.switchSkillName) == fk.SwitchYang and 0 or 1
|
||||
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
|
||||
ClientInstance:notifyUI("UpdateLimitSkill", json.encode{ pid, skill.name, times })
|
||||
ClientInstance:notifyUI("UpdateLimitSkill", { pid, skill.name, times })
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["LoseSkill"] = function(jsonData)
|
||||
fk.client_callback["LoseSkill"] = function(data)
|
||||
-- jsonData: [ int player_id, string skill_name ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, skill_name, fake = data[1], data[2], data[3]
|
||||
local target = ClientInstance:getPlayerById(id)
|
||||
local skill = Fk.skills[skill_name]
|
||||
|
@ -695,7 +707,7 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
|||
if not fake then
|
||||
target:loseSkill(skill)
|
||||
if skill.visible then
|
||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
||||
ClientInstance:notifyUI("LoseSkill", data)
|
||||
end
|
||||
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
|
||||
chk = true
|
||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
||||
ClientInstance:notifyUI("LoseSkill", data)
|
||||
end
|
||||
|
||||
local active = table.filter(sks, function(s)
|
||||
|
@ -720,13 +732,13 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
|||
|
||||
if #active > 0 then
|
||||
chk = true
|
||||
ClientInstance:notifyUI("LoseSkill", json.encode {
|
||||
ClientInstance:notifyUI("LoseSkill", {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
|
||||
if not chk then
|
||||
ClientInstance:notifyUI("LoseSkill", json.encode {
|
||||
ClientInstance:notifyUI("LoseSkill", {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
|
@ -735,9 +747,8 @@ fk.client_callback["LoseSkill"] = function(jsonData)
|
|||
updateLimitSkill(id, skill, -1)
|
||||
end
|
||||
|
||||
fk.client_callback["AddSkill"] = function(jsonData)
|
||||
fk.client_callback["AddSkill"] = function(data)
|
||||
-- jsonData: [ int player_id, string skill_name ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, skill_name, fake = data[1], data[2], data[3]
|
||||
local target = ClientInstance:getPlayerById(id)
|
||||
local skill = Fk.skills[skill_name]
|
||||
|
@ -745,7 +756,7 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
|||
if not fake then
|
||||
target:addSkill(skill)
|
||||
if skill.visible then
|
||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
||||
ClientInstance:notifyUI("AddSkill", data)
|
||||
end
|
||||
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
|
||||
chk = true
|
||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
||||
ClientInstance:notifyUI("AddSkill", data)
|
||||
end
|
||||
|
||||
local active = table.filter(sks, function(s)
|
||||
|
@ -767,14 +778,14 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
|||
|
||||
if #active > 0 then
|
||||
chk = true
|
||||
ClientInstance:notifyUI("AddSkill", json.encode {
|
||||
ClientInstance:notifyUI("AddSkill", {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
|
||||
-- 面板上总得有点啥东西表明自己有技能吧 = =
|
||||
if not chk then
|
||||
ClientInstance:notifyUI("AddSkill", json.encode {
|
||||
ClientInstance:notifyUI("AddSkill", {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
|
@ -787,30 +798,28 @@ fk.client_callback["AddSkill"] = function(jsonData)
|
|||
updateLimitSkill(id, skill, target:usedSkillTimes(skill_name, Player.HistoryGame))
|
||||
end
|
||||
|
||||
fk.client_callback["AskForUseActiveSkill"] = function(jsonData)
|
||||
fk.client_callback["AskForUseActiveSkill"] = function(data)
|
||||
-- jsonData: [ string skill_name, string prompt, bool cancelable. json extra_data ]
|
||||
local data = json.decode(jsonData)
|
||||
local skill = Fk.skills[data[1]]
|
||||
local extra_data = data[4]
|
||||
skill._extra_data = extra_data
|
||||
|
||||
Fk.currentResponseReason = extra_data.skillName
|
||||
ClientInstance:notifyUI("AskForUseActiveSkill", jsonData)
|
||||
ClientInstance:notifyUI("AskForUseActiveSkill", data)
|
||||
end
|
||||
|
||||
fk.client_callback["AskForUseCard"] = function(jsonData)
|
||||
Fk.currentResponsePattern = json.decode(jsonData)[2]
|
||||
ClientInstance:notifyUI("AskForUseCard", jsonData)
|
||||
fk.client_callback["AskForUseCard"] = function(data)
|
||||
Fk.currentResponsePattern = data[2]
|
||||
ClientInstance:notifyUI("AskForUseCard", data)
|
||||
end
|
||||
|
||||
fk.client_callback["AskForResponseCard"] = function(jsonData)
|
||||
Fk.currentResponsePattern = json.decode(jsonData)[2]
|
||||
ClientInstance:notifyUI("AskForResponseCard", jsonData)
|
||||
fk.client_callback["AskForResponseCard"] = function(data)
|
||||
Fk.currentResponsePattern = data[2]
|
||||
ClientInstance:notifyUI("AskForResponseCard", data)
|
||||
end
|
||||
|
||||
fk.client_callback["SetPlayerMark"] = function(jsonData)
|
||||
fk.client_callback["SetPlayerMark"] = function(data)
|
||||
-- jsonData: [ int id, string mark, int value ]
|
||||
local data = json.decode(jsonData)
|
||||
local player, mark, value = data[1], data[2], data[3]
|
||||
local p = ClientInstance:getPlayerById(player)
|
||||
p:setMark(mark, value)
|
||||
|
@ -825,37 +834,34 @@ fk.client_callback["SetPlayerMark"] = function(jsonData)
|
|||
if text == "#hidden" then return end
|
||||
end
|
||||
end
|
||||
ClientInstance:notifyUI("SetPlayerMark", jsonData)
|
||||
ClientInstance:notifyUI("SetPlayerMark", data)
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["SetBanner"] = function(jsonData)
|
||||
fk.client_callback["SetBanner"] = function(data)
|
||||
-- jsonData: [ int id, string mark, int value ]
|
||||
local data = json.decode(jsonData)
|
||||
local mark, value = data[1], data[2]
|
||||
ClientInstance:setBanner(mark, value)
|
||||
|
||||
if string.sub(mark, 1, 1) == "@" then
|
||||
ClientInstance:notifyUI("SetBanner", jsonData)
|
||||
ClientInstance:notifyUI("SetBanner", data)
|
||||
end
|
||||
end
|
||||
|
||||
fk.client_callback["SetCardMark"] = function(jsonData)
|
||||
fk.client_callback["SetCardMark"] = function(data)
|
||||
-- jsonData: [ int id, string mark, int value ]
|
||||
local data = json.decode(jsonData)
|
||||
local card, mark, value = data[1], data[2], data[3]
|
||||
Fk:getCardById(card):setMark(mark, value)
|
||||
|
||||
ClientInstance:notifyUI("UpdateCard", tostring(card))
|
||||
ClientInstance:notifyUI("UpdateCard", card)
|
||||
end
|
||||
|
||||
fk.client_callback["Chat"] = function(jsonData)
|
||||
fk.client_callback["Chat"] = function(data)
|
||||
-- jsonData: { int type, int sender, string msg }
|
||||
local data = json.decode(jsonData)
|
||||
if data.type == 1 then
|
||||
data.general = ""
|
||||
data.time = os.date("%H:%M:%S")
|
||||
ClientInstance:notifyUI("Chat", json.encode(data))
|
||||
ClientInstance:notifyUI("Chat", data)
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -873,37 +879,32 @@ fk.client_callback["Chat"] = function(jsonData)
|
|||
end
|
||||
data.userName = p.player:getScreenName()
|
||||
data.time = os.date("%H:%M:%S")
|
||||
ClientInstance:notifyUI("Chat", json.encode(data))
|
||||
ClientInstance:notifyUI("Chat", data)
|
||||
end
|
||||
|
||||
fk.client_callback["GameLog"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["GameLog"] = function(data)
|
||||
ClientInstance:appendLog(data)
|
||||
end
|
||||
|
||||
fk.client_callback["LogEvent"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["LogEvent"] = function(data)
|
||||
if data.type == "Death" then
|
||||
table.removeOne(
|
||||
ClientInstance.alive_players,
|
||||
ClientInstance:getPlayerById(data.to)
|
||||
)
|
||||
end
|
||||
ClientInstance:notifyUI("LogEvent", jsonData)
|
||||
ClientInstance:notifyUI("LogEvent", data)
|
||||
end
|
||||
|
||||
fk.client_callback["AddCardUseHistory"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["AddCardUseHistory"] = function(data)
|
||||
Self:addCardUseHistory(data[1], data[2])
|
||||
end
|
||||
|
||||
fk.client_callback["SetCardUseHistory"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["SetCardUseHistory"] = function(data)
|
||||
Self:setCardUseHistory(data[1], data[2], data[3])
|
||||
end
|
||||
|
||||
fk.client_callback["AddSkillUseHistory"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["AddSkillUseHistory"] = function(data)
|
||||
local playerid, skill_name, time = data[1], data[2], data[3]
|
||||
local player = ClientInstance:getPlayerById(playerid)
|
||||
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))
|
||||
end
|
||||
|
||||
fk.client_callback["SetSkillUseHistory"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["SetSkillUseHistory"] = function(data)
|
||||
local id, skill_name, time, scope = data[1], data[2], data[3], data[4]
|
||||
local player = ClientInstance:getPlayerById(id)
|
||||
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))
|
||||
end
|
||||
|
||||
fk.client_callback["AddVirtualEquip"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["AddVirtualEquip"] = function(data)
|
||||
local cname = data.name
|
||||
local player = ClientInstance:getPlayerById(data.player)
|
||||
local subcards = data.subcards
|
||||
|
@ -934,8 +933,7 @@ fk.client_callback["AddVirtualEquip"] = function(jsonData)
|
|||
player:addVirtualEquip(c)
|
||||
end
|
||||
|
||||
fk.client_callback["RemoveVirtualEquip"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["RemoveVirtualEquip"] = function(data)
|
||||
local player = ClientInstance:getPlayerById(data.player)
|
||||
player:removeVirtualEquip(data.id)
|
||||
end
|
||||
|
@ -944,38 +942,35 @@ fk.client_callback["Heartbeat"] = function()
|
|||
ClientInstance.client:notifyServer("Heartbeat", "")
|
||||
end
|
||||
|
||||
fk.client_callback["ChangeSelf"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
ClientInstance:getPlayerById(data.id).player_cards[Player.Hand] = data.handcards
|
||||
ClientInstance:getPlayerById(data.id).special_cards = data.special_cards
|
||||
fk.client_callback["ChangeSelf"] = function(data)
|
||||
local p = ClientInstance:getPlayerById(data.id)
|
||||
p.player_cards[Player.Hand] = data.handcards
|
||||
p.special_cards = data.special_cards
|
||||
ClientInstance:notifyUI("ChangeSelf", data.id)
|
||||
end
|
||||
|
||||
fk.client_callback["UpdateQuestSkillUI"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["UpdateQuestSkillUI"] = function(data)
|
||||
local player, skillName, usedTimes = data[1], data[2], data[3]
|
||||
updateLimitSkill(player, Fk.skills[skillName], usedTimes)
|
||||
end
|
||||
|
||||
fk.client_callback["UpdateGameData"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["UpdateGameData"] = function(data)
|
||||
local player, total, win, run = data[1], data[2], data[3], data[4]
|
||||
player = ClientInstance:getPlayerById(player)
|
||||
if player then
|
||||
player.player:setGameData(total, win, run)
|
||||
end
|
||||
|
||||
ClientInstance:notifyUI("UpdateGameData", jsonData)
|
||||
ClientInstance:notifyUI("UpdateGameData", data)
|
||||
end
|
||||
|
||||
fk.client_callback["AddTotalGameTime"] = function(jsonData)
|
||||
local data = json.decode(jsonData)
|
||||
fk.client_callback["AddTotalGameTime"] = function(data)
|
||||
local player, time = data[1], data[2]
|
||||
player = ClientInstance:getPlayerById(player)
|
||||
if player then
|
||||
player.player:addTotalGameTime(time)
|
||||
if player == Self then
|
||||
ClientInstance:notifyUI("AddTotalGameTime", jsonData)
|
||||
ClientInstance:notifyUI("AddTotalGameTime", data)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1051,30 +1046,184 @@ fk.client_callback["EnterLobby"] = function(jsonData)
|
|||
c:notifyUI("EnterLobby", jsonData)
|
||||
end
|
||||
|
||||
fk.client_callback["PrintCard"] = function(j)
|
||||
local data = json.decode(j)
|
||||
fk.client_callback["PrintCard"] = function(data)
|
||||
local n, s, num = table.unpack(data)
|
||||
local cd = Fk:cloneCard(n, s, num)
|
||||
Fk:_addPrintedCard(cd)
|
||||
end
|
||||
|
||||
fk.client_callback["AddBuddy"] = function(j)
|
||||
fk.client_callback["AddBuddy"] = function(data)
|
||||
local c = ClientInstance
|
||||
local data = json.decode(j)
|
||||
local id, hand = table.unpack(data)
|
||||
local to = c:getPlayerById(id)
|
||||
Self:addBuddy(to)
|
||||
to.player_cards[Player.Hand] = hand
|
||||
end
|
||||
|
||||
fk.client_callback["RmBuddy"] = function(j)
|
||||
fk.client_callback["RmBuddy"] = function(data)
|
||||
local c = ClientInstance
|
||||
local id = tonumber(j)
|
||||
local id = data
|
||||
local to = c:getPlayerById(id)
|
||||
Self:removeBuddy(to)
|
||||
to.player_cards[Player.Hand] = table.map(to.player_cards, function() return -1 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)
|
||||
ClientInstance = Client:new()
|
||||
dofile "lua/client/client_util.lua"
|
||||
|
|
|
@ -9,7 +9,7 @@ end
|
|||
function GetGeneralData(name)
|
||||
local general = Fk.generals[name]
|
||||
if general == nil then general = Fk.generals["diaochan"] end
|
||||
return json.encode {
|
||||
return {
|
||||
package = general.package.name,
|
||||
extension = general.package.extensionName,
|
||||
kingdom = general.kingdom,
|
||||
|
@ -65,16 +65,16 @@ function GetGeneralDetail(name)
|
|||
table.insertIfNeed(ret.companions, g.name)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetSameGenerals(name)
|
||||
return json.encode(Fk:getSameGenerals(name))
|
||||
return Fk:getSameGenerals(name)
|
||||
end
|
||||
|
||||
function IsCompanionWith(general, general2)
|
||||
local _general, _general2 = Fk.generals[general], Fk.generals[general2]
|
||||
return json.encode(_general:isCompanionWith(_general2))
|
||||
return _general:isCompanionWith(_general2)
|
||||
end
|
||||
|
||||
local cardSubtypeStrings = {
|
||||
|
@ -89,7 +89,7 @@ local cardSubtypeStrings = {
|
|||
|
||||
function GetCardData(id, virtualCardForm)
|
||||
local card = Fk:getCardById(id)
|
||||
if card == nil then return json.encode{
|
||||
if card == nil then return {
|
||||
cid = id,
|
||||
known = false
|
||||
} end
|
||||
|
@ -124,7 +124,7 @@ function GetCardData(id, virtualCardForm)
|
|||
ret.subtype = cardSubtypeStrings[virtualCard.sub_type]
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetCardExtensionByName(cardName)
|
||||
|
@ -133,11 +133,11 @@ function GetCardExtensionByName(cardName)
|
|||
end
|
||||
|
||||
function GetAllMods()
|
||||
return json.encode(Fk.extensions)
|
||||
return Fk.extensions
|
||||
end
|
||||
|
||||
function GetAllModNames()
|
||||
return json.encode(Fk.extension_names)
|
||||
return Fk.extension_names
|
||||
end
|
||||
|
||||
function GetAllGeneralPack()
|
||||
|
@ -147,28 +147,28 @@ function GetAllGeneralPack()
|
|||
table.insert(ret, name)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetGenerals(pack_name)
|
||||
if not Fk.packages[pack_name] then return "[]" end
|
||||
if not Fk.packages[pack_name] then return {} end
|
||||
local ret = {}
|
||||
for _, g in ipairs(Fk.packages[pack_name].generals) do
|
||||
if not g.total_hidden then
|
||||
table.insert(ret, g.name)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function SearchAllGenerals(word)
|
||||
local ret = {}
|
||||
for _, name in ipairs(Fk.package_names) do
|
||||
if Fk.packages[name].type == Package.GeneralPack then
|
||||
table.insertTable(ret, json.decode(SearchGenerals(name, word)))
|
||||
table.insertTable(ret, SearchGenerals(name, word))
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function SearchGenerals(pack_name, word)
|
||||
|
@ -179,7 +179,7 @@ function SearchGenerals(pack_name, word)
|
|||
table.insert(ret, g.name)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function UpdatePackageEnable(pkg, enabled)
|
||||
|
@ -220,7 +220,7 @@ function GetAllCardPack()
|
|||
table.insert(ret, name)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetCards(pack_name)
|
||||
|
@ -228,7 +228,7 @@ function GetCards(pack_name)
|
|||
for _, c in ipairs(Fk.packages[pack_name].cards) do
|
||||
table.insert(ret, c.id)
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetCardSkill(cid)
|
||||
|
@ -236,7 +236,7 @@ function GetCardSkill(cid)
|
|||
end
|
||||
|
||||
function GetCardSpecialSkills(cid)
|
||||
return json.encode(Fk:getCardById(cid).special_skills or Util.DummyTable)
|
||||
return Fk:getCardById(cid).special_skills or Util.DummyTable
|
||||
end
|
||||
|
||||
function DistanceTo(from, to)
|
||||
|
@ -246,21 +246,21 @@ function DistanceTo(from, to)
|
|||
end
|
||||
|
||||
function GetPile(id, name)
|
||||
return json.encode(ClientInstance:getPlayerById(id):getPile(name) or {})
|
||||
return ClientInstance:getPlayerById(id):getPile(name) or Util.DummyTable
|
||||
end
|
||||
|
||||
function GetAllPiles(id)
|
||||
return json.encode(ClientInstance:getPlayerById(id).special_cards or Util.DummyTable)
|
||||
return ClientInstance:getPlayerById(id).special_cards or Util.DummyTable
|
||||
end
|
||||
|
||||
function GetPlayerSkills(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 {
|
||||
name = s.name,
|
||||
description = Fk:getDescription(s.name),
|
||||
} or nil
|
||||
end))
|
||||
end)
|
||||
end
|
||||
|
||||
---@param card string | integer
|
||||
|
@ -278,11 +278,11 @@ function CanUseCard(card, player, extra_data_str)
|
|||
if skill:isInstanceOf(ViewAsSkill) then
|
||||
c = skill:viewAs(selected_cards)
|
||||
if not c then
|
||||
return "false"
|
||||
return false
|
||||
end
|
||||
else
|
||||
-- ActiveSkill should return true here
|
||||
return "true"
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -294,13 +294,13 @@ function CanUseCard(card, player, extra_data_str)
|
|||
if min_target > 0 then
|
||||
for _, p in ipairs(ClientInstance.players) do
|
||||
if c.skill:targetFilter(p.id, {}, {}, c, extra_data) then
|
||||
return "true"
|
||||
return true
|
||||
end
|
||||
end
|
||||
return "false"
|
||||
return false
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function CardProhibitedUse(card)
|
||||
|
@ -317,11 +317,11 @@ function CardProhibitedUse(card)
|
|||
end
|
||||
end
|
||||
if c == nil then
|
||||
return "true"
|
||||
return true
|
||||
else
|
||||
ret = Self:prohibitUse(c)
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param card string | integer
|
||||
|
@ -331,7 +331,7 @@ end
|
|||
function CanUseCardToTarget(card, to_select, selected, extra_data_str)
|
||||
local extra_data = extra_data_str == "" and nil or json.decode(extra_data_str)
|
||||
if ClientInstance:getPlayerById(to_select).dead then
|
||||
return "false"
|
||||
return false
|
||||
end
|
||||
local c ---@type Card
|
||||
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)
|
||||
ret = ret and not Self:isProhibited(Fk:currentRoom():getPlayerById(to_select), c)
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param card string | integer
|
||||
|
@ -362,7 +362,7 @@ function CanSelectCardForSkill(card, to_select, selected_targets)
|
|||
end
|
||||
|
||||
local ret = c.skill:cardFilter(to_select, selected_cards, selected_targets)
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
---@param card string | integer
|
||||
|
@ -379,14 +379,14 @@ function CardFeasible(card, selected_targets)
|
|||
end
|
||||
|
||||
local ret = c.skill:feasible(selected_targets, selected_cards, Self, c)
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
-- Handle skills
|
||||
|
||||
function GetSkillData(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"
|
||||
if skill:isInstanceOf(ActiveSkill) or skill:isInstanceOf(ViewAsSkill) then
|
||||
freq = "active"
|
||||
|
@ -399,7 +399,7 @@ function GetSkillData(skill_name)
|
|||
elseif skill.frequency == Skill.Quest then
|
||||
frequency = "quest"
|
||||
end
|
||||
return json.encode{
|
||||
return {
|
||||
skill = Fk:translate(skill_name),
|
||||
orig_skill = skill_name,
|
||||
extension = skill.package.extensionName,
|
||||
|
@ -439,7 +439,7 @@ function ActiveCanUse(skill_name, extra_data_str)
|
|||
end
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function ActiveSkillPrompt(skill_name, selected, selected_targets)
|
||||
|
@ -452,7 +452,7 @@ function ActiveSkillPrompt(skill_name, selected, selected_targets)
|
|||
ret = skill.prompt
|
||||
end
|
||||
end
|
||||
return json.encode(ret or "")
|
||||
return ret or ""
|
||||
end
|
||||
|
||||
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)
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
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
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function ActiveFeasible(skill_name, selected, selected_cards)
|
||||
|
@ -498,7 +498,7 @@ function ActiveFeasible(skill_name, selected, selected_cards)
|
|||
end
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function CanViewAs(skill_name, card_ids)
|
||||
|
@ -511,7 +511,7 @@ function CanViewAs(skill_name, card_ids)
|
|||
ret = true
|
||||
end
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
-- card_name may be id, name of card, or json string
|
||||
|
@ -532,12 +532,12 @@ function CardFitPattern(card_name, pattern)
|
|||
ret = exp:match(c)
|
||||
end
|
||||
else
|
||||
return "true"
|
||||
return true
|
||||
end
|
||||
else
|
||||
ret = exp:matchExp(card_name)
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function SkillFitPattern(skill_name, pattern)
|
||||
|
@ -547,7 +547,7 @@ function SkillFitPattern(skill_name, pattern)
|
|||
local exp = Exppattern:Parse(pattern)
|
||||
ret = exp:matchExp(skill.pattern)
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function CardProhibitedResponse(card)
|
||||
|
@ -564,11 +564,11 @@ function CardProhibitedResponse(card)
|
|||
end
|
||||
end
|
||||
if c == nil then
|
||||
return "true"
|
||||
return true
|
||||
else
|
||||
ret = Self:prohibitResponse(c)
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function SkillCanResponse(skill_name, cardResponsing)
|
||||
|
@ -577,13 +577,13 @@ function SkillCanResponse(skill_name, cardResponsing)
|
|||
if skill and skill:isInstanceOf(ViewAsSkill) then
|
||||
ret = skill:enabledAtResponse(Self, cardResponsing)
|
||||
end
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetVirtualEquip(player, cid)
|
||||
local c = ClientInstance:getPlayerById(player):getVirualEquip(cid)
|
||||
if not c then return "null" end
|
||||
return json.encode{
|
||||
if not c then return nil end
|
||||
return {
|
||||
name = c.name,
|
||||
cid = c.subcards[1],
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ function GetExpandPileOfSkill(skillName)
|
|||
end
|
||||
|
||||
if type(e) == "table" then
|
||||
return json.encode(e)
|
||||
return e
|
||||
else
|
||||
return e or ""
|
||||
end
|
||||
|
@ -615,15 +615,15 @@ function GetGameModes()
|
|||
})
|
||||
end
|
||||
table.sort(ret, function(a, b) return a.name > b.name end)
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function GetInteractionOfSkill(skill_name)
|
||||
local skill = Fk.skills[skill_name]
|
||||
if skill and skill.interaction then
|
||||
return json.encode(skill:interaction())
|
||||
return skill:interaction()
|
||||
end
|
||||
return "null"
|
||||
return nil
|
||||
end
|
||||
|
||||
function SetInteractionDataOfSkill(skill_name, data)
|
||||
|
@ -642,13 +642,13 @@ end
|
|||
function GetPlayerHandcards(pid)
|
||||
local c = ClientInstance
|
||||
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
|
||||
|
||||
function GetPlayerEquips(pid)
|
||||
local c = ClientInstance
|
||||
local p = c:getPlayerById(pid)
|
||||
return json.encode(p.player_cards[Player.Equip])
|
||||
return p.player_cards[Player.Equip]
|
||||
end
|
||||
|
||||
function ResetClientLua()
|
||||
|
@ -673,20 +673,20 @@ function ResetAddPlayer(j)
|
|||
end
|
||||
|
||||
function GetRoomConfig()
|
||||
return json.encode(ClientInstance.room_settings)
|
||||
return ClientInstance.room_settings
|
||||
end
|
||||
|
||||
function GetPlayerGameData(pid)
|
||||
local c = ClientInstance
|
||||
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 ret = {}
|
||||
for _, i in fk.qlist(raw) do
|
||||
table.insert(ret, i)
|
||||
end
|
||||
table.insert(ret, p.player:getTotalGameTime())
|
||||
return json.encode(ret)
|
||||
return ret
|
||||
end
|
||||
|
||||
function SetPlayerGameData(pid, data)
|
||||
|
@ -708,7 +708,7 @@ end
|
|||
|
||||
function CheckSurrenderAvailable(playedTime)
|
||||
local curMode = ClientInstance.room_settings.gameMode
|
||||
return json.encode(Fk.game_modes[curMode]:surrenderFunc(playedTime))
|
||||
return Fk.game_modes[curMode]:surrenderFunc(playedTime)
|
||||
end
|
||||
|
||||
function SaveRecord()
|
||||
|
@ -756,22 +756,22 @@ end
|
|||
|
||||
function PoxiFilter(poxi_type, to_select, selected, data, extra_data)
|
||||
local poxi = Fk.poxi_methods[poxi_type]
|
||||
if not poxi then return "false" end
|
||||
return json.encode(poxi.card_filter(to_select, selected, data, extra_data))
|
||||
if not poxi then return false end
|
||||
return poxi.card_filter(to_select, selected, data, extra_data)
|
||||
end
|
||||
|
||||
function PoxiFeasible(poxi_type, selected, data, extra_data)
|
||||
local poxi = Fk.poxi_methods[poxi_type]
|
||||
if not poxi then return "false" end
|
||||
return json.encode(poxi.feasible(selected, data, extra_data))
|
||||
if not poxi then return false end
|
||||
return poxi.feasible(selected, data, extra_data)
|
||||
end
|
||||
|
||||
function GetQmlMark(mtype, name, value, p)
|
||||
local spec = Fk.qml_marks[mtype]
|
||||
if not spec then return "{}" end
|
||||
if not spec then return {} end
|
||||
p = ClientInstance:getPlayerById(p)
|
||||
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,
|
||||
text = spec.how_to_show(name, value, p)
|
||||
}
|
||||
|
@ -781,7 +781,7 @@ function GetMiniGame(gtype, p, data)
|
|||
local spec = Fk.mini_games[gtype]
|
||||
p = ClientInstance:getPlayerById(p)
|
||||
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,
|
||||
}
|
||||
end
|
||||
|
|
|
@ -38,7 +38,7 @@ function AbstractRoom:getPlayerById(id) end
|
|||
--- 获取一张牌所处的区域。
|
||||
---@param cardId integer | Card @ 要获得区域的那张牌,可以是Card或者一个id
|
||||
---@return CardArea @ 这张牌的区域
|
||||
function AbstractRoom:getCardArea(cardId) end
|
||||
function AbstractRoom:getCardArea(cardId) return Card.Unknown end
|
||||
|
||||
function AbstractRoom:setBanner(name, value)
|
||||
if value == 0 then value = nil end
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
]]--
|
||||
|
||||
---@class Matcher
|
||||
---@field public trueName string[]
|
||||
---@field public number integer[]
|
||||
---@field public suit string[]
|
||||
---@field public place string[]
|
||||
---@field public name string[]
|
||||
---@field public cardType string[]
|
||||
---@field public id integer[]
|
||||
---@field public trueName? string[]
|
||||
---@field public number? integer[]
|
||||
---@field public suit? string[]
|
||||
---@field public place? string[]
|
||||
---@field public name? string[]
|
||||
---@field public cardType? string[]
|
||||
---@field public id? integer[]
|
||||
|
||||
-- v0.2.6改动: cardType会被解析为trueName数组和name数组,而不是自己单独成立
|
||||
|
||||
|
|
|
@ -449,11 +449,14 @@ end
|
|||
|
||||
-- override default string.len
|
||||
string.rawlen = string.len
|
||||
|
||||
---@param self string
|
||||
---@diagnostic disable-next-line: duplicate-set-field
|
||||
function string:len()
|
||||
return utf8.len(self)
|
||||
end
|
||||
|
||||
---@param self string
|
||||
---@param delimiter string
|
||||
---@return string[]
|
||||
function string:split(delimiter)
|
||||
|
@ -470,16 +473,20 @@ function string:split(delimiter)
|
|||
return result
|
||||
end
|
||||
|
||||
---@param self string
|
||||
function string:startsWith(start)
|
||||
return self:sub(1, #start) == start
|
||||
end
|
||||
|
||||
---@param self string
|
||||
function string:endsWith(e)
|
||||
return e == "" or self:sub(-#e) == e
|
||||
end
|
||||
|
||||
FileIO = {
|
||||
pwd = fk.QmlBackend_pwd,
|
||||
|
||||
---@return string[]
|
||||
ls = function(filename)
|
||||
if filename == nil then
|
||||
return fk.QmlBackend_ls(".")
|
||||
|
|
|
@ -11,7 +11,30 @@ package.path = package.path .. ";./lua/lib/?.lua"
|
|||
class = require "middleclass"
|
||||
|
||||
-- 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())
|
||||
|
|
|
@ -24,10 +24,6 @@ SPlayerList = {}
|
|||
---@return integer microsecond
|
||||
function fk:GetMicroSecond()end
|
||||
|
||||
--- construct a QList<ServerPlayer *>.
|
||||
---@return fk.SPlayerList
|
||||
function fk:SPlayerList()end
|
||||
|
||||
function fk.QmlBackend_pwd()end
|
||||
|
||||
---@return string[]
|
||||
|
@ -44,3 +40,5 @@ function fk.qCritical(msg) end
|
|||
function fk.qInfo(msg) end
|
||||
function fk.qDebug(msg) end
|
||||
function fk.qWarning(msg) end
|
||||
|
||||
fk.FK_VER = '0.0.0'
|
||||
|
|
|
@ -5,41 +5,21 @@
|
|||
---@class fk.Player
|
||||
FPlayer = {}
|
||||
|
||||
---@return integer id
|
||||
function FPlayer:getId()end
|
||||
|
||||
---@return string name
|
||||
function FPlayer:getScreenName()end
|
||||
|
||||
---@return string avatar
|
||||
function FPlayer:getAvatar()end
|
||||
|
||||
---@class fk.ServerPlayer : fk.Player
|
||||
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
|
||||
|
||||
--- 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
|
||||
|
||||
--- Notice the client.
|
||||
---@param command string
|
||||
---@param jsonData string
|
||||
function FServerPlayer:doNotify(command,jsonData)end
|
||||
|
||||
function FServerPlayer:setBusy(_) end
|
||||
function FServerPlayer:isBusy(_) end
|
||||
function FServerPlayer:setThinking(_) end
|
||||
|
||||
function FServerPlayer:getState() end
|
||||
|
||||
---@type any
|
||||
fk.Self = nil
|
||||
|
|
|
@ -1 +1,14 @@
|
|||
-- 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
|
||||
-- 暂且用来当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 observee = self.players[1]
|
||||
player:doNotify("Setup", json.encode{
|
||||
observee.id,
|
||||
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)
|
||||
local summary = self:getSummary(observee, true)
|
||||
player:doNotify("Observe", json.encode(summary))
|
||||
|
||||
table.insert(self.observers, {observee.id, player, player:getId()})
|
||||
end
|
||||
|
|
|
@ -655,6 +655,45 @@ function Room:changeKingdom(player, kingdom, sendLog)
|
|||
})
|
||||
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
|
||||
end
|
||||
|
||||
local function assign(t1, t2, k)
|
||||
t1[k] = t2[k]
|
||||
end
|
||||
|
||||
-- 获取摘要信息。供重连/旁观使用
|
||||
-- 根据参数,返回一个大表保存自己的信息,客户端自行分析
|
||||
---@param player ServerPlayer
|
||||
---@param observe? boolean
|
||||
function ServerPlayer:marshal(player, observe)
|
||||
function ServerPlayer:getSummary(player, observe)
|
||||
local room = self.room
|
||||
if not room.game_started then
|
||||
local ret = { p = {} }
|
||||
-- If game does not starts, that mean we are entering room that
|
||||
-- all players are choosing their generals.
|
||||
-- Note that when we are in this function, the main thread must be
|
||||
-- calling delay() or waiting for reply.
|
||||
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
|
||||
return
|
||||
return ret
|
||||
end
|
||||
|
||||
room:notifyProperty(player, self, "maxHp")
|
||||
room:notifyProperty(player, self, "hp")
|
||||
room:notifyProperty(player, self, "shield")
|
||||
room:notifyProperty(player, self, "gender")
|
||||
room:notifyProperty(player, self, "kingdom")
|
||||
local properties = {}
|
||||
|
||||
assign(properties, self, "general")
|
||||
assign(properties, self, "deputyGeneral")
|
||||
assign(properties, self, "maxHp")
|
||||
assign(properties, self, "hp")
|
||||
assign(properties, self, "shield")
|
||||
assign(properties, self, "gender")
|
||||
assign(properties, self, "kingdom")
|
||||
|
||||
if self.dead then
|
||||
room:notifyProperty(player, self, "dead")
|
||||
room:notifyProperty(player, self, self.rest > 0 and "rest" or "role")
|
||||
assign(properties, self, "dead")
|
||||
assign(properties, self, self.rest > 0 and "rest" or "role")
|
||||
else
|
||||
room:notifyProperty(player, self, "seat")
|
||||
room:notifyProperty(player, self, "phase")
|
||||
assign(properties, self, "seat")
|
||||
assign(properties, self, "phase")
|
||||
end
|
||||
|
||||
if not self.faceup then
|
||||
room:notifyProperty(player, self, "faceup")
|
||||
assign(properties, self, "faceup")
|
||||
end
|
||||
|
||||
if self.chained then
|
||||
room:notifyProperty(player, 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
|
||||
assign(properties, self, "chained")
|
||||
end
|
||||
|
||||
if self.role_shown then
|
||||
room:notifyProperty(player, self, "role")
|
||||
assign(properties, self, "role")
|
||||
end
|
||||
|
||||
if #self.sealedSlots > 0 then
|
||||
room:notifyProperty(player, self, "sealedSlots")
|
||||
assign(properties, self, "sealedSlots")
|
||||
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
|
||||
|
||||
function ServerPlayer:reconnect()
|
||||
local room = self.room
|
||||
self.serverplayer:setState(fk.Player_Online)
|
||||
|
||||
self:doNotify("Setup", json.encode{
|
||||
self.id,
|
||||
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", "")
|
||||
local summary = room:getSummary(self, false)
|
||||
self:doNotify("Reconnect", json.encode(summary))
|
||||
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() })
|
||||
|
||||
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
|
||||
for _, s in ipairs(self._manually_fake_skills) do
|
||||
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}"
|
||||
)
|
||||
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 ()
|
||||
set(LUA_LIB lua5.4)
|
||||
set(SQLITE3_LIB sqlite3)
|
||||
|
|
0
src/applink.c
Executable file → Normal file
0
src/applink.c
Executable file → Normal file
|
@ -95,7 +95,7 @@ void PackMan::loadSummary(const QString &jsonData, bool useThread) {
|
|||
connect(thread, &QThread::finished, [=]() {
|
||||
thread->deleteLater();
|
||||
#ifndef FK_SERVER_ONLY
|
||||
Backend->emitNotifyUI("DownloadComplete", "");
|
||||
Backend->notifyUI("DownloadComplete", "");
|
||||
#endif
|
||||
});
|
||||
} else {
|
||||
|
@ -135,7 +135,7 @@ void PackMan::downloadNewPack(const QString &url, bool useThread) {
|
|||
connect(thread, &QThread::finished, [=]() {
|
||||
thread->deleteLater();
|
||||
#ifndef FK_SERVER_ONLY
|
||||
Backend->emitNotifyUI("DownloadComplete", "");
|
||||
Backend->notifyUI("DownloadComplete", "");
|
||||
#endif
|
||||
});
|
||||
} else {
|
||||
|
@ -252,14 +252,14 @@ static int transfer_progress_cb(const git_indexer_progress *stats,
|
|||
auto msg = QString("Resolving deltas %1/%2")
|
||||
.arg(stats->indexed_deltas)
|
||||
.arg(stats->total_deltas);
|
||||
Backend->emitNotifyUI("UpdateBusyText", msg);
|
||||
Backend->notifyUI("UpdateBusyText", msg);
|
||||
} else if (stats->total_objects > 0) {
|
||||
auto msg = QString("Received %1/%2 objects (%3) in %4 KiB")
|
||||
.arg(stats->received_objects)
|
||||
.arg(stats->total_objects)
|
||||
.arg(stats->indexed_objects)
|
||||
.arg(stats->received_bytes / 1024);
|
||||
Backend->emitNotifyUI("UpdateBusyText", msg);
|
||||
Backend->notifyUI("UpdateBusyText", msg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
#define _PACKMAN_H
|
||||
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
// 管理拓展包所需的类,本质上是libgit2接口的再封装。
|
||||
class PackMan : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PackMan(QObject *parent = nullptr);
|
||||
~PackMan();
|
||||
|
@ -20,6 +23,7 @@ public:
|
|||
Q_INVOKABLE void upgradePack(const QString &pack);
|
||||
Q_INVOKABLE void removePack(const QString &pack);
|
||||
Q_INVOKABLE QString listPackages();
|
||||
|
||||
private:
|
||||
sqlite3 *db;
|
||||
|
||||
|
|
53
src/main.cpp
53
src/main.cpp
|
@ -5,11 +5,7 @@
|
|||
using namespace fkShell;
|
||||
|
||||
#include "packman.h"
|
||||
#ifndef Q_OS_WASM
|
||||
#include "server.h"
|
||||
#else
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
|
||||
#include "shell.h"
|
||||
|
@ -29,7 +25,7 @@ using namespace fkShell;
|
|||
#include "qmlbackend.h"
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_WASM)
|
||||
#if defined(Q_OS_ANDROID)
|
||||
static bool copyPath(const QString &srcFilePath, const QString &tgtFilePath) {
|
||||
QFileInfo srcFileInfo(srcFilePath);
|
||||
if (srcFileInfo.isDir()) {
|
||||
|
@ -196,7 +192,6 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
// 分析命令行,如果有 -s 或者 --server 就在命令行直接开服务器
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("FreeKill server");
|
||||
|
@ -244,7 +239,6 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
return app->exec();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FK_SERVER_ONLY
|
||||
// 根本没编译 GUI 相关的功能,直接在此退出
|
||||
|
@ -252,17 +246,6 @@ int main(int argc, char *argv[]) {
|
|||
Please use ./FreeKill -s to start a server in command line.");
|
||||
#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);
|
||||
#ifdef DESKTOP_BUILD
|
||||
((QApplication *)app)->setWindowIcon(QIcon("image/icon.png"));
|
||||
|
@ -328,11 +311,12 @@ int main(int argc, char *argv[]) {
|
|||
Pacman = new PackMan;
|
||||
|
||||
// 向 Qml 中先定义几个全局变量
|
||||
engine->rootContext()->setContextProperty("FkVersion", FK_VERSION);
|
||||
engine->rootContext()->setContextProperty("Backend", &backend);
|
||||
engine->rootContext()->setContextProperty("ModBackend", nullptr);
|
||||
engine->rootContext()->setContextProperty("Pacman", Pacman);
|
||||
engine->rootContext()->setContextProperty("SysLocale", localeName);
|
||||
auto root = engine->rootContext();
|
||||
root->setContextProperty("FkVersion", FK_VERSION);
|
||||
root->setContextProperty("Backend", &backend);
|
||||
root->setContextProperty("ModBackend", nullptr);
|
||||
root->setContextProperty("Pacman", Pacman);
|
||||
root->setContextProperty("SysLocale", localeName);
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
bool debugging = true;
|
||||
|
@ -344,9 +328,6 @@ int main(int argc, char *argv[]) {
|
|||
QString system;
|
||||
#if defined(Q_OS_ANDROID)
|
||||
system = "Android";
|
||||
#elif defined(Q_OS_WASM)
|
||||
system = "Web";
|
||||
engine->rootContext()->setContextProperty("ServerAddr", "127.0.0.1:9527");
|
||||
#elif defined(Q_OS_WIN32)
|
||||
system = "Win";
|
||||
::system("chcp 65001");
|
||||
|
@ -355,9 +336,9 @@ int main(int argc, char *argv[]) {
|
|||
#else
|
||||
system = "Other";
|
||||
#endif
|
||||
engine->rootContext()->setContextProperty("OS", system);
|
||||
root->setContextProperty("OS", system);
|
||||
|
||||
engine->rootContext()->setContextProperty(
|
||||
root->setContextProperty(
|
||||
"AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
||||
|
||||
engine->addImportPath(QDir::currentPath());
|
||||
|
@ -378,20 +359,8 @@ int main(int argc, char *argv[]) {
|
|||
delete engine;
|
||||
delete Pacman;
|
||||
|
||||
#ifdef Q_OS_WASM
|
||||
EM_ASM (
|
||||
FS.syncfs(function(err) {});
|
||||
);
|
||||
#endif
|
||||
|
||||
if (info_log) {
|
||||
fclose(info_log);
|
||||
info_log = nullptr;
|
||||
}
|
||||
if (err_log) {
|
||||
fclose(err_log);
|
||||
info_log = nullptr;
|
||||
}
|
||||
if (info_log) fclose(info_log);
|
||||
if (err_log) fclose(err_log);
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
#include "client_socket.h"
|
||||
#include "roomthread.h"
|
||||
#include <qjsondocument.h>
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
#include "server.h"
|
||||
#include "serverplayer.h"
|
||||
#endif
|
||||
#include "util.h"
|
||||
|
||||
Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
||||
|
@ -18,9 +16,7 @@ Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
|
|||
setSocket(socket);
|
||||
expectedReplyId = -1;
|
||||
replyTimeout = 0;
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
extraReplyReadySemaphore = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
Router::~Router() { abortRequest(); }
|
||||
|
@ -57,15 +53,12 @@ bool Router::isConsoleStart() const {
|
|||
return socket->peerAddress() == "127.0.0.1";
|
||||
}
|
||||
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
void Router::setReplyReadySemaphore(QSemaphore *semaphore) {
|
||||
extraReplyReadySemaphore = semaphore;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Router::request(int type, const QString &command, const QString &jsonData,
|
||||
int timeout) {
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
// In case a request is called without a following waitForReply call
|
||||
if (replyReadySemaphore.available() > 0)
|
||||
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||
|
@ -88,7 +81,6 @@ void Router::request(int type, const QString &command, const QString &jsonData,
|
|||
body << timeout;
|
||||
|
||||
emit messageReady(JsonArray2Bytes(body));
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
void Router::cancelRequest() {
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
replyMutex.lock();
|
||||
expectedReplyId = -1;
|
||||
replyTimeout = 0;
|
||||
|
@ -124,22 +115,18 @@ void Router::cancelRequest() {
|
|||
|
||||
if (replyReadySemaphore.available() > 0)
|
||||
replyReadySemaphore.acquire(replyReadySemaphore.available());
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Router::waitForReply(int timeout) {
|
||||
QString ret;
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
replyReadySemaphore.tryAcquire(1, timeout * 1000);
|
||||
replyMutex.lock();
|
||||
ret = m_reply;
|
||||
replyMutex.unlock();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Router::abortRequest() {
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
replyMutex.lock();
|
||||
if (expectedReplyId != -1) {
|
||||
replyReadySemaphore.release();
|
||||
|
@ -149,7 +136,6 @@ void Router::abortRequest() {
|
|||
extraReplyReadySemaphore = nullptr;
|
||||
}
|
||||
replyMutex.unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Router::handlePacket(const QByteArray &rawPacket) {
|
||||
|
@ -167,9 +153,7 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
|||
#ifndef FK_SERVER_ONLY
|
||||
ClientInstance->callLua(command, jsonData, false);
|
||||
#endif
|
||||
}
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
else {
|
||||
} else {
|
||||
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
||||
if (command == "Heartbeat") {
|
||||
player->alive = true;
|
||||
|
@ -179,7 +163,6 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
|||
Room *room = player->getRoom();
|
||||
room->handlePacket(player, command, jsonData);
|
||||
}
|
||||
#endif
|
||||
} else if (type & TYPE_REQUEST) {
|
||||
this->requestId = requestId;
|
||||
this->requestTimeout = packet[4].toInt();
|
||||
|
@ -192,9 +175,7 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
|||
// requesting server is not allowed
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
else if (type & TYPE_REPLY) {
|
||||
} else if (type & TYPE_REPLY) {
|
||||
QMutexLocker locker(&replyMutex);
|
||||
|
||||
ServerPlayer *player = qobject_cast<ServerPlayer *>(parent());
|
||||
|
@ -226,5 +207,4 @@ void Router::handlePacket(const QByteArray &rawPacket) {
|
|||
locker.unlock();
|
||||
emit replyReady();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -34,9 +34,7 @@ public:
|
|||
void installAESKey(const QByteArray &key);
|
||||
bool isConsoleStart() const;
|
||||
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
void setReplyReadySemaphore(QSemaphore *semaphore);
|
||||
#endif
|
||||
|
||||
void request(int type, const QString &command,
|
||||
const QString &jsonData, int timeout);
|
||||
|
@ -72,10 +70,8 @@ private:
|
|||
int expectedReplyId;
|
||||
int replyTimeout;
|
||||
QString m_reply; // should be json string
|
||||
#ifndef FK_CLIENT_ONLY
|
||||
QSemaphore replyReadySemaphore;
|
||||
QSemaphore *extraReplyReadySemaphore;
|
||||
#endif
|
||||
|
||||
// Two Lua global table for callbacks and interactions
|
||||
// stored in the lua_State of the sender
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
class ClientSocket;
|
||||
|
||||
// 只是对QTcpServer的简单封装
|
||||
class ServerSocket : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -17,6 +18,7 @@ signals:
|
|||
void new_connection(ClientSocket *socket);
|
||||
|
||||
private slots:
|
||||
// 新建一个ClientSocket,然后立刻交给Server相关函数处理。
|
||||
void processNewConnection();
|
||||
|
||||
private:
|
||||
|
|
|
@ -17,14 +17,10 @@ typedef int LuaFunction;
|
|||
#include "sqlite3.h"
|
||||
#define OPENSSL_API_COMPAT 0x10101000L
|
||||
|
||||
#if !defined (Q_OS_ANDROID) && !defined (Q_OS_WASM)
|
||||
#if !defined (Q_OS_ANDROID)
|
||||
#define DESKTOP_BUILD
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WASM)
|
||||
#define FK_CLIENT_ONLY
|
||||
#endif
|
||||
|
||||
// You may define FK_SERVER_ONLY with cmake .. -D...
|
||||
#ifndef FK_SERVER_ONLY
|
||||
#include <QApplication>
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
%nodefaultdtor QmlBackend;
|
||||
class QmlBackend : public QObject {
|
||||
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 QStringList ls(const QString &dir);
|
||||
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
|
||||
// ------------------------------------------------------
|
||||
|
||||
%{
|
||||
#include <qmlbackend.h>
|
||||
%}
|
||||
|
||||
// Lua 5.4 特有的不能pushnumber, swig迟迟不更只好手动调教
|
||||
%typemap(out) int
|
||||
%{
|
||||
lua_pushinteger(L, $1);
|
||||
SWIG_arg ++;
|
||||
%}
|
||||
|
||||
// LuaFunction(int) and lua function
|
||||
%naturalvar LuaFunction;
|
||||
%typemap(in) LuaFunction
|
||||
|
@ -65,6 +76,7 @@ SWIG_arg ++;
|
|||
// QStringList
|
||||
%naturalvar QStringList;
|
||||
|
||||
/* 没有从lua传入QStringList的情况,注释!
|
||||
%typemap(in, checkfn = "lua_istable") QStringList
|
||||
%{
|
||||
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);
|
||||
}
|
||||
%}
|
||||
*/
|
||||
|
||||
%typemap(out) QStringList
|
||||
%{
|
||||
|
@ -94,4 +107,37 @@ SWIG_arg++;
|
|||
$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
|
||||
|
||||
// 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>
|
||||
class QList {
|
||||
public:
|
||||
QList();
|
||||
~QList();
|
||||
int length() const;
|
||||
void append(const T &elem);
|
||||
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);
|
||||
T at(int i) const;
|
||||
};
|
||||
|
||||
%extend QList {
|
||||
T at(int i) const
|
||||
{
|
||||
return $self->value(i);
|
||||
}
|
||||
}
|
||||
|
||||
%template(SPlayerList) QList<ServerPlayer *>;
|
||||
%template(PlayerList) QList<const Player *>;
|
||||
%template(IntList) QList<int>;
|
||||
%template(BoolList) QList<bool>;
|
||||
|
||||
%native(GetMicroSecond) int GetMicroSecond(lua_State *L);
|
||||
%{
|
||||
|
@ -56,3 +38,15 @@ void qDebug(const char *msg, ...);
|
|||
void qInfo(const char *msg, ...);
|
||||
void qWarning(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
|
||||
|
||||
#include "qmlbackend.h"
|
||||
#include <lua.h>
|
||||
#include <qjsondocument.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
#ifndef FK_SERVER_ONLY
|
||||
#include <qaudiooutput.h>
|
||||
|
@ -16,9 +18,7 @@
|
|||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#ifndef Q_OS_WASM
|
||||
#include "server.h"
|
||||
#endif
|
||||
#include "client.h"
|
||||
#include "util.h"
|
||||
#include "replayer.h"
|
||||
|
@ -81,7 +81,6 @@ void QmlBackend::setEngine(QQmlApplicationEngine *engine) {
|
|||
}
|
||||
|
||||
void QmlBackend::startServer(ushort port) {
|
||||
#ifndef Q_OS_WASM
|
||||
if (!ServerInstance) {
|
||||
Server *server = new Server(this);
|
||||
|
||||
|
@ -90,7 +89,6 @@ void QmlBackend::startServer(ushort port) {
|
|||
emit notifyUI("ErrorMsg", tr("Cannot start server!"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void QmlBackend::joinServer(QString address) {
|
||||
|
@ -144,10 +142,6 @@ void QmlBackend::quitLobby(bool close) {
|
|||
// ServerInstance->deleteLater();
|
||||
}
|
||||
|
||||
void QmlBackend::emitNotifyUI(const QString &command, const QString &jsonData) {
|
||||
emit notifyUI(command, jsonData);
|
||||
}
|
||||
|
||||
QString QmlBackend::translate(const QString &src) {
|
||||
if (!ClientInstance)
|
||||
return src;
|
||||
|
@ -179,6 +173,9 @@ void QmlBackend::pushLuaValue(lua_State *L, QVariant v) {
|
|||
case QMetaType::UInt:
|
||||
lua_pushinteger(L, v.toInt());
|
||||
break;
|
||||
case QMetaType::LongLong:
|
||||
lua_pushinteger(L, v.toLongLong());
|
||||
break;
|
||||
case QMetaType::Double:
|
||||
lua_pushnumber(L, v.toDouble());
|
||||
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) {
|
||||
if (!ClientInstance) return "{}";
|
||||
if (!ClientInstance) return QVariantMap();
|
||||
|
||||
lua_State *L = ClientInstance->getLuaState();
|
||||
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);
|
||||
const char *result = lua_tostring(L, -1);
|
||||
if (err) {
|
||||
qCritical() << result;
|
||||
qCritical() << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return "";
|
||||
return QVariant();
|
||||
}
|
||||
auto result = readLuaValue(L);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return QString(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QString QmlBackend::evalLuaExp(const QString &lua) {
|
||||
if (!ClientInstance) return "{}";
|
||||
QVariant QmlBackend::evalLuaExp(const QString &lua) {
|
||||
if (!ClientInstance) return QVariantMap();
|
||||
|
||||
lua_State *L = ClientInstance->getLuaState();
|
||||
int err;
|
||||
|
@ -252,15 +319,15 @@ QString QmlBackend::evalLuaExp(const QString &lua) {
|
|||
return "";
|
||||
}
|
||||
err = lua_pcall(L, 0, 1, 0);
|
||||
const char *result = luaL_tolstring(L, -1, NULL);
|
||||
if (err) {
|
||||
qCritical() << result;
|
||||
qCritical() << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return "";
|
||||
return QVariant();
|
||||
}
|
||||
auto result = readLuaValue(L);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return QString(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QString QmlBackend::pubEncrypt(const QString &key, const QString &data) {
|
||||
|
@ -505,13 +572,13 @@ void QmlBackend::setReplayer(Replayer *rep) {
|
|||
replayer = rep;
|
||||
if (rep) {
|
||||
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) {
|
||||
this->emitNotifyUI("ReplayerElapsedChange", QString::number(sec));
|
||||
this->notifyUI("ReplayerElapsedChange", QString::number(sec));
|
||||
});
|
||||
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::replayerSlowDown, rep, &Replayer::slowDown);
|
||||
|
|
|
@ -23,6 +23,11 @@ public:
|
|||
static Q_INVOKABLE bool exists(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
|
||||
QQmlApplicationEngine *getEngine() const;
|
||||
void setEngine(QQmlApplicationEngine *engine);
|
||||
|
@ -33,14 +38,11 @@ public:
|
|||
// Lobby
|
||||
Q_INVOKABLE void quitLobby(bool close = true);
|
||||
|
||||
// lua --> qml
|
||||
void emitNotifyUI(const QString &command, const QString &jsonData);
|
||||
|
||||
// read data from lua, call lua functions
|
||||
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);
|
||||
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 loadConf();
|
||||
|
@ -74,7 +76,7 @@ public:
|
|||
Q_INVOKABLE void controlReplayer(QString type);
|
||||
|
||||
signals:
|
||||
void notifyUI(const QString &command, const QString &jsonData);
|
||||
void notifyUI(const QString &command, const QVariant &data);
|
||||
void volumeChanged(qreal);
|
||||
void replayerToggle();
|
||||
void replayerSpeedUp();
|
||||
|
@ -96,8 +98,6 @@ private:
|
|||
qreal m_volume;
|
||||
|
||||
Replayer *replayer;
|
||||
|
||||
void pushLuaValue(lua_State *L, QVariant v);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user