2v2选将相关 (#305)

以及完善了移牌的log
This commit is contained in:
notify 2024-01-11 18:36:05 +08:00 committed by GitHub
parent 1bc6453599
commit 92768735fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 258 additions and 80 deletions

View File

@ -1575,6 +1575,25 @@ callbacks["CustomDialog"] = (j) => {
} }
} }
callbacks["MiniGame"] = (j) => {
const data = JSON.parse(j);
const game = data.type;
const dat = data.data;
const gdata = JSON.parse(Backend.callLuaFunction("GetMiniGame", [game, Self.id, JSON.stringify(dat)]));
roomScene.state = "replying";
roomScene.popupBox.source = AppPath + "/" + gdata.qml_path + ".qml";
if (dat) {
roomScene.popupBox.item.loadData(dat);
}
}
callbacks["UpdateMiniGame"] = (j) => {
const data = JSON.parse(j);
if (roomScene.popupBox.item) {
roomScene.popupBox.item.updateData(data);
}
}
callbacks["UpdateLimitSkill"] = (j) => { callbacks["UpdateLimitSkill"] = (j) => {
const data = JSON.parse(j); const data = JSON.parse(j);
const id = data[0]; const id = data[0];

View File

@ -509,7 +509,91 @@ local function sendMoveCardLog(move)
local hidden = table.contains(move.ids, -1) local hidden = table.contains(move.ids, -1)
local msgtype local msgtype
if move.from and move.toArea == Card.DrawPile then if move.toArea == Card.PlayerHand then
if move.fromArea == Card.PlayerSpecial then
client:appendLog{
type = "$GetCardsFromPile",
from = move.to,
arg = move.fromSpecialName,
arg2 = #move.ids,
card = move.ids,
}
elseif move.fromArea == Card.DrawPile then
client:appendLog{
type = "$DrawCards",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif move.fromArea == Card.Processing then
client:appendLog{
type = "$GotCardBack",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif move.fromArea == Card.DiscardPile then
client:appendLog{
type = "$RecycleCard",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif move.from then
client:appendLog{
type = "$MoveCards",
from = move.from,
to = { move.to },
arg = #move.ids,
card = move.ids,
}
else
client:appendLog{
type = "$PreyCardsFromPile",
from = move.to,
card = move.ids,
arg = #move.ids,
}
end
elseif move.toArea == Card.PlayerEquip then
client:appendLog{
type = "$InstallEquip",
from = move.to,
card = move.ids,
}
elseif move.toArea == Card.PlayerJudge then
if move.from ~= move.to and move.fromArea == Card.PlayerJudge then
client:appendLog{
type = "$LightningMove",
from = move.from,
to = { move.to },
card = move.ids,
}
elseif move.from then
client:appendLog{
type = "$PasteCard",
from = move.from,
to = { move.to },
card = move.ids,
}
end
elseif move.toArea == Card.PlayerSpecial then
client:appendLog{
type = "$AddToPile",
arg = move.specialName,
arg2 = #move.ids,
from = move.to,
card = move.ids,
}
elseif move.fromArea == Card.PlayerEquip then
client:appendLog{
type = "$UninstallEquip",
from = move.from,
card = move.ids,
}
-- elseif move.toArea == Card.Processing then
-- nop
elseif move.from and move.toArea == Card.DrawPile then
msgtype = hidden and "$PutCard" or "$PutKnownCard" msgtype = hidden and "$PutCard" or "$PutKnownCard"
client:appendLog{ client:appendLog{
type = msgtype, type = msgtype,
@ -521,78 +605,7 @@ local function sendMoveCardLog(move)
type = "$$PutCard", type = "$$PutCard",
from = move.from, from = move.from,
}) })
elseif move.toArea == Card.PlayerSpecial then elseif move.toArea == Card.DiscardPile then
msgtype = hidden and "$RemoveCardFromGame" or "$AddToPile"
client:appendLog{
type = msgtype,
arg = move.specialName,
arg2 = #move.ids,
card = move.ids,
}
elseif move.fromArea == Card.PlayerSpecial and move.to then
client:appendLog{
type = "$GetCardsFromPile",
from = move.to,
arg = move.fromSpecialName,
arg2 = #move.ids,
card = move.ids,
}
elseif move.moveReason == fk.ReasonDraw then
client:appendLog{
type = "$DrawCards",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif (move.fromArea == Card.DrawPile or move.fromArea == Card.DiscardPile)
and move.moveReason == fk.ReasonPrey then
client:appendLog{
type = "$PreyCardsFromPile",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif (move.fromArea == Card.Processing or move.fromArea == Card.PlayerJudge)
and move.toArea == Card.PlayerHand then
client:appendLog{
type = "$GotCardBack",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif move.fromArea == Card.DiscardPile and move.toArea == Card.PlayerHand then
client:appendLog{
type = "$RecycleCard",
from = move.to,
card = move.ids,
arg = #move.ids,
}
elseif move.from and move.fromArea ~= Card.PlayerJudge and
move.toArea ~= Card.PlayerJudge and move.to and move.from ~= move.to then
client:appendLog{
type = "$MoveCards",
from = move.from,
to = { move.to },
arg = #move.ids,
card = move.ids,
}
elseif move.from and move.to and move.toArea == Card.PlayerJudge then
if move.fromArea == Card.PlayerJudge and move.from ~= move.to then
msgtype = "$LightningMove"
elseif move.fromArea ~= Card.PlayerJudge then
msgtype = "$PasteCard"
end
if msgtype then
client:appendLog{
type = msgtype,
from = move.from,
to = { move.to },
card = move.ids,
}
end
end
-- TODO ...
if move.moveReason == fk.ReasonDiscard then if move.moveReason == fk.ReasonDiscard then
client:appendLog{ client:appendLog{
type = "$DiscardCards", type = "$DiscardCards",
@ -600,6 +613,19 @@ local function sendMoveCardLog(move)
card = move.ids, card = move.ids,
arg = #move.ids, arg = #move.ids,
} }
elseif move.moveReason == fk.ReasonPutIntoDiscardPile then
client:appendLog{
type = "$PutToDiscard",
card = move.ids,
arg = #move.ids,
}
end
-- elseif move.toArea == Card.Void then
-- nop
end
-- TODO: footnote
if move.moveReason == fk.ReasonDiscard then
client:setCardNote(move.ids, { client:setCardNote(move.ids, {
type = "$$DiscardCards", type = "$$DiscardCards",
from = move.from from = move.from

View File

@ -748,4 +748,13 @@ function GetQmlMark(mtype, name, value, p)
} }
end end
function GetMiniGame(gtype, p, data)
local spec = Fk.mini_games[gtype]
p = ClientInstance:getPlayerById(p)
data = json.decode(data)
return json.encode {
qml_path = type(spec.qml_path) == "function" and spec.qml_path(p, data) or spec.qml_path,
}
end
dofile "lua/client/i18n/init.lua" dofile "lua/client/i18n/init.lua"

View File

@ -386,22 +386,26 @@ Fk:loadTranslationTable{
["#LoseSkill"] = "%from 失去了技能 “%arg”", ["#LoseSkill"] = "%from 失去了技能 “%arg”",
-- moveCards (they are sent by notifyMoveCards) -- moveCards (they are sent by notifyMoveCards)
["$PutCard"] = "%from 的 %arg 张牌被置于牌堆",
["$PutKnownCard"] = "%from 的牌 %card 被置于牌堆",
["$RemoveCardFromGame"] = "%arg2 张牌被作为 %arg 移出游戏",
["$AddToPile"] = "%card 被作为 %arg 移出游戏",
["$GetCardsFromPile"] = "%from 从 %arg 中获得了 %arg2 张牌 %card", ["$GetCardsFromPile"] = "%from 从 %arg 中获得了 %arg2 张牌 %card",
["$DrawCards"] = "%from 摸了 %arg 张牌 %card", ["$DrawCards"] = "%from 摸了 %arg 张牌 %card",
["$MoveCards"] = "%to 从 %from 处获得了 %arg 张牌 %card",
["$PreyCardsFromPile"] = "%from 获得了 %arg 张牌 %card", ["$PreyCardsFromPile"] = "%from 获得了 %arg 张牌 %card",
["$GotCardBack"] = "%from 收回了 %arg 张牌 %card", ["$GotCardBack"] = "%from 收回了 %arg 张牌 %card",
["$RecycleCard"] = "%from 从弃牌堆回收了 %arg 张牌 %card", ["$RecycleCard"] = "%from 从弃牌堆回收了 %arg 张牌 %card",
["$MoveCards"] = "%to 从 %from 处获得了 %arg 张牌 %card",
["$LightningMove"] = "%card 从 %from 转移到了 %to",
["$PasteCard"] = "%from 给 %to 贴了张 %card",
["$DiscardCards"] = "%from 弃置了 %arg 张牌 %card",
["$InstallEquip"] = "%from 装备了 %card", ["$InstallEquip"] = "%from 装备了 %card",
["$UninstallEquip"] = "%from 卸载了 %card", ["$UninstallEquip"] = "%from 卸载了 %card",
["$LightningMove"] = "%card 从 %from 转移到了 %to",
["$PasteCard"] = "%from 给 %to 贴了张 %card",
["$AddToPile"] = "%arg2 张牌 %card 被作为 %from 的 %arg 移出游戏",
["$PutCard"] = "%from 的 %arg 张牌被置于牌堆",
["$PutKnownCard"] = "%from 的牌 %card 被置于牌堆",
["$DiscardCards"] = "%from 弃置了 %arg 张牌 %card",
["$PutToDiscard"] = "%arg 张牌 %card 被置入弃牌堆",
["#ShowCard"] = "%from 展示了牌 %card", ["#ShowCard"] = "%from 展示了牌 %card",
["#Recast"] = "%from 重铸了 %card", ["#Recast"] = "%from 重铸了 %card",
["#RecastBySkill"] = "%from 发动了 “%arg” 重铸了 %card", ["#RecastBySkill"] = "%from 发动了 “%arg” 重铸了 %card",

View File

@ -28,6 +28,7 @@
---@field private _custom_events any[] @ 自定义事件列表 ---@field private _custom_events any[] @ 自定义事件列表
---@field public poxi_methods table<string, PoxiSpec> @ “魄袭”框操作方法表 ---@field public poxi_methods table<string, PoxiSpec> @ “魄袭”框操作方法表
---@field public qml_marks table<string, QmlMarkSpec> @ 自定义Qml标记的表 ---@field public qml_marks table<string, QmlMarkSpec> @ 自定义Qml标记的表
---@field public mini_games table<string, MiniGameSpec> @ 自定义多人交互表
local Engine = class("Engine") local Engine = class("Engine")
--- Engine的构造函数。 --- Engine的构造函数。
@ -61,6 +62,7 @@ function Engine:initialize()
self._custom_events = {} self._custom_events = {}
self.poxi_methods = {} self.poxi_methods = {}
self.qml_marks = {} self.qml_marks = {}
self.mini_games = {}
self:loadPackages() self:loadPackages()
self:loadDisabled() self:loadDisabled()
@ -356,6 +358,7 @@ function Engine:addPoxiMethod(spec)
spec.post_select = spec.post_select or function(s) return s end spec.post_select = spec.post_select or function(s) return s end
end end
---@param spec QmlMarkSpec
function Engine:addQmlMark(spec) function Engine:addQmlMark(spec)
assert(type(spec.name) == "string") assert(type(spec.name) == "string")
if self.qml_marks[spec.name] then if self.qml_marks[spec.name] then
@ -364,6 +367,15 @@ function Engine:addQmlMark(spec)
self.qml_marks[spec.name] = spec self.qml_marks[spec.name] = spec
end end
---@param spec MiniGameSpec
function Engine:addMiniGame(spec)
assert(type(spec.name) == "string")
if self.mini_games[spec.name] then
fk.qCritical("Warning: duplicated mini game type " .. spec.name)
end
self.mini_games[spec.name] = spec
end
--- 从已经开启的拓展包中,随机选出若干名武将。 --- 从已经开启的拓展包中,随机选出若干名武将。
--- ---
--- 对于同名武将不会重复选取。 --- 对于同名武将不会重复选取。

View File

@ -608,3 +608,10 @@ end
---@field name string ---@field name string
---@field qml_path string | fun(name: string, value?: any, player?: Player): string ---@field qml_path string | fun(name: string, value?: any, player?: Player): string
---@field how_to_show fun(name: string, value?: any, player?: Player): string? ---@field how_to_show fun(name: string, value?: any, player?: Player): string?
-- TODO: 断连 不操作的人观看 现在只做了专为22设计的框
---@class MiniGameSpec
---@field name string
---@field qml_path string | fun(player: Player, data: any): string
---@field update_func? fun(player: ServerPlayer, data: any)
---@field default_choice? fun(player: ServerPlayer, data: any): any

View File

@ -439,6 +439,10 @@ function GameLogic:start()
e = self:getCurrentCleaner() e = self:getCurrentCleaner()
end end
if not e then -- 没有事件,按理说不应该,平局处理
self.room:gameOver("")
end
-- ret, evt解释 -- ret, evt解释
-- * true, nil: 中止 -- * true, nil: 中止
-- * false, nil: 正常结束 -- * false, nil: 正常结束

View File

@ -182,6 +182,18 @@ request_handlers["surrender"] = function(room, id, reqlist)
end end
end end
request_handlers["updatemini"] = function(room, pid, reqlist)
local player = room:getPlayerById(pid)
local data = player.mini_game_data
if not data then return end
local game = Fk.mini_games[data.type]
if not (game and game.update_func) then return end
local dat = table.simpleClone(reqlist)
table.remove(dat, 1)
table.remove(dat, 1)
game.update_func(player, dat)
end
request_handlers["newroom"] = function(s, id) request_handlers["newroom"] = function(s, id)
s:registerRoom(id) s:registerRoom(id)
end end

View File

@ -2214,6 +2214,34 @@ function Room:closeAG(player)
else self:doBroadcastNotify("CloseAG", "") end else self:doBroadcastNotify("CloseAG", "") end
end end
-- TODO: 重构request机制不然这个还得手动拿client_reply
---@param players ServerPlayer[]
---@param focus string
---@param game_type string
---@param data_table table<integer, any> @ 对应每个player
function Room:askForMiniGame(players, focus, game_type, data_table)
local command = "MiniGame"
local game = Fk.mini_games[game_type]
if #players == 0 or not game then return end
for _, p in ipairs(players) do
local data = data_table[p.id]
p.mini_game_data = { type = game_type, data = data }
p.request_data = json.encode(p.mini_game_data)
p.default_reply = game.default_choice and json.encode(game.default_choice(p, data)) or ""
end
self:notifyMoveFocus(players, focus)
self:doBroadcastRequest(command, players)
for _, p in ipairs(players) do
p.mini_game_data = nil
if not p.reply_ready then
p.client_reply = p.default_reply
p.reply_ready = true
end
end
end
-- Show a qml dialog and return qml's ClientInstance.replyToServer -- Show a qml dialog and return qml's ClientInstance.replyToServer
-- Do anything you like through this function -- Do anything you like through this function

View File

@ -5,6 +5,7 @@
---@field public room Room ---@field public room Room
---@field public next ServerPlayer ---@field public next ServerPlayer
---@field public request_data string ---@field public request_data string
---@field public mini_game_data any
---@field public client_reply string ---@field public client_reply string
---@field public default_reply string ---@field public default_reply string
---@field public reply_ready boolean ---@field public reply_ready boolean

View File

@ -88,6 +88,8 @@ local control = fk.CreateActiveSkill{
-- }, from.hp, false)) -- }, from.hp, false))
-- room:setPlayerMark(from, "@$a", {1,2,3}) -- room:setPlayerMark(from, "@$a", {1,2,3})
-- room:setPlayerMark(from, "@$b", {'slash','duel','axe'}) -- room:setPlayerMark(from, "@$b", {'slash','duel','axe'})
--room:askForMiniGame({from}, "test", "test", { [from.id] = {"Helloworld"} })
--print(from.client_reply)
if to:getMark("mouxushengcontrolled") == 0 then if to:getMark("mouxushengcontrolled") == 0 then
room:addPlayerMark(to, "mouxushengcontrolled") room:addPlayerMark(to, "mouxushengcontrolled")
from:control(to) from:control(to)
@ -126,6 +128,13 @@ local control = fk.CreateActiveSkill{
end, end,
} }
--[[ --[[
Fk:addMiniGame{
name = "test",
qml_path = "packages/test/qml/TestMini",
update_func = function(player, data)
player:doNotify("UpdateMiniGame", json.encode(data))
end
}
Fk:addPoxiMethod{ Fk:addPoxiMethod{
name = "test", name = "test",
card_filter = function(to_select, selected, data, extra_data) card_filter = function(to_select, selected, data, extra_data)

View File

@ -0,0 +1,47 @@
//
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Fk.RoomElement
GraphicsBox {
id: root
height: 200; width: 300
ColumnLayout {
Text {
id: txt
color: "white"
}
Button {
text: "Btn 1"
onClicked: {
ClientInstance.notifyServer("PushRequest", "updatemini,B1")
}
}
Button {
text: "Btn 2"
onClicked: {
ClientInstance.notifyServer("PushRequest", "updatemini,B2")
}
}
Button {
text: "Reply"
onClicked: {
close();
roomScene.state = "notactive";
ClientInstance.replyToServer("", JSON.stringify("Hello"));
}
}
}
function loadData(data) {
txt.text = data[0]
}
function updateData(data) {
txt.text = JSON.stringify(data) + " updated"
}
}