Custom Packages When Creating Room (#76)

添加了创建房间时自选拓展包的功能
This commit is contained in:
notify 2023-03-14 14:12:13 +08:00 committed by GitHub
parent 5f8a06e7df
commit 9b185c439d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 313 additions and 98 deletions

View File

@ -184,6 +184,9 @@ fk.client_callback["EnterRoom"] = function(jsonData)
ClientInstance.players = {Self} ClientInstance.players = {Self}
ClientInstance.alive_players = {Self} ClientInstance.alive_players = {Self}
ClientInstance.discard_pile = {} ClientInstance.discard_pile = {}
local data = json.decode(jsonData)[3]
Fk.disabled_packs = data.disabledPack
ClientInstance:notifyUI("EnterRoom", jsonData) ClientInstance:notifyUI("EnterRoom", jsonData)
end end

View File

@ -21,6 +21,10 @@ Fk:loadTranslationTable{
["Player num"] = "玩家数目", ["Player num"] = "玩家数目",
["Game Mode"] = "游戏模式", ["Game Mode"] = "游戏模式",
["Enable free assign"] = "自由选将", ["Enable free assign"] = "自由选将",
["General Settings"] = "通常设置",
["Package Settings"] = "拓展包设置",
["General Packages"] = "武将拓展包",
["Card Packages"] = "卡牌拓展包",
["Generals Overview"] = "武将一览", ["Generals Overview"] = "武将一览",
["Cards Overview"] = "卡牌一览", ["Cards Overview"] = "卡牌一览",

View File

@ -10,6 +10,7 @@
---@field cards Card[] ---@field cards Card[]
---@field translations table<string, table<string, string>> ---@field translations table<string, table<string, string>>
---@field game_modes table<string, GameMode> ---@field game_modes table<string, GameMode>
---@field disabled_packs string[]
local Engine = class("Engine") local Engine = class("Engine")
function Engine:initialize() function Engine:initialize()
@ -32,6 +33,7 @@ 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:loadPackages() self:loadPackages()
self:addSkills(AuxSkills) self:addSkills(AuxSkills)
@ -207,7 +209,7 @@ function Engine:getGeneralsRandomly(num, generalPool, except, filter)
assert(type(filter) == "function") assert(type(filter) == "function")
end end
generalPool = generalPool or self.generals generalPool = generalPool or self:getAllGenerals()
except = except or {} except = except or {}
for _, g in ipairs(self.packages["test_p_0"].generals) do for _, g in ipairs(self.packages["test_p_0"].generals) do
table.insert(except, g.name) table.insert(except, g.name)
@ -242,11 +244,13 @@ end
---@return General[] ---@return General[]
function Engine:getAllGenerals(except) function Engine:getAllGenerals(except)
local result = {} local result = {}
for _, general in ipairs(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) then
table.insert(result, general) table.insert(result, general)
end end
end end
end
return result return result
end end
@ -257,9 +261,11 @@ 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
table.insert(result, card.id) table.insert(result, card.id)
end end
end end
end
return result return result
end end

View File

@ -49,6 +49,11 @@ function table.map(self, func)
return ret return ret
end end
-- frequenly used filter & map functions
IdMapper = function(e) return e.id end
Id2CardMapper = function(id) return Fk:getCardById(id) end
Id2PlayerMapper = function(id) return Fk:currentRoom():getPlayerById(id) end
---@generic T ---@generic T
---@param self T[] ---@param self T[]
---@return T[] ---@return T[]
@ -151,6 +156,41 @@ function table.random(tab, n)
return n0 == nil and ret[1] or ret return n0 == nil and ret[1] or ret
end end
-- allow a = "Hello"; a[1] == "H"
local str_mt = getmetatable("")
str_mt.__index = function(str, k)
if type(k) == "number" then
if math.abs(k) > str:len() then
error("string index out of range")
end
local start, _end
if k > 0 then
start, _end = utf8.offset(str, k), utf8.offset(str, k + 1)
elseif k < 0 then
local len = str:len()
start, _end = utf8.offset(str, len + k + 1), utf8.offset(str, len + k + 2)
else
error("str[0] is undefined behavior")
end
return str:sub(start, _end - 1)
end
return string[k]
end
str_mt.__add = function(a, b)
return a .. b
end
str_mt.__mul = function(a, b)
return a:rep(b)
end
-- override default string.len
string.rawlen = string.len
function string:len()
return utf8.len(self)
end
---@param delimiter string ---@param delimiter string
---@return string[] ---@return string[]
function string:split(delimiter) function string:split(delimiter)

View File

@ -88,7 +88,7 @@ function GameLogic:chooseGenerals()
end end
local nonlord = room:getOtherPlayers(lord, true) local nonlord = room:getOtherPlayers(lord, true)
local generals = Fk:getGeneralsRandomly(#nonlord * 3, Fk.generals, {lord_general}) local generals = Fk:getGeneralsRandomly(#nonlord * 3, nil, {lord_general})
table.shuffle(generals) table.shuffle(generals)
for _, p in ipairs(nonlord) do for _, p in ipairs(nonlord) do
local arg = { local arg = {

View File

@ -60,6 +60,7 @@ function Room:initialize(_room)
self.room.startGame = function(_self) self.room.startGame = function(_self)
Room.initialize(self, _room) -- clear old data Room.initialize(self, _room) -- clear old data
self.settings = json.decode(_room:settings()) self.settings = json.decode(_room:settings())
Fk.disabled_packs = self.settings.disabledPack
local main_co = coroutine.create(function() local main_co = coroutine.create(function()
self:run() self:run()
end) end)

View File

@ -303,6 +303,8 @@ extension:addCards{
} }
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["maneuvering"] = "军争",
["thunder__slash"] = "雷杀", ["thunder__slash"] = "雷杀",
["fire__slash"] = "火杀", ["fire__slash"] = "火杀",
["iron_chain"] = "铁锁连环", ["iron_chain"] = "铁锁连环",

View File

@ -13,6 +13,9 @@ QtObject {
property string roomBg property string roomBg
property string bgmFile property string bgmFile
property string language property string language
property var disabledPack: []
property string preferedMode
property int preferedPlayerNum
// Player property of client // Player property of client
property string serverAddr property string serverAddr
@ -38,6 +41,9 @@ QtObject {
roomBg = conf.roomBg || AppPath + "/image/gamebg"; roomBg = conf.roomBg || AppPath + "/image/gamebg";
bgmFile = conf.bgmFile || AppPath + "/audio/system/bgm.mp3"; bgmFile = conf.bgmFile || AppPath + "/audio/system/bgm.mp3";
language = conf.language || "zh_CN"; language = conf.language || "zh_CN";
disabledPack = conf.disabledPack || [ "test_p_0" ];
preferedMode = conf.preferedMode || "aaa_role_mode";
preferedPlayerNum = conf.preferedPlayerNum || 2;
} }
function saveConf() { function saveConf() {
@ -51,6 +57,9 @@ QtObject {
conf.roomBg = roomBg; conf.roomBg = roomBg;
conf.bgmFile = bgmFile; conf.bgmFile = bgmFile;
conf.language = language; conf.language = language;
conf.disabledPack = disabledPack;
conf.preferedMode = preferedMode;
conf.preferedPlayerNum = preferedPlayerNum;
Backend.saveConf(JSON.stringify(conf, undefined, 2)); Backend.saveConf(JSON.stringify(conf, undefined, 2));
} }

View File

@ -179,7 +179,7 @@ Item {
Loader { Loader {
id: lobby_dialog id: lobby_dialog
anchors.centerIn: parent anchors.fill: parent
onSourceChanged: { onSourceChanged: {
if (item === null) if (item === null)
return; return;

View File

@ -1,102 +1,39 @@
import QtQuick 2.15 import QtQuick
import QtQuick.Controls 2.0 import QtQuick.Controls
import QtQuick.Layouts 1.15 import QtQuick.Layouts
Item { Item {
id: root id: root
anchors.fill: parent
width: childrenRect.width
height: childrenRect.height
signal finished() signal finished()
ColumnLayout { TabBar {
spacing: 20 id: bar
y: -height
RowLayout { transformOrigin: Item.BottomLeft
anchors.rightMargin: 8 rotation: 90
spacing: 16 width: root.height
Text { TabButton {
text: Backend.translate("Room Name") text: Backend.translate("General Settings")
} }
TextField { TabButton {
id: roomName text: Backend.translate("Package Settings")
font.pixelSize: 18
text: Backend.translate("$RoomName").arg(Self.screenName)
} }
} }
RowLayout { SwipeView {
anchors.rightMargin: 8 width: root.width - bar.height - 16
spacing: 16 x: bar.height + 16
Text { height: root.height
text: Backend.translate("Player num") interactive: false
} orientation: Qt.Vertical
SpinBox { currentIndex: bar.currentIndex
id: playerNum RoomGeneralSettings {}
from: 2 Item {
to: 8 RoomPackageSettings {
} anchors.fill: parent
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Game Mode")
}
ComboBox {
id: gameModeCombo
textRole: "name"
model: ListModel {
id: gameModeList
}
onCurrentIndexChanged: {
let data = gameModeList.get(currentIndex);
playerNum.from = data.minPlayer;
playerNum.to = data.maxPlayer;
}
}
}
CheckBox {
id: freeAssignCheck
checked: Debugging ? true : false
text: Backend.translate("Enable free assign")
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Button {
text: Backend.translate("OK")
onClicked: {
root.finished();
mainWindow.busy = true;
ClientInstance.notifyServer(
"CreateRoom",
JSON.stringify([roomName.text, playerNum.value, {
enableFreeAssign: freeAssignCheck.checked,
gameMode: gameModeList.get(gameModeCombo.currentIndex).orig_name,
}])
);
}
}
Button {
text: Backend.translate("Cancel")
onClicked: {
root.finished();
} }
} }
} }
} }
Component.onCompleted: {
let mode_data = JSON.parse(Backend.callLuaFunction("GetGameModes", []));
for (let d of mode_data) {
gameModeList.append(d);
}
gameModeCombo.currentIndex = 0;
}
}

View File

@ -6,13 +6,11 @@ import QtQuick.Dialogs
Item { Item {
id: root id: root
width: childrenRect.width
height: childrenRect.height
signal finished() signal finished()
ColumnLayout { ColumnLayout {
spacing: 20 spacing: 20
anchors.centerIn: parent
RowLayout { RowLayout {
anchors.rightMargin: 8 anchors.rightMargin: 8

View File

@ -0,0 +1,106 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ColumnLayout {
spacing: 20
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Room Name")
}
TextField {
id: roomName
font.pixelSize: 18
text: Backend.translate("$RoomName").arg(Self.screenName)
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Player num")
}
SpinBox {
id: playerNum
from: 2
to: 8
onValueChanged: {
config.preferedPlayerNum = value;
}
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Game Mode")
}
ComboBox {
id: gameModeCombo
textRole: "name"
model: ListModel {
id: gameModeList
}
onCurrentIndexChanged: {
let data = gameModeList.get(currentIndex);
playerNum.from = data.minPlayer;
playerNum.to = data.maxPlayer;
config.preferedMode = data.orig_name;
}
}
}
CheckBox {
id: freeAssignCheck
checked: Debugging ? true : false
text: Backend.translate("Enable free assign")
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Button {
text: Backend.translate("OK")
onClicked: {
root.finished();
mainWindow.busy = true;
ClientInstance.notifyServer(
"CreateRoom",
JSON.stringify([roomName.text, playerNum.value, {
enableFreeAssign: freeAssignCheck.checked,
gameMode: config.preferedMode,
disabledPack: config.disabledPack,
}])
);
}
}
Button {
text: Backend.translate("Cancel")
onClicked: {
root.finished();
}
}
}
Component.onCompleted: {
let mode_data = JSON.parse(Backend.callLuaFunction("GetGameModes", []));
let i = 0;
for (let d of mode_data) {
gameModeList.append(d);
if (d.orig_name == config.preferedMode) {
gameModeCombo.currentIndex = i;
}
i += 1;
}
playerNum.value = config.preferedPlayerNum;
}
}

View File

@ -0,0 +1,109 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Flickable {
id: root
flickableDirection: Flickable.AutoFlickIfNeeded
clip: true
contentHeight: layout.height
ScrollBar.vertical: ScrollBar {
parent: root.parent
anchors.top: root.top
anchors.right: root.right
anchors.bottom: root.bottom
}
ColumnLayout {
id: layout
anchors.top: parent.top
anchors.topMargin: 8
CheckBox {
text: "禁用Lua拓展 (重启后生效)"
}
Text {
text: Backend.translate("General Packages")
font.bold: true
}
GridLayout {
id: gpacks
columns: 2
Repeater {
model: ListModel {
id: gpacklist
}
CheckBox {
text: name
checked: pkg_enabled
enabled: orig_name !== "test_p_0"
onCheckedChanged: {
let packs = config.disabledPack;
if (checked) {
let idx = packs.indexOf(orig_name);
if (idx !== -1) packs.splice(idx, 1);
} else {
packs.push(orig_name);
}
}
}
}
}
Text {
text: Backend.translate("Card Packages")
font.bold: true
}
GridLayout {
id: cpacks
columns: 2
Repeater {
model: ListModel {
id: cpacklist
}
CheckBox {
text: name
checked: pkg_enabled
onCheckedChanged: {
let packs = config.disabledPack;
if (checked) {
let idx = packs.indexOf(orig_name);
if (idx !== -1) packs.splice(idx, 1);
} else {
packs.push(orig_name);
}
}
}
}
}
}
Component.onCompleted: {
let g = JSON.parse(Backend.callLuaFunction("GetAllGeneralPack", []));
for (let orig of g) {
gpacklist.append({
name: Backend.translate(orig),
orig_name: orig,
pkg_enabled: config.disabledPack.indexOf(orig) === -1,
});
}
let c = JSON.parse(Backend.callLuaFunction("GetAllCardPack", []));
for (let orig of c) {
cpacklist.append({
name: Backend.translate(orig),
orig_name: orig,
pkg_enabled: config.disabledPack.indexOf(orig) === -1,
});
}
}
}