diff --git a/Fk/LobbyElement/RoomGeneralSettings.qml b/Fk/LobbyElement/RoomGeneralSettings.qml index 7b6e2d8f..fa400c7b 100644 --- a/Fk/LobbyElement/RoomGeneralSettings.qml +++ b/Fk/LobbyElement/RoomGeneralSettings.qml @@ -87,7 +87,12 @@ Flickable { Text { id: warning anchors.rightMargin: 8 - visible: JSON.parse(Backend.callLuaFunction("GetAvailableGeneralsNum", [])) < config.preferredGeneralNum * config.preferedPlayerNum + visible: { + const avail = JSON.parse(Backend.callLuaFunction("GetAvailableGeneralsNum", [])); + config.disabledPack; // 没什么用,只是为了禁包刷新时刷新visible罢了 + const ret = avail < config.preferredGeneralNum * config.preferedPlayerNum; + return ret; + } text: Backend.translate("No enough generals") color: "red" } @@ -159,6 +164,7 @@ Flickable { text: Backend.translate("OK") enabled: !(warning.visible) onClicked: { + config.saveConf(); root.finished(); mainWindow.busy = true; @@ -208,6 +214,11 @@ Flickable { } playerNum.value = config.preferedPlayerNum; + + config.disabledPack.forEach(p => { + Backend.callLuaFunction("UpdatePackageEnable", [p, false]); + }); + config.disabledPackChanged(); } } } diff --git a/Fk/LobbyElement/RoomPackageSettings.qml b/Fk/LobbyElement/RoomPackageSettings.qml index 7e218745..2e2c648f 100644 --- a/Fk/LobbyElement/RoomPackageSettings.qml +++ b/Fk/LobbyElement/RoomPackageSettings.qml @@ -25,16 +25,36 @@ Flickable { text: "禁用Lua拓展 (重启后生效)" } - Text { - text: Backend.translate("General Packages") - font.bold: true + RowLayout { + Text { + text: Backend.translate("General Packages") + font.bold: true + } + Button { + text: Backend.translate("Select All") + onClicked: { + for (let i = 0; i < gpacks.count; i++) { + const item = gpacks.itemAt(i); + item.checked = true; + } + } + } + Button { + text: Backend.translate("Revert Selection") + onClicked: { + for (let i = 0; i < gpacks.count; i++) { + const item = gpacks.itemAt(i); + item.checked = !item.checked; + } + } + } } GridLayout { - id: gpacks columns: 2 Repeater { + id: gpacks model: ListModel { id: gpacklist } @@ -45,28 +65,42 @@ Flickable { enabled: orig_name !== "test_p_0" onCheckedChanged: { - const packs = config.disabledPack; - if (checked) { - const idx = packs.indexOf(orig_name); - if (idx !== -1) packs.splice(idx, 1); - } else { - packs.push(orig_name); - } + checkPackage(orig_name, checked); } } } } - Text { - text: Backend.translate("Card Packages") - font.bold: true + RowLayout { + Text { + text: Backend.translate("Card Packages") + font.bold: true + } + Button { + text: Backend.translate("Select All") + onClicked: { + for (let i = 0; i < cpacks.count; i++) { + const item = cpacks.itemAt(i); + item.checked = true; + } + } + } + Button { + text: Backend.translate("Revert Selection") + onClicked: { + for (let i = 0; i < cpacks.count; i++) { + const item = cpacks.itemAt(i); + item.checked = !item.checked; + } + } + } } GridLayout { - id: cpacks columns: 2 Repeater { + id: cpacks model: ListModel { id: cpacklist } @@ -76,19 +110,25 @@ Flickable { checked: pkg_enabled onCheckedChanged: { - const packs = config.disabledPack; - if (checked) { - const idx = packs.indexOf(orig_name); - if (idx !== -1) packs.splice(idx, 1); - } else { - packs.push(orig_name); - } + checkPackage(orig_name, checked); } } } } } + function checkPackage(orig_name, checked) { + const packs = config.disabledPack; + if (checked) { + const idx = packs.indexOf(orig_name); + if (idx !== -1) packs.splice(idx, 1); + } else { + packs.push(orig_name); + } + Backend.callLuaFunction("UpdatePackageEnable", [orig_name, checked]); + config.disabledPackChanged(); + } + Component.onCompleted: { const g = JSON.parse(Backend.callLuaFunction("GetAllGeneralPack", [])); for (let orig of g) { diff --git a/Fk/Pages/Room.qml b/Fk/Pages/Room.qml index 8e1ab8a5..51f46825 100644 --- a/Fk/Pages/Room.qml +++ b/Fk/Pages/Room.qml @@ -410,10 +410,19 @@ Item { anchors.rightMargin: 20 color: "#88EEEEEE" radius: 8 - visible: roomScene.state === "playing" && (specialCardSkills ?? false) - && (specialCardSkills.count > 1 - || ((specialCardSkills.model ?? false) - && specialCardSkills.model[0] !== "_normal_use")) + visible: { + if (roomScene.state !== "playing") { + return false; + } + if (!specialCardSkills) { + return false; + } + if (specialCardSkills.count > 1) { + return true; + } + return (specialCardSkills.model ?? false) + && specialCardSkills.model[0] !== "_normal_use" + } width: childrenRect.width height: childrenRect.height - 20 @@ -487,21 +496,20 @@ Item { onSourceChanged: { if (item === null) return; - item.finished.connect(function(){ + item.finished.connect(() => { sourceComponent = undefined; }); - item.widthChanged.connect(function(){ + item.widthChanged.connect(() => { popupBox.moveToCenter(); }); - item.heightChanged.connect(function(){ + item.heightChanged.connect(() => { popupBox.moveToCenter(); }); moveToCenter(); } onSourceComponentChanged: sourceChanged(); - function moveToCenter() - { + function moveToCenter() { item.x = Math.round((roomArea.width - item.width) / 2); item.y = Math.round(roomArea.height * 0.67 - item.height / 2); } diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts index 15aebdeb..83e40c2b 100644 --- a/lang/zh_CN.ts +++ b/lang/zh_CN.ts @@ -215,6 +215,10 @@ others logged in with this name 已经有人用这个名字登入了 + + others logged in again with this name + 其他人用你的用户名和密码登陆到了服务器,请检查密码是否泄漏 + invalid user name 用户名不合法,只能含有英数字和汉字 diff --git a/lua/client/client.lua b/lua/client/client.lua index 4b24ece7..c6f43608 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -43,6 +43,9 @@ function Client:initialize() for class, skills in pairs(Fk.global_status_skill) do self.status_skills[class] = {table.unpack(skills)} end + + self.disabled_packs = {} + self.disabled_generals = {} end ---@param id integer @@ -236,8 +239,8 @@ fk.client_callback["EnterRoom"] = function(jsonData) local data = json.decode(jsonData)[3] ClientInstance.room_settings = data - Fk.disabled_packs = data.disabledPack - Fk.disabled_generals = data.disabledGenerals + ClientInstance.disabled_packs = data.disabledPack + ClientInstance.disabled_generals = data.disabledGenerals ClientInstance:notifyUI("EnterRoom", jsonData) end @@ -750,6 +753,7 @@ 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 ClientInstance:notifyUI("ChangeSelf", data.id) end diff --git a/lua/client/client_util.lua b/lua/client/client_util.lua index 3f95e750..f26e3dd9 100644 --- a/lua/client/client_util.lua +++ b/lua/client/client_util.lua @@ -126,6 +126,14 @@ function GetGenerals(pack_name) return json.encode(ret) end +function UpdatePackageEnable(pkg, enabled) + if enabled then + table.removeOne(ClientInstance.disabled_packs, pkg) + else + table.insertIfNeed(ClientInstance.disabled_packs, pkg) + end +end + function GetAvailableGeneralsNum() local generalPool = Fk:getAllGenerals() local except = {} @@ -552,8 +560,8 @@ function ResetClientLua() ClientInstance.discard_pile = {} ClientInstance.room_settings = data - Fk.disabled_packs = data.disabledPack - Fk.disabled_generals = data.disabledGenerals + ClientInstance.disabled_packs = data.disabledPack + ClientInstance.disabled_generals = data.disabledGenerals -- ClientInstance:notifyUI("EnterRoom", jsonData) end diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua index beec9da6..d101e66f 100644 --- a/lua/client/i18n/zh_CN.lua +++ b/lua/client/i18n/zh_CN.lua @@ -46,6 +46,8 @@ Fk:loadTranslationTable{ ["Package Settings"] = "拓展包设置", ["General Packages"] = "武将拓展包", ["Card Packages"] = "卡牌拓展包", + ["Select All"] = "全选", + ["Revert Selection"] = "反选", ["Give Flower"] = "送花", ["Give Egg"] = "砸蛋", diff --git a/lua/core/engine.lua b/lua/core/engine.lua index b2f3d064..4199a3c8 100644 --- a/lua/core/engine.lua +++ b/lua/core/engine.lua @@ -19,7 +19,6 @@ ---@field public cards Card[] @ 所有卡牌 ---@field public translations table> @ 翻译表 ---@field public game_modes table @ 所有游戏模式 ----@field public disabled_packs string[] @ 禁用的拓展包列表 ---@field public currentResponsePattern string @ 要求用牌的种类(如要求用特定花色的桃···) ---@field public currentResponseReason string @ 要求用牌的原因(如濒死,被特定牌指定,使用特定技能···) local Engine = class("Engine") @@ -49,14 +48,31 @@ function Engine:initialize() self.cards = {} -- Card[] self.translations = {} -- srcText --> translated self.game_modes = {} - self.disabled_packs = {} - self.disabled_generals = {} self.kingdoms = {} self:loadPackages() self:addSkills(AuxSkills) end +local _foreign_keys = { + "currentResponsePattern", + "currentResponseReason", +} + +function Engine:__index(k) + if table.contains(_foreign_keys, k) then + return self:currentRoom()[k] + end +end + +function Engine:__newindex(k, v) + if table.contains(_foreign_keys, k) then + self:currentRoom()[k] = v + else + rawset(self, k, v) + end +end + --- 向Engine中加载一个拓展包。 --- --- 会加载这个拓展包含有的所有武将、卡牌以及游戏模式。 @@ -204,6 +220,12 @@ function Engine:addGenerals(generals) end end +local function canUseGeneral(g) + local r = Fk:currentRoom() + return not table.contains(r.disabled_packs, Fk.generals[g].package.name) and + not table.contains(r.disabled_generals, g) +end + --- 根据武将名称,获取它的同名武将。 --- --- 注意以此法返回的同名武将列表不包含他自己。 @@ -214,9 +236,7 @@ function Engine:getSameGenerals(name) local tName = tmp[#tmp] local ret = self.same_generals[tName] or {} return table.filter(ret, function(g) - return g ~= name and self.generals[g] ~= nil and - not table.contains(self.disabled_packs, self.generals[g].package.name) and - not table.contains(self.disabled_generals, g) + return g ~= name and self.generals[g] ~= nil and canUseGeneral(g) end) end @@ -336,7 +356,7 @@ function Engine:getAllGenerals(except) local result = {} for _, general in pairs(self.generals) do if not (except and table.contains(except, general)) then - if not table.contains(self.disabled_packs, general.package.name) and not table.contains(self.disabled_generals, general.name) then + if canUseGeneral(general.name) then table.insert(result, general) end end @@ -352,7 +372,7 @@ function Engine:getAllCardIds(except) local result = {} for _, card in ipairs(self.cards) do if not (except and table.contains(except, card.id)) then - if not table.contains(self.disabled_packs, card.package.name) then + if not table.contains(self:currentRoom().disabled_packs, card.package.name) then table.insert(result, card.id) end end diff --git a/lua/core/player.lua b/lua/core/player.lua index 635e09df..70f93bac 100644 --- a/lua/core/player.lua +++ b/lua/core/player.lua @@ -541,9 +541,8 @@ function Player:setSkillUseHistory(skill_name, num, scope) return end - if self.skillUsedHistory[skill_name] then - self.skillUsedHistory[skill_name][scope] = num - end + self.skillUsedHistory[skill_name] = self.skillUsedHistory[skill_name] or {0, 0, 0, 0} + self.skillUsedHistory[skill_name][scope] = num end --- 获取玩家使用特定牌的历史次数。 diff --git a/lua/server/request.lua b/lua/server/request.lua index dadc7823..7d13e284 100644 --- a/lua/server/request.lua +++ b/lua/server/request.lua @@ -131,6 +131,7 @@ request_handlers["changeself"] = function(room, id, reqlist) from_sp:doNotify("ChangeSelf", json.encode { id = toId, handcards = to:getCardIds(Player.Hand), + special_cards = to.special_cards, }) end diff --git a/lua/server/room.lua b/lua/server/room.lua index 90713596..6868b021 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -90,8 +90,8 @@ function Room:initialize(_room) self.skill_costs = {} self.settings = json.decode(self.room:settings()) - Fk.disabled_packs = self.settings.disabledPack - Fk.disabled_generals = self.settings.disabledGenerals + self.disabled_packs = self.settings.disabledPack + self.disabled_generals = self.settings.disabledGenerals end -- 供调度器使用的函数。能让房间开始运行/从挂起状态恢复。 diff --git a/lua/server/serverplayer.lua b/lua/server/serverplayer.lua index bb54813a..3f8f192d 100644 --- a/lua/server/serverplayer.lua +++ b/lua/server/serverplayer.lua @@ -233,12 +233,26 @@ function ServerPlayer:marshal(player) } 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) end - -- TODO: pile - for k, v in pairs(self.mark) do player:doNotify("SetPlayerMark", json.encode{self.id, k, v}) end @@ -254,8 +268,11 @@ function ServerPlayer:marshal(player) end for k, v in pairs(self.skillUsedHistory) do - if v[1] > 0 then - player:doNotify("AddSkillUseHistory", json.encode{self.id, k, v[1]}) + if v[4] > 0 then + player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[1], 1}) + player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[2], 2}) + player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[3], 3}) + player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[4], 4}) end end diff --git a/src/server/server.cpp b/src/server/server.cpp index b3d1a2ed..8e677747 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -397,6 +397,12 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name, error_msg = "username or password error"; } else { auto player = players.value(id); + // 顶号机制,如果在线的话就让他变成不在线 + if (player->getState() == Player::Online) { + player->doNotify("ErrorMsg", "others logged in again with this name"); + emit player->kicked(); + } + if (player->getState() == Player::Offline) { auto room = player->getRoom(); player->setSocket(client); @@ -417,7 +423,7 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name, } else { // 懒得处理掉线玩家在大厅了!踢掉得了 player->doNotify("ErrorMsg", "Unknown Error"); - player->kicked(); + emit player->kicked(); } return; diff --git a/src/server/serverplayer.cpp b/src/server/serverplayer.cpp index 6e88973c..637a9f1c 100644 --- a/src/server/serverplayer.cpp +++ b/src/server/serverplayer.cpp @@ -105,6 +105,7 @@ void ServerPlayer::prepareForRequest(const QString &command, } void ServerPlayer::kick() { + setState(Player::Offline); if (socket != nullptr) { socket->disconnectFromHost(); }