diff --git a/Fk/Cheat/CardDetail.qml b/Fk/Cheat/CardDetail.qml
index 7f5c33d4..cd069808 100644
--- a/Fk/Cheat/CardDetail.qml
+++ b/Fk/Cheat/CardDetail.qml
@@ -3,6 +3,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
+import Fk.RoomElement
Flickable {
id: root
@@ -14,35 +15,47 @@ Flickable {
contentHeight: details.height
ScrollBar.vertical: ScrollBar {}
- ColumnLayout {
+ RowLayout {
id: details
width: parent.width - 40
x: 20
+ spacing: 20
- // TODO: player details
- Text {
- id: screenName
- Layout.fillWidth: true
- font.pixelSize: 18
+ CardItem {
+ id: cardPic
+ Layout.alignment: Qt.AlignTop
+ Layout.topMargin: 10
+ cid: 0
}
- TextEdit {
- id: skillDesc
+ ColumnLayout {
+ Text {
+ id: screenName
+ Layout.fillWidth: true
+ font.pixelSize: 18
+ color: "#E4D5A0"
+ }
- Layout.fillWidth: true
- font.pixelSize: 18
+ TextEdit {
+ id: skillDesc
- readOnly: true
- selectByKeyboard: true
- selectByMouse: false
- wrapMode: TextEdit.WordWrap
- textFormat: TextEdit.RichText
+ Layout.fillWidth: true
+ font.pixelSize: 18
+ color: "#E4D5A0"
+
+ readOnly: true
+ selectByKeyboard: true
+ selectByMouse: false
+ wrapMode: TextEdit.WordWrap
+ textFormat: TextEdit.RichText
+ }
}
}
onExtra_dataChanged: {
const card = extra_data.card;
if (!card) return;
+ cardPic.setData(card.toData());
const name = card.virt_name ? card.virt_name : card.name;
screenName.text = Backend.translate(name);
skillDesc.text = Backend.translate(":" + name);
diff --git a/Fk/Cheat/FreeAssign.qml b/Fk/Cheat/FreeAssign.qml
index 12fd18e3..6a610f42 100644
--- a/Fk/Cheat/FreeAssign.qml
+++ b/Fk/Cheat/FreeAssign.qml
@@ -24,6 +24,7 @@ Item {
text: Backend.translate("Back")
onClicked: stack.pop()
}
+
Label {
text: Backend.translate("Enable free assign")
elide: Label.ElideRight
@@ -31,8 +32,29 @@ Item {
verticalAlignment: Qt.AlignVCenter
Layout.fillWidth: true
}
+
+ TextField {
+ id: word
+ placeholderText: "Search..."
+ clip: true
+ verticalAlignment: Qt.AlignVCenter
+ background: Rectangle {
+ implicitHeight: 16
+ implicitWidth: 120
+ color: "transparent"
+ }
+ }
+
ToolButton {
- opacity: 0
+ text: Backend.translate("Search")
+ enabled: word.text !== ""
+ onClicked: {
+ if (stack.depth > 1) stack.pop();
+ generalModel = JSON.parse(Backend.callLuaFunction("SearchAllGenerals",
+ [word.text]));
+ stack.push(generalList);
+ word.text = "";
+ }
}
}
}
@@ -58,15 +80,16 @@ Item {
ScrollBar.vertical: ScrollBar {}
model: packages
clip: true
- cellWidth: width / 3
+ cellWidth: width / 5
cellHeight: 40
delegate: ItemDelegate {
- width: listView.width / 3
+ width: listView.width / 5
height: 40
Text {
text: Backend.translate(name)
+ color: "#E4D5A0"
anchors.centerIn: parent
}
diff --git a/Fk/Cheat/PlayerDetail.qml b/Fk/Cheat/PlayerDetail.qml
index b76a426c..f600fe3c 100644
--- a/Fk/Cheat/PlayerDetail.qml
+++ b/Fk/Cheat/PlayerDetail.qml
@@ -3,6 +3,8 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
+import Fk.Pages
+import Fk.RoomElement
Flickable {
id: root
@@ -24,29 +26,18 @@ Flickable {
Text {
id: screenName
font.pixelSize: 18
+ color: "#E4D5A0"
}
Text {
id: playerGameData
Layout.fillWidth: true
font.pixelSize: 18
- }
-
- TextEdit {
- id: skillDesc
-
- Layout.fillWidth: true
- font.pixelSize: 18
-
- readOnly: true
- selectByKeyboard: true
- selectByMouse: false
- wrapMode: TextEdit.WordWrap
- textFormat: TextEdit.RichText
+ color: "#E4D5A0"
}
RowLayout {
- Button {
+ MetroButton {
text: Backend.translate("Give Flower")
onClicked: {
enabled = false;
@@ -55,7 +46,7 @@ Flickable {
}
}
- Button {
+ MetroButton {
text: Backend.translate("Give Egg")
onClicked: {
enabled = false;
@@ -68,7 +59,7 @@ Flickable {
}
}
- Button {
+ MetroButton {
text: Backend.translate("Give Wine")
enabled: Math.random() < 0.3
onClicked: {
@@ -78,7 +69,7 @@ Flickable {
}
}
- Button {
+ MetroButton {
text: Backend.translate("Give Shoe")
enabled: Math.random() < 0.3
onClicked: {
@@ -87,10 +78,8 @@ Flickable {
root.finish();
}
}
- }
- RowLayout {
- Button {
+ MetroButton {
text: config.blockedUsers.indexOf(screenName.text) === -1 ? Backend.translate("Block Chatter") : Backend.translate("Unblock Chatter")
enabled: pid !== Self.id && pid > 0
onClicked: {
@@ -103,7 +92,7 @@ Flickable {
config.blockedUsersChanged();
}
}
- Button {
+ MetroButton {
text: Backend.translate("Kick From Room")
visible: !roomScene.isStarted && roomScene.isOwner
enabled: pid !== Self.id
@@ -113,6 +102,41 @@ Flickable {
}
}
}
+
+ RowLayout {
+ spacing: 20
+ ColumnLayout {
+ Layout.alignment: Qt.AlignTop
+ Layout.topMargin: 16
+
+ GeneralCardItem {
+ id: mainChara
+ name: "caocao"
+ visible: name !== ""
+ }
+ GeneralCardItem {
+ id: deputyChara
+ name: "caocao"
+ visible: name !== ""
+ }
+ }
+
+ TextEdit {
+ id: skillDesc
+
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignTop
+ Layout.topMargin: 10
+ font.pixelSize: 18
+ color: "#E4D5A0"
+
+ readOnly: true
+ selectByKeyboard: true
+ selectByMouse: false
+ wrapMode: TextEdit.WordWrap
+ textFormat: TextEdit.RichText
+ }
+ }
}
function givePresent(p) {
@@ -136,6 +160,8 @@ Flickable {
root.pid = id;
screenName.text = extra_data.photo.screenName;
+ mainChara.name = extra_data.photo.general;
+ deputyChara.name = extra_data.photo.deputyGeneral;
if (!config.observing) {
const gamedata = JSON.parse(Backend.callLuaFunction("GetPlayerGameData", [id]));
diff --git a/Fk/Cheat/SameConvert.qml b/Fk/Cheat/SameConvert.qml
index ae0fd80a..b4be5da6 100644
--- a/Fk/Cheat/SameConvert.qml
+++ b/Fk/Cheat/SameConvert.qml
@@ -28,7 +28,7 @@ Item {
ColumnLayout {
Text { text: Backend.translate(gname) }
GridLayout {
- columns: 3
+ columns: 6
Repeater {
model: JSON.parse(Backend.callLuaFunction("GetSameGenerals", [gname]))
diff --git a/Fk/LobbyElement/BanGeneralSetting.qml b/Fk/LobbyElement/BanGeneralSetting.qml
index 31e5cd21..7eac2671 100644
--- a/Fk/LobbyElement/BanGeneralSetting.qml
+++ b/Fk/LobbyElement/BanGeneralSetting.qml
@@ -46,16 +46,7 @@ Item {
config.disabledGenerals = [];
}
}
- }
- Text {
- Layout.fillWidth: true
- Layout.margins: 8
- wrapMode: Text.WrapAnywhere
- text: Backend.translate("Help_Ban_List")
- }
-
- RowLayout {
Button {
text: Backend.translate("Export")
onClicked: {
@@ -91,12 +82,19 @@ Item {
}
}
+ Text {
+ Layout.fillWidth: true
+ Layout.margins: 8
+ wrapMode: Text.WrapAnywhere
+ text: Backend.translate("Help_Ban_List")
+ }
+
GridView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
- cellWidth: width / 2
+ cellWidth: width / 4
cellHeight: 24
model: config.disabledGenerals
delegate: Text {
diff --git a/Fk/LobbyElement/CreateRoom.qml b/Fk/LobbyElement/CreateRoom.qml
index 071edff5..2449f536 100644
--- a/Fk/LobbyElement/CreateRoom.qml
+++ b/Fk/LobbyElement/CreateRoom.qml
@@ -16,6 +16,7 @@ Item {
transformOrigin: Item.BottomLeft
rotation: 90
width: root.height
+ background: Rectangle { color: "#EEEEEEEE" }
TabButton {
text: Backend.translate("General Settings")
}
diff --git a/Fk/LobbyElement/EditProfile.qml b/Fk/LobbyElement/EditProfile.qml
index 2fb36e18..c64651e2 100644
--- a/Fk/LobbyElement/EditProfile.qml
+++ b/Fk/LobbyElement/EditProfile.qml
@@ -15,6 +15,7 @@ Item {
transformOrigin: Item.BottomLeft
rotation: 90
width: root.height
+ background: Rectangle { color: "#EEEEEEEE" }
TabButton {
text: Backend.translate("Userinfo Settings")
}
diff --git a/Fk/LobbyElement/RoomGeneralSettings.qml b/Fk/LobbyElement/RoomGeneralSettings.qml
index 839a3376..3e418f3b 100644
--- a/Fk/LobbyElement/RoomGeneralSettings.qml
+++ b/Fk/LobbyElement/RoomGeneralSettings.qml
@@ -28,24 +28,6 @@ Flickable {
}
}
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Player num")
- }
- SpinBox {
- id: playerNum
- from: 2
- to: 12
- value: config.preferedPlayerNum
-
- onValueChanged: {
- config.preferedPlayerNum = value;
- }
- }
- }
-
RowLayout {
anchors.rightMargin: 8
spacing: 16
@@ -69,12 +51,33 @@ Flickable {
}
}
- RowLayout {
+ GridLayout {
anchors.rightMargin: 8
- spacing: 16
+ rowSpacing: 20
+ columnSpacing: 20
+ columns: 4
+ Text {
+ text: Backend.translate("Player num")
+ }
Text {
text: Backend.translate("Select generals num")
}
+ Text {
+ text: Backend.translate("Operation timeout")
+ }
+ Text {
+ text: Backend.translate("Luck Card Times")
+ }
+ SpinBox {
+ id: playerNum
+ from: 2
+ to: 12
+ value: config.preferedPlayerNum
+
+ onValueChanged: {
+ config.preferedPlayerNum = value;
+ }
+ }
SpinBox {
id: generalNum
from: 3
@@ -85,6 +88,25 @@ Flickable {
config.preferredGeneralNum = value;
}
}
+ SpinBox {
+ from: 10
+ to: 60
+ editable: true
+ value: config.preferredTimeout
+
+ onValueChanged: {
+ config.preferredTimeout = value;
+ }
+ }
+ SpinBox {
+ from: 0
+ to: 8
+ value: config.preferredLuckTime
+
+ onValueChanged: {
+ config.preferredLuckTime = value;
+ }
+ }
}
Text {
@@ -100,41 +122,6 @@ Flickable {
color: "red"
}
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Operation timeout")
- }
- SpinBox {
- from: 10
- to: 60
- editable: true
- value: config.preferredTimeout
-
- onValueChanged: {
- config.preferredTimeout = value;
- }
- }
- }
-
- RowLayout {
- anchors.rightMargin: 8
- spacing: 16
- Text {
- text: Backend.translate("Luck Card Times")
- }
- SpinBox {
- from: 0
- to: 8
- value: config.preferredLuckTime
-
- onValueChanged: {
- config.preferredLuckTime = value;
- }
- }
- }
-
RowLayout {
anchors.rightMargin: 8
spacing: 16
@@ -150,16 +137,20 @@ Flickable {
}
}
- Switch {
- id: freeAssignCheck
- checked: Debugging ? true : false
- text: Backend.translate("Enable free assign")
- }
+ RowLayout {
+ anchors.rightMargin: 8
+ spacing: 16
+ Switch {
+ id: freeAssignCheck
+ checked: Debugging ? true : false
+ text: Backend.translate("Enable free assign")
+ }
- Switch {
- id: deputyCheck
- checked: Debugging ? true : false
- text: Backend.translate("Enable deputy general")
+ Switch {
+ id: deputyCheck
+ checked: Debugging ? true : false
+ text: Backend.translate("Enable deputy general")
+ }
}
RowLayout {
diff --git a/Fk/LobbyElement/RoomPackageSettings.qml b/Fk/LobbyElement/RoomPackageSettings.qml
index ec2ca43f..7b7edb13 100644
--- a/Fk/LobbyElement/RoomPackageSettings.qml
+++ b/Fk/LobbyElement/RoomPackageSettings.qml
@@ -52,7 +52,7 @@ Flickable {
}
GridLayout {
- columns: 2
+ columns: 4
Repeater {
id: gpacks
@@ -100,7 +100,7 @@ Flickable {
}
GridLayout {
- columns: 2
+ columns: 4
Repeater {
id: cpacks
diff --git a/Fk/Pages/Lobby.qml b/Fk/Pages/Lobby.qml
index f313152f..3140d411 100644
--- a/Fk/Pages/Lobby.qml
+++ b/Fk/Pages/Lobby.qml
@@ -224,19 +224,25 @@ Item {
}
}
- Drawer {
+ Popup {
id: lobby_drawer
- width: parent.width * 0.4 / mainWindow.scale
- height: parent.height / mainWindow.scale
- dim: false
- clip: true
- dragMargin: 0
- scale: mainWindow.scale
- transformOrigin: Item.TopLeft
+ width: realMainWin.width * 0.8
+ height: realMainWin.height * 0.8
+ anchors.centerIn: parent
+ background: Rectangle {
+ color: "#EEEEEEEE"
+ radius: 5
+ border.color: "#A6967A"
+ border.width: 1
+ }
Loader {
id: lobby_dialog
- anchors.fill: parent
+ anchors.centerIn: parent
+ width: parent.width / mainWindow.scale
+ height: parent.height / mainWindow.scale
+ scale: mainWindow.scale
+ clip: true
onSourceChanged: {
if (item === null)
return;
diff --git a/Fk/Pages/MetroButton.qml b/Fk/Pages/MetroButton.qml
index aab1b980..b602ce26 100644
--- a/Fk/Pages/MetroButton.qml
+++ b/Fk/Pages/MetroButton.qml
@@ -41,6 +41,9 @@ Item {
TapHandler {
id: mouse
+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.NoButton
+ gesturePolicy: TapHandler.WithinBounds
+
onTapped: if (parent.enabled) parent.clicked()
}
diff --git a/Fk/Pages/Room.qml b/Fk/Pages/Room.qml
index a5178680..292e252d 100644
--- a/Fk/Pages/Room.qml
+++ b/Fk/Pages/Room.qml
@@ -8,6 +8,7 @@ import QtMultimedia
import Fk
import Fk.Common
import Fk.RoomElement
+import Fk.PhotoElement as PhotoElement
import "RoomLogic.js" as Logic
Item {
@@ -37,6 +38,7 @@ Item {
property alias drawPile: drawPile
property alias skillInteraction: skillInteraction
property alias miscStatus: miscStatus
+ property alias banner: banner
property var selected_targets: []
property string responding_card
@@ -55,7 +57,6 @@ Item {
fillMode: Image.PreserveAspectCrop
}
- /*
MediaPlayer {
id: bgm
source: config.bgmFile
@@ -69,15 +70,14 @@ Item {
volume: config.bgmVolume / 100
}
}
- */
onIsStartedChanged: {
if (isStarted) {
- // bgm.play();
+ bgm.play();
canKickOwner = false;
kickOwnerTimer.stop();
} else {
- // bgm.stop();
+ bgm.stop();
}
}
@@ -533,14 +533,6 @@ Item {
}
}
- GlowText {
- text: Backend.translate("Observing ...")
- visible: config.observing && !config.replaying
- color: "#4B83CD"
- font.family: fontLi2.name
- font.pixelSize: 48
- }
-
Rectangle {
id: replayControls
visible: config.replaying
@@ -855,7 +847,7 @@ Item {
Drawer {
id: roomDrawer
- width: parent.width * 0.3 / mainWindow.scale
+ width: parent.width * 0.36 / mainWindow.scale
height: parent.height / mainWindow.scale
dim: false
clip: true
@@ -901,20 +893,25 @@ Item {
}
}
- Drawer {
+ Popup {
id: cheatDrawer
- edge: Qt.RightEdge
- width: parent.width * 0.4 / mainWindow.scale
- height: parent.height / mainWindow.scale
- dim: false
- clip: true
- dragMargin: 0
- scale: mainWindow.scale
- transformOrigin: Item.TopRight
+ width: realMainWin.width * 0.60
+ height: realMainWin.height * 0.8
+ anchors.centerIn: parent
+ background: Rectangle {
+ color: "#CC2E2C27"
+ radius: 5
+ border.color: "#A6967A"
+ border.width: 1
+ }
Loader {
id: cheatLoader
- anchors.fill: parent
+ anchors.centerIn: parent
+ width: parent.width / mainWindow.scale
+ height: parent.height / mainWindow.scale
+ scale: mainWindow.scale
+ clip: true
onSourceChanged: {
if (item === null)
return;
@@ -931,6 +928,20 @@ Item {
anchors.fill: parent
}
+ Rectangle {
+ anchors.fill: dashboard
+ visible: config.observing && !config.replaying
+ color: "transparent"
+ GlowText {
+ anchors.centerIn: parent
+ text: Backend.translate("Observing ...")
+ color: "#4B83CD"
+ font.family: fontLi2.name
+ font.pixelSize: 48
+ }
+ }
+
+ /* 这东西似乎一直不好使啊
Rectangle {
id: easyChat
width: parent.width
@@ -967,6 +978,16 @@ Item {
}
}
+ Shortcut {
+ sequence: "T"
+ onActivated: {
+ easyChat.visible = true;
+ easyChatEdit.enabled = true;
+ easyChatEdit.forceActiveFocus();
+ }
+ }
+ */
+
MiscStatus {
id: miscStatus
anchors.right: menuButton.left
@@ -975,20 +996,20 @@ Item {
anchors.topMargin: 8
}
+ PhotoElement.MarkArea {
+ id: banner
+ x: 12; y: 12
+ width: (roomScene.width - 175 * 0.75 * 7) / 4 + 175 - 16
+ transformOrigin: Item.TopLeft
+ scale: 0.75
+ bgColor: "#BB838AEA"
+ }
+
Danmaku {
id: danmaku
width: parent.width
}
- Shortcut {
- sequence: "T"
- onActivated: {
- easyChat.visible = true;
- easyChatEdit.enabled = true;
- easyChatEdit.forceActiveFocus();
- }
- }
-
Shortcut {
sequence: "D"
property bool show_distance: false
diff --git a/Fk/Pages/RoomLogic.js b/Fk/Pages/RoomLogic.js
index 8936a9dd..c1677e75 100644
--- a/Fk/Pages/RoomLogic.js
+++ b/Fk/Pages/RoomLogic.js
@@ -1012,7 +1012,7 @@ callbacks["AskForChoice"] = (jsonData) => {
});
}
-callbacks["AskForCheck"] = (jsonData) => {
+callbacks["AskForChoices"] = (jsonData) => {
// jsonData: [ string[] choices, string skill ]
// TODO: multiple choices, e.g. benxi_ol
const data = JSON.parse(jsonData);
@@ -1025,7 +1025,7 @@ callbacks["AskForCheck"] = (jsonData) => {
const prompt = data[5];
const detailed = data[6];
if (prompt === "") {
- roomScene.promptText = Backend.translate("#AskForCheck")
+ roomScene.promptText = Backend.translate("#AskForChoices")
.arg(Backend.translate(skill_name));
} else {
roomScene.setPrompt(processPrompt(prompt), true);
@@ -1335,7 +1335,7 @@ callbacks["SetPlayerMark"] = (jsonData) => {
const data = JSON.parse(jsonData);
const player = getPhoto(data[0]);
const mark = data[1];
- const value = data[2] instanceof Array ? data[2] : data[2].toString();
+ const value = data[2] instanceof Object ? data[2] : data[2].toString();
let area = mark.startsWith("@!") ? player.picMarkArea : player.markArea;
if (data[2] === 0) {
area.removeMark(mark);
@@ -1344,6 +1344,18 @@ callbacks["SetPlayerMark"] = (jsonData) => {
}
}
+callbacks["SetBanner"] = (jsonData) => {
+ const data = JSON.parse(jsonData);
+ const mark = data[0];
+ const value = data[1] instanceof Object ? data[1] : data[1].toString();
+ let area = roomScene.banner;
+ if (data[1] === 0) {
+ area.removeMark(mark);
+ } else {
+ area.setMark(mark, mark.startsWith("@@") ? "" : value);
+ }
+}
+
callbacks["Animate"] = (jsonData) => {
// jsonData: [Object object]
const data = JSON.parse(jsonData);
@@ -1581,7 +1593,7 @@ callbacks["ChangeSelf"] = (j) => {
callbacks["AskForLuckCard"] = (j) => {
// jsonData: int time
- if (config.replaying) return;
+ if (config.observing || config.replaying) return;
const time = parseInt(j);
roomScene.setPrompt(Backend.translate("#AskForLuckCard").arg(time), true);
roomScene.state = "replying";
diff --git a/Fk/PhotoElement/MarkArea.qml b/Fk/PhotoElement/MarkArea.qml
index adda007c..f4e5ed0c 100644
--- a/Fk/PhotoElement/MarkArea.qml
+++ b/Fk/PhotoElement/MarkArea.qml
@@ -6,6 +6,7 @@ import QtQuick.Layouts
Item {
id: root
width: 138
+ property var bgColor: "#3C3229"
ListModel {
id: markList
@@ -15,7 +16,7 @@ Item {
anchors.bottom: parent.bottom
width: parent.width
height: parent.height
- color: "#3C3229"
+ color: bgColor
opacity: 0.8
radius: 4
border.color: "white"
@@ -68,7 +69,21 @@ Item {
} else {
params.cardNames = data;
}
+ } else if (mark_name.startsWith('@[')) {
+ // @[xxx]yyy 怀疑是不是qml标记
+ const close_br = mark_name.indexOf(']');
+ if (close_br === -1) return;
+
+ const mark_type = mark_name.slice(2, close_br);
+ const _data = (mark_extra);
+ let data = JSON.parse(Backend.callLuaFunction("GetQmlMark", [mark_type, mark_name, JSON.stringify(_data)]));
+ if (data && data.qml_path) {
+ params.data = _data;
+ roomScene.startCheat("../../" + data.qml_path, params);
+ }
+ return;
} else {
+ if (!root.parent.playerid) return;
let data = JSON.parse(Backend.callLuaFunction("GetPile", [root.parent.playerid, mark_name]));
data = data.filter((e) => e !== -1);
if (data.length === 0)
@@ -103,6 +118,15 @@ Item {
if (mark.startsWith('@$') || mark.startsWith('@&')) {
special_value += data.length;
data = data.join(',');
+ } else if (mark.startsWith('@[')) {
+ const close_br = mark.indexOf(']');
+ if (close_br !== -1) {
+ const mark_type = mark.slice(2, close_br);
+ const _data = JSON.parse(Backend.callLuaFunction("GetQmlMark", [mark_type, mark, JSON.stringify(data)]));
+ if (_data && _data.text) {
+ special_value = _data.text;
+ }
+ }
} else {
data = data instanceof Array ? data.map((markText) => Backend.translate(markText)).join(' ') : Backend.translate(data);
}
diff --git a/Fk/RoomElement/BigGlowText.qml b/Fk/RoomElement/BigGlowText.qml
new file mode 100644
index 00000000..fb375d1c
--- /dev/null
+++ b/Fk/RoomElement/BigGlowText.qml
@@ -0,0 +1,39 @@
+import QtQuick
+import Qt5Compat.GraphicalEffects
+
+Item {
+ property alias text: pileName.text
+ GlowText {
+ id: pileName
+ horizontalAlignment: Text.AlignHCenter
+ width: parent.width
+ font.family: fontLibian.name
+ color: "#E4D5A0"
+ font.pixelSize: 30
+ font.weight: Font.Medium
+ glow.color: "black"
+ glow.spread: 0.3
+ glow.radius: 5
+ }
+
+ LinearGradient {
+ anchors.fill: pileName
+ source: pileName
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#FEF7C2"
+ }
+
+ GradientStop {
+ position: 0.5
+ color: "#D2AD4A"
+ }
+
+ GradientStop {
+ position: 1
+ color: "#BE9878"
+ }
+ }
+ }
+}
diff --git a/Fk/RoomElement/ChooseHandcard.qml b/Fk/RoomElement/ChooseHandcard.qml
index 94747891..45281e18 100644
--- a/Fk/RoomElement/ChooseHandcard.qml
+++ b/Fk/RoomElement/ChooseHandcard.qml
@@ -5,7 +5,7 @@ import QtQuick.Layouts
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
-Item {
+ColumnLayout {
id: root
anchors.fill: parent
property var extra_data: ({}) // unused
@@ -14,51 +14,40 @@ Item {
Text {
text: Backend.translate("Handcard selector")
- width: parent.width
- anchors.topMargin: 6
+ Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
- font.pixelSize: 16
+ font.pixelSize: 18
+ color: "#E4D5A0"
}
- Flickable {
- id: flickableContainer
- ScrollBar.vertical: ScrollBar {}
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- anchors.topMargin: 40
- flickableDirection: Flickable.VerticalFlick
- width: parent.width - 20
- height: parent.height - 40
- contentWidth: cardsList.width
- contentHeight: cardsList.height
+ GridView {
+ id: cardsList
+ cellWidth: 93 * 0.9 + 4
+ cellHeight: 130 * 0.9 + 4
+ Layout.preferredWidth: root.width - root.width % 88
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignHCenter
clip: true
- GridLayout {
- id: cardsList
- columns: Math.floor(flickableContainer.width / 90)
+ model: cards
- Repeater {
- model: cards
-
- CardItem {
- width: 93 * 0.9
- height: 130 * 0.9
- chosenInBox: modelData.chosen
- onClicked: {
- const clist = roomScene.dashboard.handcardArea.cards;
- for (let cd of clist) {
- if (cd.cid == cid) {
- cd.selected = !cd.selected;
- cd.clicked();
- finish();
- }
- }
- }
- Component.onCompleted: {
- setData(JSON.parse(Backend.callLuaFunction("GetCardData", [modelData.cid])));
+ delegate: CardItem {
+ width: 93 * 0.9
+ height: 130 * 0.9
+ chosenInBox: modelData.chosen
+ onClicked: {
+ const clist = roomScene.dashboard.handcardArea.cards;
+ for (let cd of clist) {
+ if (cd.cid == cid) {
+ cd.selected = !cd.selected;
+ cd.clicked();
+ finish();
}
}
}
+ Component.onCompleted: {
+ setData(JSON.parse(Backend.callLuaFunction("GetCardData", [modelData.cid])));
+ }
}
}
diff --git a/Fk/RoomElement/GeneralCardItem.qml b/Fk/RoomElement/GeneralCardItem.qml
index 123a05fd..290882c0 100644
--- a/Fk/RoomElement/GeneralCardItem.qml
+++ b/Fk/RoomElement/GeneralCardItem.qml
@@ -153,7 +153,7 @@ CardItem {
height: 80
x: 2
y: lineCount > 6 ? 30 : 34
- text: Backend.translate(name)
+ text: name !== "" ? Backend.translate(name) : "nil"
visible: Backend.translate(name).length <= 6 && detailed
color: "white"
font.family: fontLibian.name
diff --git a/Fk/RoomElement/ViewGeneralPile.qml b/Fk/RoomElement/ViewGeneralPile.qml
index aead17bd..46645f41 100644
--- a/Fk/RoomElement/ViewGeneralPile.qml
+++ b/Fk/RoomElement/ViewGeneralPile.qml
@@ -2,87 +2,34 @@
import QtQuick
import QtQuick.Layouts
-import QtQuick.Controls
-import Qt5Compat.GraphicalEffects
-Item {
+ColumnLayout {
id: root
anchors.fill: parent
property var extra_data: ({})
signal finish()
- Rectangle {
- anchors.fill: parent
- color: "black"
+ BigGlowText {
+ Layout.fillWidth: true
+ Layout.preferredHeight: childrenRect.height + 4
- GlowText {
- id: pileName
- text: Backend.translate(extra_data.name)
- width: parent.width
- anchors.topMargin: 10
- horizontalAlignment: Text.AlignHCenter
- font.family: fontLibian.name
- color: "#E4D5A0"
- font.pixelSize: 30
- font.weight: Font.Medium
- glow.color: "black"
- glow.spread: 0.3
- glow.radius: 5
- }
+ text: Backend.translate(extra_data.name)
+ }
- LinearGradient {
- anchors.fill: pileName
- source: pileName
- gradient: Gradient {
- GradientStop {
- position: 0
- color: "#FEF7C2"
- }
+ GridView {
+ cellWidth: 93 + 4
+ cellHeight: 130 + 4
+ Layout.preferredWidth: root.width - root.width % 97
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignHCenter
+ clip: true
- GradientStop {
- position: 0.5
- color: "#D2AD4A"
- }
+ model: extra_data.ids || extra_data.cardNames
- GradientStop {
- position: 1
- color: "#BE9878"
- }
- }
- }
-
- Flickable {
- id: flickableContainer
- ScrollBar.vertical: ScrollBar {}
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- anchors.topMargin: 40
- flickableDirection: Flickable.VerticalFlick
- width: parent.width - 20
- height: parent.height - 40
- contentWidth: cardsList.width
- contentHeight: cardsList.height
- clip: true
-
- ColumnLayout {
- id: cardsList
-
- GridLayout {
- columns: Math.floor(flickableContainer.width / 100)
-
- Repeater {
- model: extra_data.ids || extra_data.cardNames
-
- GeneralCardItem {
- id: cardItem
- // width: (flickableContainer.width - 15) / 4
- // height: cardItem.width * 1.4
- autoBack: false
- name: modelData
- }
- }
- }
- }
+ delegate: GeneralCardItem {
+ id: cardItem
+ autoBack: false
+ name: modelData
}
}
}
diff --git a/Fk/RoomElement/ViewPile.qml b/Fk/RoomElement/ViewPile.qml
index 860f4e6a..4b0bb269 100644
--- a/Fk/RoomElement/ViewPile.qml
+++ b/Fk/RoomElement/ViewPile.qml
@@ -2,98 +2,45 @@
import QtQuick
import QtQuick.Layouts
-import QtQuick.Controls
-import Qt5Compat.GraphicalEffects
-Item {
+ColumnLayout {
id: root
anchors.fill: parent
property var extra_data: ({})
signal finish()
- Rectangle {
- anchors.fill: parent
- color: "black"
+ BigGlowText {
+ Layout.fillWidth: true
+ Layout.preferredHeight: childrenRect.height + 4
- GlowText {
- id: pileName
- text: Backend.translate(extra_data.name)
- width: parent.width
- anchors.topMargin: 10
- horizontalAlignment: Text.AlignHCenter
- font.family: fontLibian.name
- color: "#E4D5A0"
- font.pixelSize: 30
- font.weight: Font.Medium
- glow.color: "black"
- glow.spread: 0.3
- glow.radius: 5
- }
+ text: Backend.translate(extra_data.name)
+ }
- LinearGradient {
- anchors.fill: pileName
- source: pileName
- gradient: Gradient {
- GradientStop {
- position: 0
- color: "#FEF7C2"
- }
-
- GradientStop {
- position: 0.5
- color: "#D2AD4A"
- }
-
- GradientStop {
- position: 1
- color: "#BE9878"
- }
- }
- }
-
- Flickable {
- id: flickableContainer
- ScrollBar.vertical: ScrollBar {}
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- anchors.topMargin: 40
- flickableDirection: Flickable.VerticalFlick
- width: parent.width - 20
- height: parent.height - 40
- contentWidth: cardsList.width
- contentHeight: cardsList.height
- clip: true
-
- ColumnLayout {
- id: cardsList
-
- GridLayout {
- columns: 4
-
- Repeater {
- model: extra_data.ids || extra_data.cardNames
-
- CardItem {
- id: cardItem
- width: (flickableContainer.width - 15) / 4
- height: cardItem.width * 1.4
- autoBack: false
- Component.onCompleted: {
- let data = {}
- if (extra_data.ids) {
- data = JSON.parse(Backend.callLuaFunction("GetCardData", [modelData]));
- } else {
- data.cid = 0;
- data.name = modelData;
- data.suit = '';
- data.number = 0;
- data.color = '';
- }
- setData(data);
- }
- }
- }
+ GridView {
+ cellWidth: 93 + 4
+ cellHeight: 130 + 4
+ Layout.preferredWidth: root.width - root.width % 97
+ Layout.fillHeight: true
+ Layout.alignment: Qt.AlignHCenter
+ clip: true
+
+ model: extra_data.ids || extra_data.cardNames
+
+ delegate: CardItem {
+ id: cardItem
+ autoBack: false
+ Component.onCompleted: {
+ let data = {}
+ if (extra_data.ids) {
+ data = JSON.parse(Backend.callLuaFunction("GetCardData", [modelData]));
+ } else {
+ data.cid = 0;
+ data.name = modelData;
+ data.suit = '';
+ data.number = 0;
+ data.color = '';
}
+ setData(data);
}
}
}
diff --git a/Fk/RoomElement/qmldir b/Fk/RoomElement/qmldir
index ac94eb75..13c69b78 100644
--- a/Fk/RoomElement/qmldir
+++ b/Fk/RoomElement/qmldir
@@ -8,6 +8,7 @@ Dashboard 1.0 Dashboard.qml
GameOverBox 1.0 GameOverBox.qml
GeneralCardItem 1.0 GeneralCardItem.qml
GlowText 1.0 GlowText.qml
+BigGlowText 1.0 BigGlowText.qml
GraphicsBox 1.0 GraphicsBox.qml
GuanxingBox 1.0 GuanxingBox.qml
HandcardArea 1.0 HandcardArea.qml
diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts
index 72bba804..e5dbf625 100644
--- a/lang/zh_CN.ts
+++ b/lang/zh_CN.ts
@@ -334,6 +334,10 @@
房间已满!
+
+
+ 房主拒绝你加入。
+
服务器已满!
diff --git a/lua/client/client.lua b/lua/client/client.lua
index 12bfa646..3b79f51a 100644
--- a/lua/client/client.lua
+++ b/lua/client/client.lua
@@ -8,6 +8,7 @@
---@field public current ClientPlayer @ 当前回合玩家
---@field public discard_pile integer[] @ 弃牌堆
---@field public status_skills Skill[] @ 状态技总和
+---@field public banners table @ 左上角显示的东西
---@field public observing boolean
Client = class('Client')
@@ -57,6 +58,8 @@ function Client:initialize()
self.status_skills[class] = {table.unpack(skills)}
end
+ self.banners = {}
+
self.skill_costs = {}
self.card_marks = {}
self.filtered_cards = {}
@@ -234,6 +237,15 @@ function Client:setCardNote(ids, msg)
end
end
+function Client:setBanner(name, value)
+ if value == 0 then value = nil end
+ self.banners[name] = value
+end
+
+function Client:getBanner(name)
+ return self.banners[name]
+end
+
fk.client_callback["SetCardFootnote"] = function(jsonData)
local data = json.decode(jsonData)
ClientInstance:setCardNote(data[1], data[2]);
@@ -769,6 +781,17 @@ fk.client_callback["SetPlayerMark"] = function(jsonData)
end
end
+fk.client_callback["SetBanner"] = function(jsonData)
+ -- jsonData: [ int id, string mark, int value ]
+ local data = json.decode(jsonData)
+ local mark, value = data[1], data[2]
+ ClientInstance:setBanner(mark, value)
+
+ if string.sub(mark, 1, 1) == "@" then
+ ClientInstance:notifyUI("SetBanner", jsonData)
+ end
+end
+
fk.client_callback["SetCardMark"] = function(jsonData)
-- jsonData: [ int id, string mark, int value ]
local data = json.decode(jsonData)
diff --git a/lua/client/client_util.lua b/lua/client/client_util.lua
index adc00859..83aaa849 100644
--- a/lua/client/client_util.lua
+++ b/lua/client/client_util.lua
@@ -734,4 +734,14 @@ function PoxiFeasible(poxi_type, selected, data, extra_data)
return json.encode(poxi.feasible(selected, data, extra_data))
end
+function GetQmlMark(mtype, name, value)
+ local spec = Fk.qml_marks[mtype]
+ if not spec then return "{}" end
+ value = json.decode(value)
+ return json.encode {
+ qml_path = spec.qml_path,
+ text = spec.how_to_show(name, value)
+ }
+end
+
dofile "lua/client/i18n/init.lua"
diff --git a/lua/client/i18n/en_US.lua b/lua/client/i18n/en_US.lua
index cc3ccbed..5f34c0f1 100644
--- a/lua/client/i18n/en_US.lua
+++ b/lua/client/i18n/en_US.lua
@@ -159,7 +159,7 @@ Fk:loadTranslationTable({
["#AskForLuckCard"] = "Do you want to use luck card (%1 times left)?",
["AskForLuckCard"] = "Luck card",
["#AskForChoice"] = "%1: Please choose",
- ["#AskForCheck"] = "%1: Please choose",
+ ["#AskForChoices"] = "%1: Please choose",
["#choose-trigger"] = "Please choose the skill to use",
["trigger"] = "Trigger skill",
-- ["Please arrange cards"] = "请拖拽移动卡牌",
@@ -170,7 +170,7 @@ Fk:loadTranslationTable({
["AskForGuanxing"] = "Stargazing",
["AskForExchange"] = "Exchaging",
["AskForChoice"] = "Making choice",
- ["AskForCheck"] = "Making choice",
+ ["AskForChoices"] = "Making choice",
["AskForKingdom"] = "Choosing kingdom",
["AskForPindian"] = "Point fight",
["AskForMoveCardInBoard"] = "Moving cards",
diff --git a/lua/client/i18n/zh_CN.lua b/lua/client/i18n/zh_CN.lua
index 71bb9901..31aa502f 100644
--- a/lua/client/i18n/zh_CN.lua
+++ b/lua/client/i18n/zh_CN.lua
@@ -206,7 +206,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
["#AskForLuckCard"] = "你想使用手气卡吗?还可以使用 %1 次,剩余手气卡∞张",
["AskForLuckCard"] = "手气卡",
["#AskForChoice"] = "%1:请选择",
- ["#AskForCheck"] = "%1:请选择",
+ ["#AskForChoices"] = "%1:请选择",
["#choose-trigger"] = "请选择一项技能发动",
["trigger"] = "选择技能",
["Please arrange cards"] = "请拖拽移动卡牌",
@@ -217,7 +217,7 @@ FreeKill使用的是libgit2的C API,与此同时使用Git完成拓展包的下
["AskForGuanxing"] = "观星",
["AskForExchange"] = "换牌",
["AskForChoice"] = "选择",
- ["AskForCheck"] = "选择",
+ ["AskForChoices"] = "选择",
["AskForKingdom"] = "选择势力",
["AskForPindian"] = "拼点",
["AskForMoveCardInBoard"] = "移动卡牌",
diff --git a/lua/core/engine.lua b/lua/core/engine.lua
index cf4a568a..309c6b9b 100644
--- a/lua/core/engine.lua
+++ b/lua/core/engine.lua
@@ -27,6 +27,7 @@
---@field public printed_cards table @ 被某些房间现场打印的卡牌,id都是负数且从-2开始
---@field private _custom_events any[] @ 自定义事件列表
---@field public poxi_methods table @ “魄袭”框操作方法表
+---@field public qml_marks table @ 自定义Qml标记的表
local Engine = class("Engine")
--- Engine的构造函数。
@@ -59,6 +60,7 @@ function Engine:initialize()
self.kingdoms = {}
self._custom_events = {}
self.poxi_methods = {}
+ self.qml_marks = {}
self:loadPackages()
self:loadDisabled()
@@ -345,11 +347,22 @@ function Engine:addPoxiMethod(spec)
assert(type(spec.name) == "string")
assert(type(spec.card_filter) == "function")
assert(type(spec.feasible) == "function")
+ if self.poxi_methods[spec.name] then
+ fk.qCritical("Warning: duplicated poxi_method " .. spec.name)
+ end
self.poxi_methods[spec.name] = spec
spec.default_choice = spec.default_choice or function() return {} end
spec.post_select = spec.post_select or function(s) return s end
end
+function Engine:addQmlMark(spec)
+ assert(type(spec.name) == "string")
+ if self.qml_marks[spec.name] then
+ fk.qCritical("Warning: duplicated qml mark type " .. spec.name)
+ end
+ self.qml_marks[spec.name] = spec
+end
+
--- 从已经开启的拓展包中,随机选出若干名武将。
---
--- 对于同名武将不会重复选取。
diff --git a/lua/fk_ex.lua b/lua/fk_ex.lua
index 449ec452..d6f329c4 100644
--- a/lua/fk_ex.lua
+++ b/lua/fk_ex.lua
@@ -598,3 +598,8 @@ end
---@field post_select? fun(selected: int[], data: any, extra_data: any): int[]
---@field default_choice? fun(data: any, extra_data: any): int[]
---@field prompt? string | fun(data: any, extra_data: any): string
+
+---@class QmlMarkSpec
+---@field name string
+---@field qml_path string
+---@field how_to_show function(name: string, value?: any): string?
diff --git a/lua/server/request.lua b/lua/server/request.lua
index 8469fe95..7c87d1cf 100644
--- a/lua/server/request.lua
+++ b/lua/server/request.lua
@@ -41,6 +41,11 @@ local function tellRoomToObserver(self, player)
end
end
+ -- send banners
+ for k, v in pairs(self.banners) do
+ player:doNotify("SetBanner", json.encode{ k, v })
+ end
+
for _, p in ipairs(self.players) do
self:notifyProperty(player, p, "general")
self:notifyProperty(player, p, "deputyGeneral")
diff --git a/lua/server/room.lua b/lua/server/room.lua
index 3e442976..b329375c 100644
--- a/lua/server/room.lua
+++ b/lua/server/room.lua
@@ -15,6 +15,7 @@
---@field public game_finished boolean @ 游戏是否已经结束
---@field public timeout integer @ 出牌时长上限
---@field public tag table @ Tag清单,其实跟Player的标记是差不多的东西
+---@field public banners table @ 左上角显示点啥好呢?
---@field public general_pile string[] @ 武将牌堆,这是可用武将名的数组
---@field public draw_pile integer[] @ 摸牌堆,这是卡牌id的数组
---@field public discard_pile integer[] @ 弃牌堆,也是卡牌id的数组
@@ -77,6 +78,7 @@ function Room:initialize(_room)
self.game_finished = false
self.timeout = _room:getTimeout()
self.tag = {}
+ self.banners = {}
self.general_pile = {}
self.draw_pile = {}
self.discard_pile = {}
@@ -563,6 +565,16 @@ function Room:removeTag(tag_name)
self.tag[tag_name] = nil
end
+function Room:setBanner(name, value)
+ if value == 0 then value = nil end
+ self.banners[name] = value
+ self:doBroadcastNotify("SetBanner", json.encode{ name, value })
+end
+
+function Room:getBanner(name)
+ return self.banners[name]
+end
+
---@return boolean
local function execGameEvent(type, ...)
local event = GameEvent:new(type, ...)
@@ -1338,9 +1350,9 @@ end
---@param cancelable? boolean @ 能否点取消
---@param no_indicate? boolean @ 是否不显示指示线
---@return integer[], integer[]
-function Room:askForChooseBoth(player, minCardNum, maxCardNum, targets, minTargetNum, maxTargetNum, pattern, prompt, skillName, cancelable, no_indicate)
+function Room:askForChooseCardsAndPlayers(player, minCardNum, maxCardNum, targets, minTargetNum, maxTargetNum, pattern, prompt, skillName, cancelable, no_indicate)
if minCardNum < 1 or minTargetNum < 1 then
- return table.unpack({}, {})
+ return {}, {}
end
cancelable = (cancelable == nil) and true or cancelable
no_indicate = no_indicate or false
@@ -1366,7 +1378,7 @@ function Room:askForChooseBoth(player, minCardNum, maxCardNum, targets, minTarge
return ret.targets, ret.cards
else
if cancelable then
- return table.unpack({}, {})
+ return {}, {}
else
return table.random(targets, minTargetNum), table.random(pcards, minCardNum)
end
@@ -1675,12 +1687,12 @@ end
---@param detailed? boolean @ 选项详细描述
---@param all_choices? string[] @ 所有选项(不可选变灰)
---@return string[] @ 选择的选项
-function Room:askForCheck(player, choices, minNum, maxNum, skill_name, prompt, cancelable, detailed, all_choices)
+function Room:askForChoices(player, choices, minNum, maxNum, skill_name, prompt, cancelable, detailed, all_choices)
cancelable = (cancelable == nil) and true or cancelable
if #choices <= minNum and not all_choices then return choices end
assert(minNum <= maxNum)
assert(not all_choices or table.every(choices, function(c) return table.contains(all_choices, c) end))
- local command = "AskForCheck"
+ local command = "AskForChoices"
skill_name = skill_name or ""
prompt = prompt or ""
all_choices = all_choices or choices
diff --git a/lua/server/serverplayer.lua b/lua/server/serverplayer.lua
index 11b53b38..677ad4b9 100644
--- a/lua/server/serverplayer.lua
+++ b/lua/server/serverplayer.lua
@@ -362,6 +362,11 @@ function ServerPlayer:reconnect()
end
end
+ -- send banners
+ for k, v in pairs(room.banners) do
+ self:doNotify("SetBanner", json.encode{ k, v })
+ end
+
for _, p in ipairs(room.players) do
room:notifyProperty(self, p, "general")
room:notifyProperty(self, p, "deputyGeneral")
diff --git a/packages/test/init.lua b/packages/test/init.lua
index 5f599725..f1e81e1a 100644
--- a/packages/test/init.lua
+++ b/packages/test/init.lua
@@ -87,6 +87,10 @@ local control = fk.CreateActiveSkill{
on_use = function(self, room, effect)
--room:doSuperLightBox("packages/test/qml/Test.qml")
local from = room:getPlayerById(effect.from)
+ -- room:setPlayerMark(from, "@[test]test", {
+ -- all = {3, 1, 6, 9, 5, 11, 10, 2, 8, 7, 12, 4, 13},
+ -- ok = {10, 2},
+ -- })
-- room:swapSeat(from, to)
for _, pid in ipairs(effect.tos) do
local to = room:getPlayerById(pid)
@@ -145,6 +149,27 @@ Fk:addPoxiMethod{
end,
prompt = "魄袭:选你们俩手牌总共四个花色,或者不选直接按确定按钮"
}
+Fk:loadTranslationTable{['@[test]test']='割圆'}
+Fk:addQmlMark{
+ name = "test",
+ how_to_show = function(name, value)
+ local all_points = value.all
+ local ok_points = value.ok
+ -- 若没有点亮的就不显示
+ if #ok_points == 0 then return "" end
+ -- 否则,显示相邻的,逻辑上要构成循环
+ local start_idx = table.indexOf(all_points, ok_points[1]) - 1
+ local end_idx = table.indexOf(all_points, ok_points[#ok_points]) + 1
+ if start_idx == 0 then start_idx = #all_points end
+ if end_idx == #all_points + 1 then end_idx = 1 end
+ if start_idx == end_idx then
+ return Card:getNumberStr(all_points[start_idx])
+ else
+ return Card:getNumberStr(all_points[start_idx]) .. Card:getNumberStr(all_points[end_idx])
+ end
+ end,
+ qml_path = "packages/test/qml/TestDialog"
+}
--]]
local test_vs = fk.CreateViewAsSkill{
name = "test_vs",
diff --git a/packages/test/qml/TestDialog.qml b/packages/test/qml/TestDialog.qml
index a663bc53..be4ad3e6 100644
--- a/packages/test/qml/TestDialog.qml
+++ b/packages/test/qml/TestDialog.qml
@@ -1,38 +1,57 @@
+// 割圆的例子
import QtQuick
-import "../../../qml/Pages/RoomElement"
-import "../../../qml/Pages"
-
-GraphicsBox {
- property string custom_string: ""
+import QtQuick.Layouts
+import Fk.RoomElement
+ColumnLayout {
id: root
- title.text: Backend.translate("Test")
- width: Math.max(140, body.width + 20)
- height: body.height + title.height + 20
+ anchors.fill: parent
+ property var extra_data: ({ name: "", data: {
+ all: [1, 2, 4, 6],
+ ok: [1, 4],
+ } })
+ signal finish()
- Column {
- id: body
- x: 10
- y: title.height + 5
- spacing: 10
+ BigGlowText {
+ Layout.fillWidth: true
+ Layout.preferredHeight: childrenRect.height + 4
- Text {
- text: root.custom_string
- color: "#E4D5A0"
+ text: Backend.translate(extra_data.name)
+ }
+
+ PathView {
+ id: pathView
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ model: extra_data.data.all
+ delegate: Rectangle{
+ width: 42; height: 42
+ color: extra_data.data.ok.includes(modelData) ? "yellow" : "#CCEEEEEE"
+ radius: 2
+ Text {
+ anchors.centerIn: parent
+ text: modelData
+ font.pixelSize: 24
+ }
}
-
- MetroButton {
- text: Backend.translate("OKOK")
- anchors.horizontalCenter: parent.horizontalCenter
-
- onClicked: {
- close();
- ClientInstance.replyToServer("", "Hello from test dialog");
+ path: Path {
+ // 默认横屏了,应该没人用竖屏玩这游戏
+ startX: pathView.width / 2
+ startY: 40
+ PathArc {
+ x: pathView.width / 2
+ y: pathView.height - 40
+ radiusX: (pathView.height - 80) / 2
+ radiusY: (pathView.height - 80) / 2
+ direction: PathArc.Clockwise
+ }
+ PathArc {
+ x: pathView.width / 2
+ y: 40
+ radiusX: (pathView.height - 80) / 2
+ radiusY: (pathView.height - 80) / 2
+ direction: PathArc.Clockwise
}
}
}
-
- function loadData(data) {
- custom_string = data;
- }
}
diff --git a/src/network/router.cpp b/src/network/router.cpp
index be73a555..38c96437 100644
--- a/src/network/router.cpp
+++ b/src/network/router.cpp
@@ -284,7 +284,13 @@ void Router::handlePacket(const QByteArray &rawPacket) {
} else if (command == "KickPlayer") {
int i = jsonData.toInt();
auto p = room->findPlayer(i);
- if (p && !room->isStarted()) room->removePlayer(p);
+ if (p && !room->isStarted()) {
+ room->removePlayer(p);
+ room->addRejectId(i);
+ QTimer::singleShot(30000, this, [=]() {
+ room->removeRejectId(i);
+ });
+ }
} else if (command == "Ready") {
player->setReady(!player->isReady());
room->doBroadcastNotify(room->getPlayers(), "ReadyChanged",
diff --git a/src/server/room.cpp b/src/server/room.cpp
index 3241336e..4e96f636 100644
--- a/src/server/room.cpp
+++ b/src/server/room.cpp
@@ -125,6 +125,11 @@ void Room::addPlayer(ServerPlayer *player) {
if (!player)
return;
+ if (rejected_players.contains(player->getId())) {
+ player->doNotify("ErrorMsg", "rejected your demand of joining room");
+ return;
+ }
+
// 如果要加入的房间满员了,或者已经开战了,就不能再加入
if (isFull() || gameStarted) {
player->doNotify("ErrorMsg", "Room is full or already started!");
@@ -322,6 +327,11 @@ void Room::addObserver(ServerPlayer *player) {
return;
}
+ if (rejected_players.contains(player->getId())) {
+ player->doNotify("ErrorMsg", "rejected your demand of joining room");
+ return;
+ }
+
// 向observers中追加player,并从大厅移除player,然后将player的room设为this
observers.append(player);
player->setRoom(this);
@@ -573,3 +583,12 @@ void Room::pushRequest(const QString &req) {
m_thread->pushRequest(QString("%1,%2").arg(QString::number(id), req));
}
}
+
+void Room::addRejectId(int id) {
+ if (isLobby()) return;
+ rejected_players << id;
+}
+
+void Room::removeRejectId(int id) {
+ rejected_players.removeOne(id);
+}
diff --git a/src/server/room.h b/src/server/room.h
index ad7a4b90..2cf9a13a 100644
--- a/src/server/room.h
+++ b/src/server/room.h
@@ -63,6 +63,8 @@ class Room : public QObject {
void manuallyStart();
void pushRequest(const QString &req);
+ void addRejectId(int id);
+ void removeRejectId(int id);
signals:
void abandoned();
@@ -82,6 +84,7 @@ class Room : public QObject {
QList players;
QList observers;
QList runned_players;
+ QList rejected_players;
int robot_id;
bool gameStarted;
bool m_ready;
diff --git a/src/server/server.cpp b/src/server/server.cpp
index e8eada4b..30c5d98a 100644
--- a/src/server/server.cpp
+++ b/src/server/server.cpp
@@ -60,7 +60,7 @@ Server::Server(QObject *parent) : QObject(parent) {
}
}
- for (int i = 0; i < 20; i++) {
+ for (int i = 0; i < 30; i++) {
if (!this->isListening) {
return;
}