From 3dfff72836665a2c57ae91fadd4d5c3730a39e61 Mon Sep 17 00:00:00 2001 From: notify Date: Sun, 30 Apr 2023 18:51:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD=20(#141)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加最大选将18 将退出房改为延迟按钮 修虚拟闪电bug 修看破bug 增加长度限制 将异步模块单独一个Lua --- lua/freekill.lua | 8 ++ lua/server/events/movecard.lua | 11 +- lua/server/request.lua | 129 ++++++++++++++++++ lua/server/room.lua | 123 ++--------------- packages/standard_cards/init.lua | 6 +- packages/test/init.lua | 3 + qml/Pages/Init.qml | 2 + .../LobbyElement/RoomGeneralSettings.qml | 3 +- qml/Pages/LobbyElement/UserInfo.qml | 1 + qml/Pages/Room.qml | 5 +- qml/Pages/WebInit.qml | 2 + 11 files changed, 174 insertions(+), 119 deletions(-) create mode 100644 lua/server/request.lua diff --git a/lua/freekill.lua b/lua/freekill.lua index f0800a54..1f768c88 100644 --- a/lua/freekill.lua +++ b/lua/freekill.lua @@ -64,6 +64,14 @@ io = nil package = nil load = nil loadfile = nil +local _dofile = dofile +dofile = function(f) + local errmsg = "Refusing dofile that not in game directory" + assert(not f:startsWith("/"), errmsg) + assert(not f:startsWith(".."), errmsg) + assert(not f:find(":"), errmsg) + return _dofile(f) +end -- 初始化Engine类并置于Fk全局变量中,这里会加载拓展包 dofile "lua/fk_ex.lua" diff --git a/lua/server/events/movecard.lua b/lua/server/events/movecard.lua index 5bb90eb0..4fbc0eb2 100644 --- a/lua/server/events/movecard.lua +++ b/lua/server/events/movecard.lua @@ -61,9 +61,13 @@ GameEvent.functions[GameEvent.MoveCards] = function(self) for _, info in ipairs(data.moveInfo) do local realFromArea = self:getCardArea(info.cardId) local playerAreas = { Player.Hand, Player.Equip, Player.Judge, Player.Special } + local virtualEquip if table.contains(playerAreas, realFromArea) and data.from then - self:getPlayerById(data.from):removeCards(realFromArea, { info.cardId }, info.fromSpecialName) + local from = self:getPlayerById(data.from) + from:removeCards(realFromArea, { info.cardId }, info.fromSpecialName) + virtualEquip = from:getVirualEquip(info.cardId) + elseif realFromArea ~= Card.Unknown then local fromAreaIds = {} if realFromArea == Card.Processing then @@ -80,7 +84,10 @@ GameEvent.functions[GameEvent.MoveCards] = function(self) end if table.contains(playerAreas, data.toArea) and data.to then - self:getPlayerById(data.to):addCards(data.toArea, { info.cardId }, data.specialName) + local to = self:getPlayerById(data.to) + if virtualEquip then to:addVirtualEquip(virtualEquip) end + to:addCards(data.toArea, { info.cardId }, data.specialName) + else local toAreaIds = {} if data.toArea == Card.Processing then diff --git a/lua/server/request.lua b/lua/server/request.lua new file mode 100644 index 00000000..6bf30ca6 --- /dev/null +++ b/lua/server/request.lua @@ -0,0 +1,129 @@ +-- SPDX-License-Identifier: GPL-3.0-or-later + +local function tellRoomToObserver(self, player) + local observee = self.players[1] + player:doNotify("Setup", json.encode{ + observee.id, + observee.serverplayer:getScreenName(), + observee.serverplayer:getAvatar(), + }) + player:doNotify("EnterRoom", json.encode{ + #self.players, self.timeout, self.settings + }) + + -- send player data + for _, p in ipairs(self:getOtherPlayers(observee, true, true)) do + player:doNotify("AddPlayer", json.encode{ + p.id, + p.serverplayer:getScreenName(), + p.serverplayer:getAvatar(), + }) + 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)) + + for _, p in ipairs(self.players) do + self:notifyProperty(player, p, "general") + self:notifyProperty(player, p, "deputyGeneral") + p:marshal(player) + end + + player:doNotify("UpdateDrawPile", #self.draw_pile) + player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0) + + table.insert(self.observers, {observee.id, player}) +end + +local function addObserver(self, id) + local all_observers = self.room:getObservers() + for _, p in fk.qlist(all_observers) do + if p:getId() == id then + tellRoomToObserver(self, p) + self:doBroadcastNotify("AddObserver", json.encode{ + p:getId(), + p:getScreenName(), + p:getAvatar() + }) + break + end + end +end + +local function removeObserver(self, id) + for _, t in ipairs(self.observers) do + local __, p = table.unpack(t) + if p:getId() == id then + table.removeOne(self.observers, t) + self:doBroadcastNotify("RemoveObserver", json.encode{ + p:getId(), + }) + break + end + end +end + +local request_handlers = {} +request_handlers["reconnect"] = function(room, id, reqlist) + local p = room:getPlayerById(id) + p:reconnect() +end + +request_handlers["observe"] = function(room, id, reqlist) + addObserver(room, id) +end + +request_handlers["leave"] = function(room, id, reqlist) + removeObserver(room, id) +end + +request_handlers["prelight"] = function(room, id, reqlist) + local p = room:getPlayerById(id) + p:prelightSkill(reqlist[3], reqlist[4] == "true") +end + +request_handlers["changeself"] = function(room, id, reqlist) + local p = room:getPlayerById(id) + local toId = tonumber(reqlist[3]) + local from = p + local to = room:getPlayerById(toId) + local from_sp = from._splayer + + -- 注意发来信息的玩家的主视角可能已经不是自己了 + -- 先换成正确的玩家 + from = table.find(room.players, function(p) + return table.contains(p._observers, from_sp) + end) + + -- 切换视角 + table.removeOne(from._observers, from_sp) + table.insert(to._observers, from_sp) + from_sp:doNotify("ChangeSelf", json.encode { + id = toId, + handcards = to:getCardIds(Player.Hand), + }) +end + +local function requestLoop(self, rest_time) + while true do + local ret = false + local request = self.room:fetchRequest() + if request ~= "" then + ret = true + local reqlist = request:split(",") + local id = tonumber(reqlist[1]) + local command = reqlist[2] + request_handlers[command](self, id, reqlist) + elseif rest_time > 10 then + -- let current thread sleep 10ms + -- otherwise CPU usage will be 100% (infinite yield <-> resume loop) + fk.QThread_msleep(10) + end + coroutine.yield(ret) + end +end + +return requestLoop diff --git a/lua/server/room.lua b/lua/server/room.lua index 367c6563..e53d9441 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -630,119 +630,7 @@ function Room:doRaceRequest(command, players, jsonData) return ret end --- main loop for the request handling coroutine ---- 这是个私有函数,不用管。 -function Room:requestLoop(rest_time) - local function tellRoomToObserver(player) - local observee = self.players[1] - player:doNotify("Setup", json.encode{ - observee.id, - observee.serverplayer:getScreenName(), - observee.serverplayer:getAvatar(), - }) - player:doNotify("EnterRoom", json.encode{ - #self.players, self.timeout, self.settings - }) - - -- send player data - for _, p in ipairs(self:getOtherPlayers(observee, true, true)) do - player:doNotify("AddPlayer", json.encode{ - p.id, - p.serverplayer:getScreenName(), - p.serverplayer:getAvatar(), - }) - 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)) - - for _, p in ipairs(self.players) do - self:notifyProperty(player, p, "general") - self:notifyProperty(player, p, "deputyGeneral") - p:marshal(player) - end - - player:doNotify("UpdateDrawPile", #self.draw_pile) - player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0) - - table.insert(self.observers, {observee.id, player}) - end - - local function addObserver(id) - local all_observers = self.room:getObservers() - for _, p in fk.qlist(all_observers) do - if p:getId() == id then - tellRoomToObserver(p) - self:doBroadcastNotify("AddObserver", json.encode{ - p:getId(), - p:getScreenName(), - p:getAvatar() - }) - break - end - end - end - - local function removeObserver(id) - for _, t in ipairs(self.observers) do - local __, p = table.unpack(t) - if p:getId() == id then - table.removeOne(self.observers, t) - self:doBroadcastNotify("RemoveObserver", json.encode{ - p:getId(), - }) - break - end - end - end - - while true do - local ret = false - local request = self.room:fetchRequest() - if request ~= "" then - ret = true - local reqlist = request:split(",") - local id = tonumber(reqlist[1]) - local command = reqlist[2] - if command == "reconnect" then - self:getPlayerById(id):reconnect() - elseif command == "observe" then - addObserver(id) - elseif command == "leave" then - removeObserver(id) - elseif command == "prelight" then - self:getPlayerById(id):prelightSkill(reqlist[3], reqlist[4] == "true") - elseif command == "changeself" then - local toId = tonumber(reqlist[3]) - local from = self:getPlayerById(id) - local to = self:getPlayerById(toId) - local from_sp = from._splayer - - -- 注意发来信息的玩家的主视角可能已经不是自己了 - -- 先换成正确的玩家 - from = table.find(self.players, function(p) - return table.contains(p._observers, from_sp) - end) - - -- 切换视角 - table.removeOne(from._observers, from_sp) - table.insert(to._observers, from_sp) - from_sp:doNotify("ChangeSelf", json.encode { - id = toId, - handcards = to:getCardIds(Player.Hand), - }) - end - elseif rest_time > 10 then - -- let current thread sleep 10ms - -- otherwise CPU usage will be 100% (infinite yield <-> resume loop) - fk.QThread_msleep(10) - end - coroutine.yield(ret) - end -end +Room.requestLoop = require "server.request" --- 延迟一段时间。 --- @@ -2016,6 +1904,15 @@ function Room:doCardEffect(cardEffectEvent) break end end + if not table.contains(players, p) then + for _, s in ipairs(p.player_skills) do + if s.pattern and Exppattern:Parse("nullification"):matchExp(s.pattern) + and not table.contains(cardEffectEvent.disresponsiveList or {}, p.id) then + table.insert(players, p) + break + end + end + end end local prompt = "" diff --git a/packages/standard_cards/init.lua b/packages/standard_cards/init.lua index 6ec4738d..7a6c6af0 100644 --- a/packages/standard_cards/init.lua +++ b/packages/standard_cards/init.lua @@ -670,9 +670,13 @@ local lightningSkill = fk.CreateActiveSkill{ local nextp = to repeat nextp = nextp:getNextAlive() - if nextp == to then return end + if nextp == to then break end until not nextp:hasDelayedTrick("lightning") + if effect.card:isVirtual() then + nextp:addVirtualEquip(effect.card) + end + room:moveCards{ ids = room:getSubcardsByRule(effect.card, { Card.Processing }), to = nextp.id, diff --git a/packages/test/init.lua b/packages/test/init.lua index 30358fc6..57095356 100644 --- a/packages/test/init.lua +++ b/packages/test/init.lua @@ -101,6 +101,7 @@ local test_active = fk.CreateActiveSkill{ } local test_vs = fk.CreateViewAsSkill{ name = "test_vs", + pattern = "nullification", card_filter = function(self, to_select, selected) return #selected == 0 end, @@ -113,6 +114,8 @@ local test_vs = fk.CreateViewAsSkill{ "dismantlement", "savage_assault", "archery_attack", + "lightning", + "nullification", } } end, diff --git a/qml/Pages/Init.qml b/qml/Pages/Init.qml index 245b0063..626353cd 100644 --- a/qml/Pages/Init.qml +++ b/qml/Pages/Init.qml @@ -83,6 +83,7 @@ Item { } TextField { id: screenNameEdit + maximumLength: 32 Layout.fillWidth: true placeholderText: qsTr("Username") text: "" @@ -103,6 +104,7 @@ Item { } TextField { id: passwordEdit + maximumLength: 64 Layout.fillWidth: true placeholderText: qsTr("Password") text: "" diff --git a/qml/Pages/LobbyElement/RoomGeneralSettings.qml b/qml/Pages/LobbyElement/RoomGeneralSettings.qml index 3b0eb07b..27170c78 100644 --- a/qml/Pages/LobbyElement/RoomGeneralSettings.qml +++ b/qml/Pages/LobbyElement/RoomGeneralSettings.qml @@ -15,6 +15,7 @@ ColumnLayout { } TextField { id: roomName + maximumLength: 64 font.pixelSize: 18 text: Backend.translate("$RoomName").arg(Self.screenName) } @@ -70,7 +71,7 @@ ColumnLayout { SpinBox { id: generalNum from: 3 - to: 8 + to: 18 value: config.preferredGeneralNum onValueChanged: { diff --git a/qml/Pages/LobbyElement/UserInfo.qml b/qml/Pages/LobbyElement/UserInfo.qml index ed48cc86..d8ac7dce 100644 --- a/qml/Pages/LobbyElement/UserInfo.qml +++ b/qml/Pages/LobbyElement/UserInfo.qml @@ -27,6 +27,7 @@ ColumnLayout { } TextField { id: avatarName + maximumLength: 64 font.pixelSize: 18 text: Self.avatar } diff --git a/qml/Pages/Room.qml b/qml/Pages/Room.qml index 0ffe7bc2..3201a7c3 100644 --- a/qml/Pages/Room.qml +++ b/qml/Pages/Room.qml @@ -68,12 +68,13 @@ Item { } // tmp - Button { + DelayButton { id: quitButton text: "quit" anchors.top: parent.top anchors.right: parent.right - onClicked: { + delay: Debugging ? 10 : 1000 + onActivated: { // ClientInstance.clearPlayers(); ClientInstance.notifyServer("QuitRoom", "[]"); } diff --git a/qml/Pages/WebInit.qml b/qml/Pages/WebInit.qml index c3ba4f34..33f5cebd 100644 --- a/qml/Pages/WebInit.qml +++ b/qml/Pages/WebInit.qml @@ -22,6 +22,7 @@ Item { spacing: 8 TextField { id: screenNameEdit + maximumLength: 32 text: "player" onTextChanged: { passwordEdit.text = ""; @@ -35,6 +36,7 @@ Item { } TextField { id: passwordEdit + maximumLength: 64 text: "" echoMode: TextInput.Password passwordCharacter: "*"