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.alive_players = {Self}
ClientInstance.discard_pile = {}
local data = json.decode(jsonData)[3]
Fk.disabled_packs = data.disabledPack
ClientInstance:notifyUI("EnterRoom", jsonData)
end

View File

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

View File

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

View File

@ -49,6 +49,11 @@ function table.map(self, func)
return ret
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
---@param self T[]
---@return T[]
@ -151,6 +156,41 @@ function table.random(tab, n)
return n0 == nil and ret[1] or ret
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
---@return string[]
function string:split(delimiter)

View File

@ -88,7 +88,7 @@ function GameLogic:chooseGenerals()
end
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)
for _, p in ipairs(nonlord) do
local arg = {

View File

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

View File

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

View File

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

View File

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

View File

@ -1,102 +1,39 @@
import QtQuick 2.15
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.15
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Item {
id: root
width: childrenRect.width
height: childrenRect.height
anchors.fill: parent
signal finished()
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)
}
TabBar {
id: bar
y: -height
transformOrigin: Item.BottomLeft
rotation: 90
width: root.height
TabButton {
text: Backend.translate("General Settings")
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Player num")
}
SpinBox {
id: playerNum
from: 2
to: 8
}
}
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();
}
}
TabButton {
text: Backend.translate("Package Settings")
}
}
Component.onCompleted: {
let mode_data = JSON.parse(Backend.callLuaFunction("GetGameModes", []));
for (let d of mode_data) {
gameModeList.append(d);
SwipeView {
width: root.width - bar.height - 16
x: bar.height + 16
height: root.height
interactive: false
orientation: Qt.Vertical
currentIndex: bar.currentIndex
RoomGeneralSettings {}
Item {
RoomPackageSettings {
anchors.fill: parent
}
}
gameModeCombo.currentIndex = 0;
}
}

View File

@ -6,13 +6,11 @@ import QtQuick.Dialogs
Item {
id: root
width: childrenRect.width
height: childrenRect.height
signal finished()
ColumnLayout {
spacing: 20
anchors.centerIn: parent
RowLayout {
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,
});
}
}
}