- 调度器善后
- 修复可用不足警告
- 创房时可以全选或者反选
- 重连时候不可以重新开大
- 顶号
This commit is contained in:
notify 2023-06-16 13:26:02 +08:00 committed by GitHub
parent e2c4d326c5
commit 02e22024f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 175 additions and 54 deletions

View File

@ -87,7 +87,12 @@ Flickable {
Text { Text {
id: warning id: warning
anchors.rightMargin: 8 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") text: Backend.translate("No enough generals")
color: "red" color: "red"
} }
@ -159,6 +164,7 @@ Flickable {
text: Backend.translate("OK") text: Backend.translate("OK")
enabled: !(warning.visible) enabled: !(warning.visible)
onClicked: { onClicked: {
config.saveConf();
root.finished(); root.finished();
mainWindow.busy = true; mainWindow.busy = true;
@ -208,6 +214,11 @@ Flickable {
} }
playerNum.value = config.preferedPlayerNum; playerNum.value = config.preferedPlayerNum;
config.disabledPack.forEach(p => {
Backend.callLuaFunction("UpdatePackageEnable", [p, false]);
});
config.disabledPackChanged();
} }
} }
} }

View File

@ -25,16 +25,36 @@ Flickable {
text: "禁用Lua拓展 (重启后生效)" text: "禁用Lua拓展 (重启后生效)"
} }
RowLayout {
Text { Text {
text: Backend.translate("General Packages") text: Backend.translate("General Packages")
font.bold: true 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 { GridLayout {
id: gpacks
columns: 2 columns: 2
Repeater { Repeater {
id: gpacks
model: ListModel { model: ListModel {
id: gpacklist id: gpacklist
} }
@ -45,28 +65,42 @@ Flickable {
enabled: orig_name !== "test_p_0" enabled: orig_name !== "test_p_0"
onCheckedChanged: { onCheckedChanged: {
const packs = config.disabledPack; checkPackage(orig_name, checked);
if (checked) {
const idx = packs.indexOf(orig_name);
if (idx !== -1) packs.splice(idx, 1);
} else {
packs.push(orig_name);
}
} }
} }
} }
} }
RowLayout {
Text { Text {
text: Backend.translate("Card Packages") text: Backend.translate("Card Packages")
font.bold: true 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 { GridLayout {
id: cpacks
columns: 2 columns: 2
Repeater { Repeater {
id: cpacks
model: ListModel { model: ListModel {
id: cpacklist id: cpacklist
} }
@ -76,6 +110,14 @@ Flickable {
checked: pkg_enabled checked: pkg_enabled
onCheckedChanged: { onCheckedChanged: {
checkPackage(orig_name, checked);
}
}
}
}
}
function checkPackage(orig_name, checked) {
const packs = config.disabledPack; const packs = config.disabledPack;
if (checked) { if (checked) {
const idx = packs.indexOf(orig_name); const idx = packs.indexOf(orig_name);
@ -83,10 +125,8 @@ Flickable {
} else { } else {
packs.push(orig_name); packs.push(orig_name);
} }
} Backend.callLuaFunction("UpdatePackageEnable", [orig_name, checked]);
} config.disabledPackChanged();
}
}
} }
Component.onCompleted: { Component.onCompleted: {

View File

@ -410,10 +410,19 @@ Item {
anchors.rightMargin: 20 anchors.rightMargin: 20
color: "#88EEEEEE" color: "#88EEEEEE"
radius: 8 radius: 8
visible: roomScene.state === "playing" && (specialCardSkills ?? false) visible: {
&& (specialCardSkills.count > 1 if (roomScene.state !== "playing") {
|| ((specialCardSkills.model ?? false) return false;
&& specialCardSkills.model[0] !== "_normal_use")) }
if (!specialCardSkills) {
return false;
}
if (specialCardSkills.count > 1) {
return true;
}
return (specialCardSkills.model ?? false)
&& specialCardSkills.model[0] !== "_normal_use"
}
width: childrenRect.width width: childrenRect.width
height: childrenRect.height - 20 height: childrenRect.height - 20
@ -487,21 +496,20 @@ Item {
onSourceChanged: { onSourceChanged: {
if (item === null) if (item === null)
return; return;
item.finished.connect(function(){ item.finished.connect(() => {
sourceComponent = undefined; sourceComponent = undefined;
}); });
item.widthChanged.connect(function(){ item.widthChanged.connect(() => {
popupBox.moveToCenter(); popupBox.moveToCenter();
}); });
item.heightChanged.connect(function(){ item.heightChanged.connect(() => {
popupBox.moveToCenter(); popupBox.moveToCenter();
}); });
moveToCenter(); moveToCenter();
} }
onSourceComponentChanged: sourceChanged(); onSourceComponentChanged: sourceChanged();
function moveToCenter() function moveToCenter() {
{
item.x = Math.round((roomArea.width - item.width) / 2); item.x = Math.round((roomArea.width - item.width) / 2);
item.y = Math.round(roomArea.height * 0.67 - item.height / 2); item.y = Math.round(roomArea.height * 0.67 - item.height / 2);
} }

View File

@ -215,6 +215,10 @@
<source>others logged in with this name</source> <source>others logged in with this name</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>others logged in again with this name</source>
<translation></translation>
</message>
<message> <message>
<source>invalid user name</source> <source>invalid user name</source>
<translation></translation> <translation></translation>

View File

@ -43,6 +43,9 @@ function Client:initialize()
for class, skills in pairs(Fk.global_status_skill) do for class, skills in pairs(Fk.global_status_skill) do
self.status_skills[class] = {table.unpack(skills)} self.status_skills[class] = {table.unpack(skills)}
end end
self.disabled_packs = {}
self.disabled_generals = {}
end end
---@param id integer ---@param id integer
@ -236,8 +239,8 @@ fk.client_callback["EnterRoom"] = function(jsonData)
local data = json.decode(jsonData)[3] local data = json.decode(jsonData)[3]
ClientInstance.room_settings = data ClientInstance.room_settings = data
Fk.disabled_packs = data.disabledPack ClientInstance.disabled_packs = data.disabledPack
Fk.disabled_generals = data.disabledGenerals ClientInstance.disabled_generals = data.disabledGenerals
ClientInstance:notifyUI("EnterRoom", jsonData) ClientInstance:notifyUI("EnterRoom", jsonData)
end end
@ -750,6 +753,7 @@ end
fk.client_callback["ChangeSelf"] = function(jsonData) fk.client_callback["ChangeSelf"] = function(jsonData)
local data = json.decode(jsonData) local data = json.decode(jsonData)
ClientInstance:getPlayerById(data.id).player_cards[Player.Hand] = data.handcards ClientInstance:getPlayerById(data.id).player_cards[Player.Hand] = data.handcards
ClientInstance:getPlayerById(data.id).special_cards = data.special_cards
ClientInstance:notifyUI("ChangeSelf", data.id) ClientInstance:notifyUI("ChangeSelf", data.id)
end end

View File

@ -126,6 +126,14 @@ function GetGenerals(pack_name)
return json.encode(ret) return json.encode(ret)
end 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() function GetAvailableGeneralsNum()
local generalPool = Fk:getAllGenerals() local generalPool = Fk:getAllGenerals()
local except = {} local except = {}
@ -552,8 +560,8 @@ function ResetClientLua()
ClientInstance.discard_pile = {} ClientInstance.discard_pile = {}
ClientInstance.room_settings = data ClientInstance.room_settings = data
Fk.disabled_packs = data.disabledPack ClientInstance.disabled_packs = data.disabledPack
Fk.disabled_generals = data.disabledGenerals ClientInstance.disabled_generals = data.disabledGenerals
-- ClientInstance:notifyUI("EnterRoom", jsonData) -- ClientInstance:notifyUI("EnterRoom", jsonData)
end end

View File

@ -46,6 +46,8 @@ Fk:loadTranslationTable{
["Package Settings"] = "拓展包设置", ["Package Settings"] = "拓展包设置",
["General Packages"] = "武将拓展包", ["General Packages"] = "武将拓展包",
["Card Packages"] = "卡牌拓展包", ["Card Packages"] = "卡牌拓展包",
["Select All"] = "全选",
["Revert Selection"] = "反选",
["Give Flower"] = "送花", ["Give Flower"] = "送花",
["Give Egg"] = "砸蛋", ["Give Egg"] = "砸蛋",

View File

@ -19,7 +19,6 @@
---@field public cards Card[] @ 所有卡牌 ---@field public cards Card[] @ 所有卡牌
---@field public translations table<string, table<string, string>> @ 翻译表 ---@field public translations table<string, table<string, string>> @ 翻译表
---@field public game_modes table<string, GameMode> @ 所有游戏模式 ---@field public game_modes table<string, GameMode> @ 所有游戏模式
---@field public disabled_packs string[] @ 禁用的拓展包列表
---@field public currentResponsePattern string @ 要求用牌的种类(如要求用特定花色的桃···) ---@field public currentResponsePattern string @ 要求用牌的种类(如要求用特定花色的桃···)
---@field public currentResponseReason string @ 要求用牌的原因(如濒死,被特定牌指定,使用特定技能···) ---@field public currentResponseReason string @ 要求用牌的原因(如濒死,被特定牌指定,使用特定技能···)
local Engine = class("Engine") local Engine = class("Engine")
@ -49,14 +48,31 @@ function Engine:initialize()
self.cards = {} -- Card[] self.cards = {} -- Card[]
self.translations = {} -- srcText --> translated self.translations = {} -- srcText --> translated
self.game_modes = {} self.game_modes = {}
self.disabled_packs = {}
self.disabled_generals = {}
self.kingdoms = {} self.kingdoms = {}
self:loadPackages() self:loadPackages()
self:addSkills(AuxSkills) self:addSkills(AuxSkills)
end 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中加载一个拓展包。 --- 向Engine中加载一个拓展包。
--- ---
--- 会加载这个拓展包含有的所有武将、卡牌以及游戏模式。 --- 会加载这个拓展包含有的所有武将、卡牌以及游戏模式。
@ -204,6 +220,12 @@ function Engine:addGenerals(generals)
end end
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 tName = tmp[#tmp]
local ret = self.same_generals[tName] or {} local ret = self.same_generals[tName] or {}
return table.filter(ret, function(g) return table.filter(ret, function(g)
return g ~= name and self.generals[g] ~= nil and return g ~= name and self.generals[g] ~= nil and canUseGeneral(g)
not table.contains(self.disabled_packs, self.generals[g].package.name) and
not table.contains(self.disabled_generals, g)
end) end)
end end
@ -336,7 +356,7 @@ function Engine:getAllGenerals(except)
local result = {} local result = {}
for _, general in pairs(self.generals) do for _, general in pairs(self.generals) do
if not (except and table.contains(except, general)) then 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) table.insert(result, general)
end end
end end
@ -352,7 +372,7 @@ function Engine:getAllCardIds(except)
local result = {} local result = {}
for _, card in ipairs(self.cards) do for _, card in ipairs(self.cards) do
if not (except and table.contains(except, card.id)) then 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) table.insert(result, card.id)
end end
end end

View File

@ -541,10 +541,9 @@ function Player:setSkillUseHistory(skill_name, num, scope)
return return
end end
if self.skillUsedHistory[skill_name] then self.skillUsedHistory[skill_name] = self.skillUsedHistory[skill_name] or {0, 0, 0, 0}
self.skillUsedHistory[skill_name][scope] = num self.skillUsedHistory[skill_name][scope] = num
end end
end
--- 获取玩家使用特定牌的历史次数。 --- 获取玩家使用特定牌的历史次数。
---@param cardName string @ 牌名 ---@param cardName string @ 牌名

View File

@ -131,6 +131,7 @@ request_handlers["changeself"] = function(room, id, reqlist)
from_sp:doNotify("ChangeSelf", json.encode { from_sp:doNotify("ChangeSelf", json.encode {
id = toId, id = toId,
handcards = to:getCardIds(Player.Hand), handcards = to:getCardIds(Player.Hand),
special_cards = to.special_cards,
}) })
end end

View File

@ -90,8 +90,8 @@ function Room:initialize(_room)
self.skill_costs = {} self.skill_costs = {}
self.settings = json.decode(self.room:settings()) self.settings = json.decode(self.room:settings())
Fk.disabled_packs = self.settings.disabledPack self.disabled_packs = self.settings.disabledPack
Fk.disabled_generals = self.settings.disabledGenerals self.disabled_generals = self.settings.disabledGenerals
end end
-- 供调度器使用的函数。能让房间开始运行/从挂起状态恢复。 -- 供调度器使用的函数。能让房间开始运行/从挂起状态恢复。

View File

@ -233,12 +233,26 @@ function ServerPlayer:marshal(player)
} }
table.insert(card_moves, move) table.insert(card_moves, move)
end 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 if #card_moves > 0 then
room:notifyMoveCards({ player }, card_moves) room:notifyMoveCards({ player }, card_moves)
end end
-- TODO: pile
for k, v in pairs(self.mark) do for k, v in pairs(self.mark) do
player:doNotify("SetPlayerMark", json.encode{self.id, k, v}) player:doNotify("SetPlayerMark", json.encode{self.id, k, v})
end end
@ -254,8 +268,11 @@ function ServerPlayer:marshal(player)
end end
for k, v in pairs(self.skillUsedHistory) do for k, v in pairs(self.skillUsedHistory) do
if v[1] > 0 then if v[4] > 0 then
player:doNotify("AddSkillUseHistory", json.encode{self.id, k, v[1]}) player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[1], 1})
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[2], 2})
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[3], 3})
player:doNotify("SetSkillUseHistory", json.encode{self.id, k, v[4], 4})
end end
end end

View File

@ -397,6 +397,12 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
error_msg = "username or password error"; error_msg = "username or password error";
} else { } else {
auto player = players.value(id); 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) { if (player->getState() == Player::Offline) {
auto room = player->getRoom(); auto room = player->getRoom();
player->setSocket(client); player->setSocket(client);
@ -417,7 +423,7 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
} else { } else {
// 懒得处理掉线玩家在大厅了!踢掉得了 // 懒得处理掉线玩家在大厅了!踢掉得了
player->doNotify("ErrorMsg", "Unknown Error"); player->doNotify("ErrorMsg", "Unknown Error");
player->kicked(); emit player->kicked();
} }
return; return;

View File

@ -105,6 +105,7 @@ void ServerPlayer::prepareForRequest(const QString &command,
} }
void ServerPlayer::kick() { void ServerPlayer::kick() {
setState(Player::Offline);
if (socket != nullptr) { if (socket != nullptr) {
socket->disconnectFromHost(); socket->disconnectFromHost();
} }