mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-15 19:22:25 +08:00
Request (#7)
* cli * add timeout for class Room * request func, roomowner * request * corrent stupid Qml/JS * chooseGenerals * prepareForStart(part 1) * fix require grammar
This commit is contained in:
parent
58ea0ca80a
commit
7fd127b849
BIN
image/photo/owner.png
Normal file
BIN
image/photo/owner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
BIN
image/photo/ready.png
Normal file
BIN
image/photo/ready.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
|
@ -1,7 +1,7 @@
|
|||
Client = class('Client')
|
||||
|
||||
-- load client classes
|
||||
ClientPlayer = require "client/clientplayer"
|
||||
ClientPlayer = require "client.clientplayer"
|
||||
|
||||
freekill.client_callback = {}
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ function Engine:getGeneralsRandomly(num, generalPool, except, filter)
|
|||
except = except or {}
|
||||
|
||||
local availableGenerals = {}
|
||||
for _, general in ipairs(generalPool) do
|
||||
if not table.contains(except, general) and not (filter and filter(general)) then
|
||||
for _, general in pairs(generalPool) do
|
||||
if not table.contains(except, general.name) and not (filter and filter(general)) then
|
||||
table.insert(availableGenerals, general)
|
||||
end
|
||||
end
|
||||
|
@ -117,9 +117,9 @@ function Engine:getGeneralsRandomly(num, generalPool, except, filter)
|
|||
end
|
||||
|
||||
local result = {}
|
||||
while num > 0 do
|
||||
for i = 1, num do
|
||||
local randomGeneral = math.random(1, #availableGenerals)
|
||||
table.insert(result, randomGeneral)
|
||||
table.insert(result, availableGenerals[randomGeneral])
|
||||
table.remove(availableGenerals, randomGeneral)
|
||||
|
||||
if #availableGenerals == 0 then
|
||||
|
|
|
@ -13,7 +13,8 @@ function Player:initialize()
|
|||
self.chained = false
|
||||
self.dying = false
|
||||
self.dead = false
|
||||
|
||||
self.state = ""
|
||||
|
||||
self.playerSkills = {}
|
||||
end
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ FileIO = {
|
|||
isDir = freekill.QmlBackend_isDir
|
||||
}
|
||||
|
||||
os.getms = freekill.GetMicroSecond
|
||||
|
||||
Stack = class("Stack")
|
||||
function Stack:initialize()
|
||||
self.t = {}
|
||||
|
|
|
@ -8,7 +8,7 @@ package.path = package.path .. ";./lua/lib/?.lua"
|
|||
class = require "middleclass"
|
||||
json = require "json"
|
||||
require "sha256"
|
||||
Util = require "core/util"
|
||||
Util = require "core.util"
|
||||
math.randomseed(os.time())
|
||||
|
||||
DebugMode = true
|
||||
|
@ -20,12 +20,12 @@ function pt(t)
|
|||
end
|
||||
|
||||
-- load core classes
|
||||
Engine = require "core/engine"
|
||||
Package = require "core/package"
|
||||
General = require "core/general"
|
||||
Card = require "core/card"
|
||||
Skill = require "core/skill"
|
||||
Player = require "core/player"
|
||||
Engine = require "core.engine"
|
||||
Package = require "core.package"
|
||||
General = require "core.general"
|
||||
Card = require "core.card"
|
||||
Skill = require "core.skill"
|
||||
Player = require "core.player"
|
||||
|
||||
-- load packages
|
||||
Fk = Engine:new()
|
||||
|
|
|
@ -25,30 +25,106 @@ function GameLogic:run()
|
|||
self.room:adjustSeats()
|
||||
|
||||
self:chooseGenerals()
|
||||
self:startGame()
|
||||
self:prepareForStart()
|
||||
self:action()
|
||||
end
|
||||
|
||||
function GameLogic:assignRoles()
|
||||
local n = #self.room.players
|
||||
local room = self.room
|
||||
local n = #room.players
|
||||
local roles = self.role_table[n]
|
||||
table.shuffle(roles)
|
||||
|
||||
for i = 1, n do
|
||||
local p = self.room.players[i]
|
||||
local p = room.players[i]
|
||||
p.role = roles[i]
|
||||
if p.role == "lord" then
|
||||
self.room:broadcastProperty(p, "role")
|
||||
room:broadcastProperty(p, "role")
|
||||
else
|
||||
self.room:notifyProperty(p, p, "role")
|
||||
room:notifyProperty(p, p, "role")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GameLogic:chooseGenerals()
|
||||
local room = self.room
|
||||
local function setPlayerGeneral(player, general)
|
||||
if Fk.generals[general] == nil then return end
|
||||
player.general = general
|
||||
self.room:notifyProperty(player, player, "general")
|
||||
end
|
||||
local lord = room:getLord()
|
||||
local lord_general = nil
|
||||
if lord ~= nil then
|
||||
local generals = Fk:getGeneralsRandomly(3)
|
||||
for i = 1, #generals do
|
||||
generals[i] = generals[i].name
|
||||
end
|
||||
lord_general = room:askForGeneral(lord, generals)
|
||||
setPlayerGeneral(lord, lord_general)
|
||||
room:broadcastProperty(lord, "general")
|
||||
end
|
||||
|
||||
local nonlord = room:getOtherPlayers(lord)
|
||||
local generals = Fk:getGeneralsRandomly(#nonlord * 3, Fk.generals, {lord_general})
|
||||
table.shuffle(generals)
|
||||
for _, p in ipairs(nonlord) do
|
||||
local arg = {
|
||||
(table.remove(generals, 1)).name,
|
||||
(table.remove(generals, 1)).name,
|
||||
(table.remove(generals, 1)).name,
|
||||
}
|
||||
p.request_data = json.encode(arg)
|
||||
p.default_reply = arg[1]
|
||||
end
|
||||
|
||||
room:doBroadcastRequest("AskForGeneral", nonlord)
|
||||
for _, p in ipairs(nonlord) do
|
||||
if p.general == "" and p.reply_ready then
|
||||
local general = json.decode(p.client_reply)[1]
|
||||
setPlayerGeneral(p, general)
|
||||
else
|
||||
setPlayerGeneral(p, p.default_reply)
|
||||
end
|
||||
p.default_reply = ""
|
||||
end
|
||||
end
|
||||
|
||||
function GameLogic:startGame()
|
||||
function GameLogic:prepareForStart()
|
||||
local room = self.room
|
||||
local players = room.players
|
||||
room.alive_players = players
|
||||
for i = 1, #players - 1 do
|
||||
players[i].next = players[i + 1]
|
||||
end
|
||||
players[#players].next = players[1]
|
||||
|
||||
for _, p in ipairs(players) do
|
||||
assert(p.general ~= "")
|
||||
local general = Fk.generals[p.general]
|
||||
p.maxHp = general.maxHp
|
||||
p.hp = general.hp
|
||||
-- TODO: setup AI here
|
||||
|
||||
if p.role ~= "lord" then
|
||||
room:broadcastProperty(p, "general")
|
||||
elseif #players >= 5 then
|
||||
p.maxHp = p.maxHp + 1
|
||||
p.hp = p.hp + 1
|
||||
end
|
||||
room:broadcastProperty(p, "maxHp")
|
||||
room:broadcastProperty(p, "hp")
|
||||
|
||||
-- TODO: add skills to player
|
||||
end
|
||||
|
||||
-- TODO: prepare drawPile
|
||||
-- TODO: init cards in drawPile
|
||||
|
||||
-- TODO: init trigger table for self
|
||||
end
|
||||
|
||||
function GameLogic:action()
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -3,13 +3,16 @@ local Room = class("Room")
|
|||
function Room:initialize(_room)
|
||||
self.room = _room
|
||||
self.players = {} -- ServerPlayer[]
|
||||
self.gameFinished = false
|
||||
self.alive_players = {}
|
||||
self.game_finished = false
|
||||
self.timeout = _room:getTimeout()
|
||||
end
|
||||
|
||||
-- When this function returns, the Room(C++) thread stopped.
|
||||
function Room:run()
|
||||
for _, p in freekill.qlist(self.room:getPlayers()) do
|
||||
local player = ServerPlayer:new(p)
|
||||
player.state = p:getStateString()
|
||||
table.insert(self.players, player)
|
||||
self.server.players[player:getId()] = player
|
||||
end
|
||||
|
@ -32,8 +35,55 @@ function Room:notifyProperty(p, player, property)
|
|||
})
|
||||
end
|
||||
|
||||
function Room:doBroadcastNotify(command, jsonData)
|
||||
self.room:doBroadcastNotify(self.room:getPlayers(), command, jsonData)
|
||||
function Room:doBroadcastNotify(command, jsonData, players)
|
||||
players = players or self.players
|
||||
local tolist = freekill.SPlayerList()
|
||||
for _, p in ipairs(players) do
|
||||
tolist:append(p.serverplayer)
|
||||
end
|
||||
self.room:doBroadcastNotify(tolist, command, jsonData)
|
||||
end
|
||||
|
||||
function Room:doRequest(player, command, jsonData, wait)
|
||||
if wait == nil then wait = true end
|
||||
player:doRequest(command, jsonData, self.timeout)
|
||||
|
||||
if wait then
|
||||
return player:waitForReply(self.timeout)
|
||||
end
|
||||
end
|
||||
|
||||
function Room:doBroadcastRequest(command, players)
|
||||
players = players or self.players
|
||||
self:notifyMoveFocus(players, command)
|
||||
for _, p in ipairs(players) do
|
||||
self:doRequest(p, command, p.request_data, false)
|
||||
end
|
||||
|
||||
local remainTime = self.timeout
|
||||
local currentTime = os.time()
|
||||
local elapsed = 0
|
||||
for _, p in ipairs(players) do
|
||||
elapsed = os.time() - currentTime
|
||||
remainTime = remainTime - elapsed
|
||||
p:waitForReply(remainTime)
|
||||
end
|
||||
end
|
||||
|
||||
function Room:notifyMoveFocus(players, command)
|
||||
if (players.class) then
|
||||
players = {players}
|
||||
end
|
||||
|
||||
local ids = {}
|
||||
for _, p in ipairs(players) do
|
||||
table.insert(ids, p:getId())
|
||||
end
|
||||
|
||||
self:doBroadcastNotify("MoveFocus", json.encode{
|
||||
ids,
|
||||
command
|
||||
})
|
||||
end
|
||||
|
||||
function Room:adjustSeats()
|
||||
|
@ -64,8 +114,45 @@ function Room:adjustSeats()
|
|||
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
|
||||
end
|
||||
|
||||
function Room:getLord()
|
||||
local lord = self.players[1]
|
||||
if lord.role == "lord" then return lord end
|
||||
for _, p in ipairs(self.players) do
|
||||
if p.role == "lord" then return p end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function Room:getOtherPlayers(expect)
|
||||
local ret = {table.unpack(self.players)}
|
||||
table.removeOne(ret, expect)
|
||||
return ret
|
||||
end
|
||||
|
||||
function Room:askForGeneral(player, generals)
|
||||
local command = "AskForGeneral"
|
||||
self:notifyMoveFocus(player, command)
|
||||
|
||||
if #generals == 1 then return generals[1] end
|
||||
local defaultChoice = generals[1]
|
||||
|
||||
if (player.state == "online") then
|
||||
local result = self:doRequest(player, command, json.encode(generals))
|
||||
if result == "" then
|
||||
return defaultChoice
|
||||
else
|
||||
-- TODO: result is a JSON array
|
||||
-- update here when choose multiple generals
|
||||
return json.decode(result)[1]
|
||||
end
|
||||
end
|
||||
|
||||
return defaultChoice
|
||||
end
|
||||
|
||||
function Room:gameOver()
|
||||
self.gameFinished = true
|
||||
self.game_finished = true
|
||||
-- dosomething
|
||||
self.room:gameOver()
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Server = class('Server')
|
||||
|
||||
-- load server classes
|
||||
Room = require "server/room"
|
||||
GameLogic = require "server/gamelogic"
|
||||
ServerPlayer = require "server/serverplayer"
|
||||
Room = require "server.room"
|
||||
GameLogic = require "server.gamelogic"
|
||||
ServerPlayer = require "server.serverplayer"
|
||||
|
||||
freekill.server_callback = {}
|
||||
|
||||
|
|
|
@ -3,6 +3,14 @@ local ServerPlayer = Player:subclass("ServerPlayer")
|
|||
function ServerPlayer:initialize(_self)
|
||||
Player.initialize(self)
|
||||
self.serverplayer = _self
|
||||
|
||||
self.next = nil
|
||||
|
||||
-- Below are for doBroadcastRequest
|
||||
self.request_data = ""
|
||||
self.client_reply = ""
|
||||
self.default_reply = ""
|
||||
self.reply_ready = false
|
||||
end
|
||||
|
||||
function ServerPlayer:getId()
|
||||
|
@ -14,7 +22,23 @@ function ServerPlayer:doNotify(command, jsonData)
|
|||
end
|
||||
|
||||
function ServerPlayer:doRequest(command, jsonData, timeout)
|
||||
timeout = timeout or self.room.timeout
|
||||
self.client_reply = ""
|
||||
self.reply_ready = false
|
||||
self.serverplayer:doRequest(command, jsonData, timeout)
|
||||
end
|
||||
|
||||
function ServerPlayer:waitForReply(timeout)
|
||||
local result = ""
|
||||
if timeout == nil then
|
||||
result = self.serverplayer:waitForReply()
|
||||
else
|
||||
result = self.serverplayer:waitForReply(timeout)
|
||||
end
|
||||
self.request_data = ""
|
||||
self.client_reply = result
|
||||
if result ~= "" then self.reply_ready = true end
|
||||
return result
|
||||
end
|
||||
|
||||
return ServerPlayer
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
local extension = Package:new("standard")
|
||||
extension.metadata = require "standard/metadata"
|
||||
extension.metadata = require "standard.metadata"
|
||||
|
||||
Fk:loadTranslationTable{
|
||||
["wei"] = "魏",
|
||||
|
|
|
@ -9,4 +9,5 @@ QtObject {
|
|||
|
||||
// Client data
|
||||
property int roomCapacity: 0
|
||||
property int roomTimeout: 0
|
||||
}
|
||||
|
|
|
@ -29,7 +29,10 @@ callbacks["EnterLobby"] = function(jsonData) {
|
|||
}
|
||||
|
||||
callbacks["EnterRoom"] = function(jsonData) {
|
||||
config.roomCapacity = JSON.parse(jsonData)[0];
|
||||
// jsonData: int capacity, int timeout
|
||||
let data = JSON.parse(jsonData);
|
||||
config.roomCapacity = data[0];
|
||||
config.roomTimeout = data[1];
|
||||
mainStack.push(room);
|
||||
mainWindow.busy = false;
|
||||
}
|
||||
|
|
69
qml/Pages/MetroButton.qml
Normal file
69
qml/Pages/MetroButton.qml
Normal file
|
@ -0,0 +1,69 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
Item {
|
||||
property bool enabled: true
|
||||
property alias text: title.text
|
||||
property alias textColor: title.color
|
||||
property alias textFont: title.font
|
||||
property alias backgroundColor: bg.color
|
||||
property alias border: bg.border
|
||||
property alias iconSource: icon.source
|
||||
property int padding: 5
|
||||
|
||||
signal clicked
|
||||
|
||||
id: button
|
||||
width: icon.width + title.implicitWidth + padding * 2
|
||||
height: Math.max(icon.height, title.implicitHeight) + padding * 2
|
||||
|
||||
Rectangle {
|
||||
id: bg
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
border.width: 2
|
||||
border.color: "white"
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "hovered"; when: mouse.containsMouse
|
||||
PropertyChanges { target: bg; color: "white" }
|
||||
PropertyChanges { target: title; color: "black" }
|
||||
},
|
||||
State {
|
||||
name: "disabled"; when: !enabled
|
||||
PropertyChanges { target: button; opacity: 0.2 }
|
||||
}
|
||||
]
|
||||
|
||||
MouseArea {
|
||||
id: mouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: parent.enabled
|
||||
onReleased: if (parent.enabled) parent.clicked()
|
||||
}
|
||||
|
||||
Row {
|
||||
x: padding
|
||||
y: padding
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
|
||||
Image {
|
||||
id: icon
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
|
||||
Text {
|
||||
id: title
|
||||
font.pixelSize: 18
|
||||
// font.family: "WenQuanYi Micro Hei"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: ""
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,11 +13,9 @@ Item {
|
|||
property bool isOwner: false
|
||||
property bool isStarted: false
|
||||
|
||||
property alias popupBox: popupBox
|
||||
|
||||
// tmp
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "You are in room."
|
||||
}
|
||||
Button {
|
||||
text: "quit"
|
||||
anchors.bottom: parent.bottom
|
||||
|
@ -28,7 +26,7 @@ Item {
|
|||
}
|
||||
Button {
|
||||
text: "start game"
|
||||
visible: isOwner && !isStarted
|
||||
visible: dashboardModel.isOwner && !isStarted
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
|
@ -73,20 +71,20 @@ Item {
|
|||
id: photos
|
||||
model: photoModel
|
||||
Photo {
|
||||
general: _general
|
||||
screenName: _screenName
|
||||
role: _role
|
||||
kingdom: _kingdom
|
||||
netstate: _netstate
|
||||
maxHp: _maxHp
|
||||
hp: _hp
|
||||
seatNumber: _seatNumber
|
||||
isDead: _isDead
|
||||
dying: _dying
|
||||
faceturned: _faceturned
|
||||
chained: _chained
|
||||
drank: _drank
|
||||
isOwner: _isOwner
|
||||
general: model.general
|
||||
screenName: model.screenName
|
||||
role: model.role
|
||||
kingdom: model.kingdom
|
||||
netstate: model.netstate
|
||||
maxHp: model.maxHp
|
||||
hp: model.hp
|
||||
seatNumber: model.seatNumber
|
||||
isDead: model.isDead
|
||||
dying: model.dying
|
||||
faceturned: model.faceturned
|
||||
chained: model.chained
|
||||
drank: model.drank
|
||||
isOwner: model.isOwner
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,6 +127,30 @@ Item {
|
|||
self.isOwner: dashboardModel.isOwner
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: popupBox
|
||||
onSourceChanged: {
|
||||
if (item === null)
|
||||
return;
|
||||
item.finished.connect(function(){
|
||||
source = "";
|
||||
});
|
||||
item.widthChanged.connect(function(){
|
||||
popupBox.moveToCenter();
|
||||
});
|
||||
item.heightChanged.connect(function(){
|
||||
popupBox.moveToCenter();
|
||||
});
|
||||
moveToCenter();
|
||||
}
|
||||
|
||||
function moveToCenter()
|
||||
{
|
||||
item.x = Math.round((roomArea.width - item.width) / 2);
|
||||
item.y = Math.round(roomArea.height * 0.67 - item.height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
toast.show("Sucesessfully entered room.");
|
||||
|
||||
|
@ -157,20 +179,20 @@ Item {
|
|||
photoModel.append({
|
||||
id: -1,
|
||||
index: i - 1, // For animating seat swap
|
||||
_general: "",
|
||||
_screenName: "",
|
||||
_role: "unknown",
|
||||
_kingdom: "qun",
|
||||
_netstate: "online",
|
||||
_maxHp: 0,
|
||||
_hp: 0,
|
||||
_seatNumber: i + 1,
|
||||
_isDead: false,
|
||||
_dying: false,
|
||||
_faceturned: false,
|
||||
_chained: false,
|
||||
_drank: false,
|
||||
_isOwner: false
|
||||
general: "",
|
||||
screenName: "",
|
||||
role: "unknown",
|
||||
kingdom: "qun",
|
||||
netstate: "online",
|
||||
maxHp: 0,
|
||||
hp: 0,
|
||||
seatNumber: i + 1,
|
||||
isDead: false,
|
||||
dying: false,
|
||||
faceturned: false,
|
||||
chained: false,
|
||||
drank: false,
|
||||
isOwner: false
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ Item {
|
|||
|
||||
function remove(outputs)
|
||||
{
|
||||
var result = [];
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
for (var j = 0; j < outputs.length; j++) {
|
||||
let result = [];
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
for (let j = 0; j < outputs.length; j++) {
|
||||
if (outputs[j] === cards[i].cid) {
|
||||
result.push(cards[i]);
|
||||
cards.splice(i, 1);
|
||||
|
@ -37,9 +37,9 @@ Item {
|
|||
|
||||
function updateCardPosition(animated)
|
||||
{
|
||||
var i, card;
|
||||
let i, card;
|
||||
|
||||
var overflow = false;
|
||||
let overflow = false;
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.origX = i * card.width;
|
||||
|
@ -52,8 +52,8 @@ Item {
|
|||
|
||||
if (overflow) {
|
||||
// TODO: Adjust cards in multiple lines if there are too many cards
|
||||
var xLimit = root.width - card.width;
|
||||
var spacing = xLimit / (cards.length - 1);
|
||||
let xLimit = root.width - card.width;
|
||||
let spacing = xLimit / (cards.length - 1);
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.origX = i * spacing;
|
||||
|
@ -61,7 +61,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
var parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
let parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.origX += parentPos.x;
|
||||
|
|
|
@ -26,6 +26,7 @@ Item {
|
|||
property bool footnoteVisible: true
|
||||
property bool known: true // if false it only show a card back
|
||||
property bool enabled: true // if false the card will be grey
|
||||
property alias card: cardItem
|
||||
property alias glow: glowItem
|
||||
|
||||
function getColor() {
|
||||
|
@ -38,9 +39,12 @@ Item {
|
|||
property int cid: 0
|
||||
property bool selectable: true
|
||||
property bool selected: false
|
||||
property bool draggable: false
|
||||
property bool autoBack: true
|
||||
property int origX: 0
|
||||
property int origY: 0
|
||||
property real origOpacity: 0
|
||||
property real origOpacity: 1
|
||||
property bool isClicked: false
|
||||
property bool moveAborted: false
|
||||
property alias goBackAnim: goBackAnimation
|
||||
property int goBackDuration: 500
|
||||
|
@ -71,6 +75,7 @@ Item {
|
|||
source: known ? (name != "" ? SkinBank.CARD_DIR + name : "")
|
||||
: (SkinBank.CARD_DIR + "card-back")
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
}
|
||||
|
||||
Image {
|
||||
|
@ -97,7 +102,7 @@ Item {
|
|||
Image {
|
||||
id: colorItem
|
||||
visible: known && suit == ""
|
||||
source: visible ? SkinBank.CARD_SUIT_DIR + "/" + color : ""
|
||||
source: (visible && color != "") ? SkinBank.CARD_SUIT_DIR + "/" + color : ""
|
||||
x: 1
|
||||
}
|
||||
|
||||
|
@ -126,6 +131,41 @@ Item {
|
|||
opacity: 0.7
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: draggable ? parent : undefined
|
||||
drag.axis: Drag.XAndYAxis
|
||||
hoverEnabled: true
|
||||
|
||||
onReleased: {
|
||||
root.isClicked = mouse.isClick;
|
||||
parent.released();
|
||||
if (autoBack)
|
||||
goBackAnimation.start();
|
||||
}
|
||||
|
||||
onEntered: {
|
||||
parent.entered();
|
||||
if (draggable) {
|
||||
glow.visible = true;
|
||||
root.z++;
|
||||
}
|
||||
}
|
||||
|
||||
onExited: {
|
||||
parent.exited();
|
||||
if (draggable) {
|
||||
glow.visible = false;
|
||||
root.z--;
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
selected = selectable ? !selected : false;
|
||||
parent.clicked();
|
||||
}
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: goBackAnimation
|
||||
|
||||
|
@ -180,7 +220,7 @@ Item {
|
|||
|
||||
function toData()
|
||||
{
|
||||
var data = {
|
||||
let data = {
|
||||
cid: cid,
|
||||
name: name,
|
||||
suit: suit,
|
||||
|
|
177
qml/Pages/RoomElement/ChooseGeneralBox.qml
Normal file
177
qml/Pages/RoomElement/ChooseGeneralBox.qml
Normal file
|
@ -0,0 +1,177 @@
|
|||
import QtQuick 2.15
|
||||
import ".."
|
||||
import "../skin-bank.js" as SkinBank
|
||||
|
||||
GraphicsBox {
|
||||
property alias generalList: generalList
|
||||
// property var generalList: []
|
||||
property int choiceNum: 1
|
||||
property var choices: []
|
||||
property var selectedItem: []
|
||||
property bool loaded: false
|
||||
|
||||
ListModel {
|
||||
id: generalList
|
||||
}
|
||||
|
||||
id: root
|
||||
title.text: qsTr("Please choose ") + choiceNum + qsTr(" general(s)")
|
||||
width: generalArea.width + body.anchors.leftMargin + body.anchors.rightMargin
|
||||
height: body.implicitHeight + body.anchors.topMargin + body.anchors.bottomMargin
|
||||
|
||||
Column {
|
||||
id: body
|
||||
anchors.fill: parent
|
||||
anchors.margins: 40
|
||||
anchors.bottomMargin: 20
|
||||
|
||||
Item {
|
||||
id: generalArea
|
||||
width: (generalList.count >= 5 ? Math.ceil(generalList.count / 2) : Math.max(3, generalList.count)) * 97
|
||||
height: generalList.count >= 5 ? 290 : 150
|
||||
z: 1
|
||||
|
||||
Repeater {
|
||||
id: generalMagnetList
|
||||
model: generalList.count
|
||||
|
||||
Item {
|
||||
width: 93
|
||||
height: 130
|
||||
x: (index % Math.ceil(generalList.count / (generalList.count >= 5 ? 2 : 1))) * 98 + (generalList.count >= 5 && index > generalList.count / 2 && generalList.count % 2 == 1 ? 50 : 0)
|
||||
y: generalList.count < 5 ? 0 : (index < generalList.count / 2 ? 0 : 135)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: splitLine
|
||||
width: parent.width - 80
|
||||
height: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
clip: true
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 165
|
||||
|
||||
Row {
|
||||
id: resultArea
|
||||
anchors.centerIn: parent
|
||||
spacing: 10
|
||||
|
||||
Repeater {
|
||||
id: resultList
|
||||
model: choiceNum
|
||||
|
||||
Rectangle {
|
||||
color: "#1D1E19"
|
||||
radius: 3
|
||||
width: 93
|
||||
height: 130
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: buttonArea
|
||||
width: parent.width
|
||||
height: 40
|
||||
|
||||
MetroButton {
|
||||
id: fightButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
text: qsTr("Fight")
|
||||
width: 120
|
||||
height: 35
|
||||
enabled: false
|
||||
|
||||
onClicked: close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: generalCardList
|
||||
model: generalList
|
||||
|
||||
GeneralCardItem {
|
||||
name: model.name
|
||||
selectable: true
|
||||
draggable: true
|
||||
|
||||
onClicked: {
|
||||
let toSelect = true;
|
||||
for (let i = 0; i < selectedItem.length; i++) {
|
||||
if (selectedItem[i] === this) {
|
||||
toSelect = false;
|
||||
selectedItem.splice(i, 1);
|
||||
}
|
||||
}
|
||||
if (toSelect && selectedItem.length < choiceNum)
|
||||
selectedItem.push(this);
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (!isClicked)
|
||||
arrangeCards();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function arrangeCards()
|
||||
{
|
||||
let item, i;
|
||||
|
||||
selectedItem = [];
|
||||
for (i = 0; i < generalList.count; i++) {
|
||||
item = generalCardList.itemAt(i);
|
||||
if (item.y > splitLine.y)
|
||||
selectedItem.push(item);
|
||||
}
|
||||
|
||||
selectedItem.sort((a, b) => a.x - b.x);
|
||||
|
||||
if (selectedItem.length > choiceNum)
|
||||
selectedItem.splice(choiceNum, selectedItem.length - choiceNum);
|
||||
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
function updatePosition()
|
||||
{
|
||||
choices = [];
|
||||
let item, magnet, pos, i;
|
||||
for (i = 0; i < selectedItem.length && i < resultList.count; i++) {
|
||||
item = selectedItem[i];
|
||||
choices.push(item.name);
|
||||
magnet = resultList.itemAt(i);
|
||||
pos = root.mapFromItem(resultArea, magnet.x, magnet.y);
|
||||
if (item.origX !== pos.x || item.origY !== item.y) {
|
||||
item.origX = pos.x;
|
||||
item.origY = pos.y;
|
||||
item.goBack(true);
|
||||
}
|
||||
}
|
||||
|
||||
fightButton.enabled = (choices.length == choiceNum);
|
||||
|
||||
for (i = 0; i < generalCardList.count; i++) {
|
||||
item = generalCardList.itemAt(i);
|
||||
if (selectedItem.indexOf(item) != -1)
|
||||
continue;
|
||||
|
||||
magnet = generalMagnetList.itemAt(i);
|
||||
pos = root.mapFromItem(generalMagnetList.parent, magnet.x, magnet.y);
|
||||
if (item.origX !== pos.x || item.origY !== item.y) {
|
||||
item.origX = pos.x;
|
||||
item.origY = pos.y;
|
||||
item.goBack(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
qml/Pages/RoomElement/GeneralCardItem.qml
Normal file
24
qml/Pages/RoomElement/GeneralCardItem.qml
Normal file
|
@ -0,0 +1,24 @@
|
|||
import QtQuick 2.15
|
||||
import "../skin-bank.js" as SkinBank
|
||||
|
||||
/* Layout of general card:
|
||||
* +--------+
|
||||
*kindom|wu 9999| <- hp
|
||||
*name -|s |
|
||||
* |q img |
|
||||
* | |
|
||||
* | |
|
||||
* +--------+
|
||||
* Inherit from CardItem to use common signal
|
||||
*/
|
||||
|
||||
CardItem {
|
||||
property string kingdom: "qun"
|
||||
name: "caocao"
|
||||
// description: Sanguosha.getGeneralDescription(name)
|
||||
suit: ""
|
||||
number: 0
|
||||
footnote: ""
|
||||
card.source: SkinBank.GENERAL_DIR + name
|
||||
glow.color: "white" //Engine.kingdomColor[kingdom]
|
||||
}
|
53
qml/Pages/RoomElement/GraphicsBox.qml
Normal file
53
qml/Pages/RoomElement/GraphicsBox.qml
Normal file
|
@ -0,0 +1,53 @@
|
|||
import QtQuick 2.15
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Item {
|
||||
property alias title: titleItem
|
||||
signal accepted() //Read result
|
||||
signal finished() //Close the box
|
||||
|
||||
id: root
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: "#B0000000"
|
||||
radius: 5
|
||||
border.color: "#A6967A"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
source: background
|
||||
anchors.fill: background
|
||||
color: "#B0000000"
|
||||
radius: 5
|
||||
samples: 12
|
||||
spread: 0.2
|
||||
horizontalOffset: 5
|
||||
verticalOffset: 4
|
||||
transparentBorder: true
|
||||
}
|
||||
|
||||
Text {
|
||||
id: titleItem
|
||||
color: "#E4D5A0"
|
||||
font.pixelSize: 18
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 4
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: parent
|
||||
drag.axis: Drag.XAndYAxis
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
accepted();
|
||||
finished();
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ Item {
|
|||
{
|
||||
cardArea.add(inputs);
|
||||
if (inputs instanceof Array) {
|
||||
for (var i = 0; i < inputs.length; i++)
|
||||
for (let i = 0; i < inputs.length; i++)
|
||||
filterInputCard(inputs[i]);
|
||||
} else {
|
||||
filterInputCard(inputs);
|
||||
|
@ -36,9 +36,9 @@ Item {
|
|||
|
||||
function remove(outputs)
|
||||
{
|
||||
var result = cardArea.remove(outputs);
|
||||
var card;
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
let result = cardArea.remove(outputs);
|
||||
let card;
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
card = result[i];
|
||||
card.draggable = false;
|
||||
card.selectable = false;
|
||||
|
@ -49,7 +49,7 @@ Item {
|
|||
|
||||
function enableCards(cardIds)
|
||||
{
|
||||
var card, i;
|
||||
let card, i;
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.selectable = cardIds.contains(card.cid);
|
||||
|
@ -64,7 +64,7 @@ Item {
|
|||
{
|
||||
cardArea.updateCardPosition(false);
|
||||
|
||||
var i, card;
|
||||
let i, card;
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
if (card.selected)
|
||||
|
@ -81,8 +81,8 @@ Item {
|
|||
{
|
||||
area.updateCardPosition(true);
|
||||
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var card = cards[i];
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
let card = cards[i];
|
||||
if (card.selected) {
|
||||
if (!selectedCards.contains(card))
|
||||
selectCard(card);
|
||||
|
@ -101,7 +101,7 @@ Item {
|
|||
|
||||
function unselectCard(card)
|
||||
{
|
||||
for (var i = 0; i < selectedCards.length; i++) {
|
||||
for (let i = 0; i < selectedCards.length; i++) {
|
||||
if (selectedCards[i] === card) {
|
||||
selectedCards.splice(i, 1);
|
||||
cardSelected(card.cid, false);
|
||||
|
@ -112,7 +112,7 @@ Item {
|
|||
|
||||
function unselectAll(exceptId) {
|
||||
let card = undefined;
|
||||
for (var i = 0; i < selectedCards.length; i++) {
|
||||
for (let i = 0; i < selectedCards.length; i++) {
|
||||
if (selectedCards[i].cid !== exceptId) {
|
||||
selectedCards[i].selected = false;
|
||||
} else {
|
||||
|
|
|
@ -10,9 +10,9 @@ Item {
|
|||
|
||||
function add(inputs)
|
||||
{
|
||||
var card;
|
||||
let card;
|
||||
if (inputs instanceof Array) {
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
card = inputs[i];
|
||||
pendingInput.push(card);
|
||||
cards.push(card.toData());
|
||||
|
@ -38,7 +38,7 @@ Item {
|
|||
if (!checkExisting)
|
||||
return true;
|
||||
|
||||
for (var i = 0; i < cards.length; i++)
|
||||
for (let i = 0; i < cards.length; i++)
|
||||
{
|
||||
if (cards[i].cid === cid)
|
||||
return true;
|
||||
|
@ -48,13 +48,13 @@ Item {
|
|||
|
||||
function remove(outputs)
|
||||
{
|
||||
var component = Qt.createComponent("CardItem.qml");
|
||||
let component = Qt.createComponent("CardItem.qml");
|
||||
if (component.status !== Component.Ready)
|
||||
return [];
|
||||
|
||||
var parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
var card;
|
||||
var items = [];
|
||||
let parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
let card;
|
||||
let items = [];
|
||||
for (let i = 0; i < outputs.length; i++) {
|
||||
if (_contains(outputs[i])) {
|
||||
let state = JSON.parse(Sanguosha.getCard4Qml(outputs[i]))
|
||||
|
@ -82,10 +82,10 @@ Item {
|
|||
|
||||
function updateCardPosition(animated)
|
||||
{
|
||||
var i, card;
|
||||
let i, card;
|
||||
|
||||
if (animated) {
|
||||
var parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
let parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
for (i = 0; i < pendingInput.length; i++) {
|
||||
card = pendingInput[i];
|
||||
card.origX = parentPos.x - card.width / 2 + ((i - pendingInput.length / 2) * 15);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import QtQuick 2.15
|
||||
import QtGraphicalEffects 1.15
|
||||
import QtQuick.Controls 2.15
|
||||
import "PhotoElement"
|
||||
import "../skin-bank.js" as SkinBank
|
||||
|
||||
|
@ -24,6 +25,9 @@ Item {
|
|||
property bool drank: false
|
||||
property bool isOwner: false
|
||||
|
||||
property alias progressBar: progressBar
|
||||
property alias progressTip: progressTip.text
|
||||
|
||||
Behavior on x {
|
||||
NumberAnimation { duration: 600; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
|
@ -95,6 +99,15 @@ Item {
|
|||
visible: root.isDead
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
anchors.bottomMargin: 8
|
||||
anchors.rightMargin: 4
|
||||
source: SkinBank.PHOTO_DIR + (isOwner ? "owner" : "ready")
|
||||
visible: screenName != "" && !roomScene.isStarted
|
||||
}
|
||||
|
||||
Image {
|
||||
id: turnedOver
|
||||
visible: root.faceturned
|
||||
|
@ -155,6 +168,7 @@ Item {
|
|||
|
||||
GlowText {
|
||||
id: seatNum
|
||||
visible: !progressBar.visible
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: -32
|
||||
|
@ -191,4 +205,42 @@ Item {
|
|||
function tremble() {
|
||||
trembleAnimation.start()
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: progressBar
|
||||
width: parent.width
|
||||
height: 4
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: -4
|
||||
from: 0.0
|
||||
to: 100.0
|
||||
|
||||
visible: false
|
||||
NumberAnimation on value {
|
||||
running: progressBar.visible
|
||||
from: 100.0
|
||||
to: 0.0
|
||||
duration: config.roomTimeout * 1000
|
||||
|
||||
onFinished: {
|
||||
progressBar.visible = false;
|
||||
root.progressTip = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.top: progressBar.bottom
|
||||
anchors.topMargin: 1
|
||||
source: SkinBank.PHOTO_DIR + "control/tip"
|
||||
visible: progressTip.text != ""
|
||||
Text {
|
||||
id: progressTip
|
||||
font.family: "FZLiBian-S02"
|
||||
font.pixelSize: 18
|
||||
x: 18
|
||||
color: "white"
|
||||
text: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ Item {
|
|||
running: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
var i, card;
|
||||
let i, card;
|
||||
if (toVanish) {
|
||||
for (i = 0; i < discardedCards.length; i++) {
|
||||
card = discardedCards[i];
|
||||
|
@ -60,13 +60,13 @@ Item {
|
|||
|
||||
function remove(outputs)
|
||||
{
|
||||
var i, j;
|
||||
let i, j;
|
||||
|
||||
var result = area.remove(outputs);
|
||||
var vanished = [];
|
||||
let result = area.remove(outputs);
|
||||
let vanished = [];
|
||||
if (result.length < outputs.length) {
|
||||
for (i = 0; i < outputs.length; i++) {
|
||||
var exists = false;
|
||||
let exists = false;
|
||||
for (j = 0; j < result.length; j++) {
|
||||
if (result[j].cid === outputs[i]) {
|
||||
exists = true;
|
||||
|
@ -96,9 +96,9 @@ Item {
|
|||
if (cards.length <= 0)
|
||||
return;
|
||||
|
||||
var i, card;
|
||||
let i, card;
|
||||
|
||||
var overflow = false;
|
||||
let overflow = false;
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.homeX = i * card.width;
|
||||
|
@ -111,8 +111,8 @@ Item {
|
|||
|
||||
if (overflow) {
|
||||
//@to-do: Adjust cards in multiple lines if there are too many cards
|
||||
var xLimit = root.width - card.width;
|
||||
var spacing = xLimit / (cards.length - 1);
|
||||
let xLimit = root.width - card.width;
|
||||
let spacing = xLimit / (cards.length - 1);
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.homeX = i * spacing;
|
||||
|
@ -120,8 +120,8 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
var offsetX = Math.max(0, (root.width - cards.length * card.width) / 2);
|
||||
var parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
let offsetX = Math.max(0, (root.width - cards.length * card.width) / 2);
|
||||
let parentPos = roomScene.mapFromItem(root, 0, 0);
|
||||
for (i = 0; i < cards.length; i++) {
|
||||
card = cards[i];
|
||||
card.homeX += parentPos.x + offsetX;
|
||||
|
|
|
@ -7,14 +7,14 @@ function arrangePhotos() {
|
|||
* +---------------+
|
||||
*/
|
||||
|
||||
var photoWidth = 175;
|
||||
var roomAreaPadding = 10;
|
||||
var verticalPadding = Math.max(10, roomArea.width * 0.01);
|
||||
var horizontalSpacing = Math.max(30, roomArea.height * 0.1);
|
||||
var verticalSpacing = (roomArea.width - photoWidth * 7 - verticalPadding * 2) / 6;
|
||||
const photoWidth = 175;
|
||||
const roomAreaPadding = 10;
|
||||
let verticalPadding = Math.max(10, roomArea.width * 0.01);
|
||||
let horizontalSpacing = Math.max(30, roomArea.height * 0.1);
|
||||
let verticalSpacing = (roomArea.width - photoWidth * 7 - verticalPadding * 2) / 6;
|
||||
|
||||
// Position 1-7
|
||||
var regions = [
|
||||
const regions = [
|
||||
{ x: verticalPadding + (photoWidth + verticalSpacing) * 6, y: roomAreaPadding + horizontalSpacing * 2 },
|
||||
{ x: verticalPadding + (photoWidth + verticalSpacing) * 5, y: roomAreaPadding + horizontalSpacing },
|
||||
{ x: verticalPadding + (photoWidth + verticalSpacing) * 4, y: roomAreaPadding },
|
||||
|
@ -24,7 +24,7 @@ function arrangePhotos() {
|
|||
{ x: verticalPadding, y: roomAreaPadding + horizontalSpacing * 2 },
|
||||
];
|
||||
|
||||
var regularSeatIndex = [
|
||||
const regularSeatIndex = [
|
||||
[4],
|
||||
[3, 5],
|
||||
[1, 4, 7],
|
||||
|
@ -33,9 +33,9 @@ function arrangePhotos() {
|
|||
[1, 2, 3, 5, 6, 7],
|
||||
[1, 2, 3, 4, 5, 6, 7],
|
||||
];
|
||||
var seatIndex = regularSeatIndex[playerNum - 2];
|
||||
let seatIndex = regularSeatIndex[playerNum - 2];
|
||||
|
||||
var item, region, i;
|
||||
let item, region, i;
|
||||
|
||||
for (i = 0; i < playerNum - 1; i++) {
|
||||
item = photos.itemAt(i);
|
||||
|
@ -58,9 +58,8 @@ callbacks["AddPlayer"] = function(jsonData) {
|
|||
let name = data[1];
|
||||
let avatar = data[2];
|
||||
item.id = uid;
|
||||
item._screenName = name;
|
||||
item._general = avatar;
|
||||
photos.itemAt(i).tremble();
|
||||
item.screenName = name;
|
||||
item.general = avatar;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -73,19 +72,31 @@ callbacks["RemovePlayer"] = function(jsonData) {
|
|||
let item = photoModel.get(i);
|
||||
if (item.id === uid) {
|
||||
item.id = -1;
|
||||
item._screenName = "";
|
||||
item._general = "";
|
||||
item.screenName = "";
|
||||
item.general = "";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
callbacks["RoomOwner"] = function(jsonData) {
|
||||
// jsonData: int uid of the owner
|
||||
toast.show(J)
|
||||
let uid = JSON.parse(jsonData)[0];
|
||||
|
||||
if (dashboardModel.id === uid) {
|
||||
dashboardModel.isOwner = true;
|
||||
roomScene.dashboardModelChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
if (item.id === uid) {
|
||||
item.isOwner = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
callbacks["PropertyUpdate"] = function(jsonData) {
|
||||
// jsonData: int id, string property_name, value
|
||||
|
@ -103,7 +114,7 @@ callbacks["PropertyUpdate"] = function(jsonData) {
|
|||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
if (item.id === uid) {
|
||||
item["_" + property_name] = value;
|
||||
item[property_name] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -112,10 +123,11 @@ callbacks["PropertyUpdate"] = function(jsonData) {
|
|||
callbacks["ArrangeSeats"] = function(jsonData) {
|
||||
// jsonData: seat order
|
||||
let order = JSON.parse(jsonData);
|
||||
roomScene.isStarted = true;
|
||||
|
||||
for (let i = 0; i < photoModel.count; i++) {
|
||||
let item = photoModel.get(i);
|
||||
item._seatNumber = order.indexOf(item.id) + 1;
|
||||
item.seatNumber = order.indexOf(item.id) + 1;
|
||||
}
|
||||
|
||||
dashboardModel.seatNumber = order.indexOf(Self.id) + 1;
|
||||
|
@ -134,3 +146,45 @@ callbacks["ArrangeSeats"] = function(jsonData) {
|
|||
|
||||
arrangePhotos();
|
||||
}
|
||||
|
||||
function cancelAllFocus() {
|
||||
let item;
|
||||
for (let i = 0; i < playerNum - 1; i++) {
|
||||
item = photos.itemAt(i);
|
||||
item.progressBar.visible = false;
|
||||
item.progressTip = "";
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["MoveFocus"] = function(jsonData) {
|
||||
// jsonData: int[] focuses, string command
|
||||
cancelAllFocus();
|
||||
let data = JSON.parse(jsonData);
|
||||
let focuses = data[0];
|
||||
let command = data[1];
|
||||
|
||||
let item, model;
|
||||
for (let i = 0; i < playerNum - 1; i++) {
|
||||
model = photoModel.get(i);
|
||||
if (focuses.indexOf(model.id) != -1) {
|
||||
item = photos.itemAt(i);
|
||||
item.progressBar.visible = true;
|
||||
item.progressTip = command + " thinking...";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["AskForGeneral"] = function(jsonData) {
|
||||
// jsonData: string[] Generals
|
||||
// TODO: choose multiple generals
|
||||
let data = JSON.parse(jsonData);
|
||||
roomScene.popupBox.source = "RoomElement/ChooseGeneralBox.qml";
|
||||
let box = roomScene.popupBox.item;
|
||||
box.choiceNum = 1;
|
||||
box.accepted.connect(() => {
|
||||
ClientInstance.replyToServer("AskForGeneral", JSON.stringify([box.choices[0]]));
|
||||
});
|
||||
for (let i = 0; i < data.length; i++)
|
||||
box.generalList.append({ "name": data[i] });
|
||||
box.updatePosition();
|
||||
}
|
||||
|
|
21
src/main.cpp
21
src/main.cpp
|
@ -3,32 +3,39 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
QGuiApplication::setApplicationName("FreeKill");
|
||||
QGuiApplication::setApplicationVersion("Alpha 0.0.1");
|
||||
QCoreApplication *app;
|
||||
QCoreApplication::setApplicationName("FreeKill");
|
||||
QCoreApplication::setApplicationVersion("Alpha 0.0.1");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("FreeKill server");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addOption({{"s", "server"}, "start server at <port>", "port"});
|
||||
parser.process(app);
|
||||
QStringList cliOptions;
|
||||
for (int i = 0; i < argc; i++)
|
||||
cliOptions << argv[i];
|
||||
|
||||
parser.parse(cliOptions);
|
||||
|
||||
bool startServer = parser.isSet("server");
|
||||
ushort serverPort = 9527;
|
||||
|
||||
if (startServer) {
|
||||
app = new QCoreApplication(argc, argv);
|
||||
bool ok = false;
|
||||
if (parser.value("server").toInt(&ok) && ok)
|
||||
serverPort = parser.value("server").toInt();
|
||||
Server *server = new Server;
|
||||
if (!server->listen(QHostAddress::Any, serverPort)) {
|
||||
fprintf(stderr, "cannot listen on port %d!\n", serverPort);
|
||||
app.exit(1);
|
||||
app->exit(1);
|
||||
}
|
||||
return app.exec();
|
||||
return app->exec();
|
||||
}
|
||||
|
||||
app = new QGuiApplication(argc, argv);
|
||||
|
||||
QQmlApplicationEngine *engine = new QQmlApplicationEngine;
|
||||
|
||||
QmlBackend backend;
|
||||
|
@ -44,7 +51,7 @@ int main(int argc, char *argv[])
|
|||
engine->rootContext()->setContextProperty("Debugging", debugging);
|
||||
engine->load("qml/main.qml");
|
||||
|
||||
int ret = app.exec();
|
||||
int ret = app->exec();
|
||||
|
||||
// delete the engine first
|
||||
// to avoid "TypeError: Cannot read property 'xxx' of null"
|
||||
|
|
|
@ -60,7 +60,7 @@ void Router::request(int type, const QString& command,
|
|||
|
||||
replyMutex.lock();
|
||||
expectedReplyId = requestId;
|
||||
replyTimeout = 0;
|
||||
replyTimeout = timeout;
|
||||
requestStartTime = QDateTime::currentDateTime();
|
||||
m_reply = QString();
|
||||
replyMutex.unlock();
|
||||
|
@ -123,7 +123,7 @@ QString Router::waitForReply()
|
|||
|
||||
QString Router::waitForReply(int timeout)
|
||||
{
|
||||
replyReadySemaphore.tryAcquire(1, timeout);
|
||||
replyReadySemaphore.tryAcquire(1, timeout * 1000);
|
||||
return m_reply;
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,6 @@ void Router::handlePacket(const QByteArray& rawPacket)
|
|||
|
||||
m_reply = jsonData;
|
||||
// TODO: callback?
|
||||
qDebug() << rawPacket << Qt::endl;
|
||||
|
||||
replyReadySemaphore.release();
|
||||
if (extraReplyReadySemaphore) {
|
||||
|
|
|
@ -8,7 +8,9 @@ Room::Room(Server* server)
|
|||
server->nextRoomId++;
|
||||
this->server = server;
|
||||
setParent(server);
|
||||
owner = nullptr;
|
||||
gameStarted = false;
|
||||
timeout = 15;
|
||||
if (!isLobby()) {
|
||||
connect(this, &Room::playerAdded, server->lobby(), &Room::removePlayer);
|
||||
connect(this, &Room::playerRemoved, server->lobby(), &Room::addPlayer);
|
||||
|
@ -76,7 +78,7 @@ void Room::setOwner(ServerPlayer *owner)
|
|||
this->owner = owner;
|
||||
QJsonArray jsonData;
|
||||
jsonData << owner->getId();
|
||||
owner->doNotify("RoomOwner", QJsonDocument(jsonData).toJson());
|
||||
doBroadcastNotify(players, "RoomOwner", QJsonDocument(jsonData).toJson());
|
||||
}
|
||||
|
||||
void Room::addPlayer(ServerPlayer *player)
|
||||
|
@ -101,6 +103,7 @@ void Room::addPlayer(ServerPlayer *player)
|
|||
// Second, let the player enter room and add other players
|
||||
jsonData = QJsonArray();
|
||||
jsonData << this->capacity;
|
||||
jsonData << this->timeout;
|
||||
player->doNotify("EnterRoom", QJsonDocument(jsonData).toJson());
|
||||
|
||||
foreach (ServerPlayer *p, getOtherPlayers(player)) {
|
||||
|
@ -111,6 +114,12 @@ void Room::addPlayer(ServerPlayer *player)
|
|||
player->doNotify("AddPlayer", QJsonDocument(jsonData).toJson());
|
||||
}
|
||||
|
||||
if (this->owner != nullptr) {
|
||||
jsonData = QJsonArray();
|
||||
jsonData << this->owner->getId();
|
||||
player->doNotify("RoomOwner", QJsonDocument(jsonData).toJson());
|
||||
}
|
||||
|
||||
if (isFull())
|
||||
start();
|
||||
}
|
||||
|
@ -150,11 +159,17 @@ QList<ServerPlayer *> Room::getOtherPlayers(ServerPlayer* expect) const
|
|||
|
||||
ServerPlayer *Room::findPlayer(int id) const
|
||||
{
|
||||
foreach (ServerPlayer *p, players) {
|
||||
if (p->getId() == id)
|
||||
return p;
|
||||
}
|
||||
return nullptr;
|
||||
return server->findPlayer(id);
|
||||
}
|
||||
|
||||
int Room::getTimeout() const
|
||||
{
|
||||
return timeout;
|
||||
}
|
||||
|
||||
void Room::setTimeout(int timeout)
|
||||
{
|
||||
this->timeout = timeout;
|
||||
}
|
||||
|
||||
bool Room::isStarted() const
|
||||
|
|
|
@ -31,6 +31,9 @@ public:
|
|||
QList<ServerPlayer *> getOtherPlayers(ServerPlayer *expect) const;
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
|
||||
int getTimeout() const;
|
||||
void setTimeout(int timeout);
|
||||
|
||||
bool isStarted() const;
|
||||
// ====================================}
|
||||
|
||||
|
@ -64,6 +67,8 @@ private:
|
|||
ServerPlayer *owner; // who created this room?
|
||||
QList<ServerPlayer *> players;
|
||||
bool gameStarted;
|
||||
|
||||
int timeout;
|
||||
};
|
||||
|
||||
#endif // _ROOM_H
|
||||
|
|
|
@ -8,7 +8,7 @@ ServerPlayer::ServerPlayer(Room *room)
|
|||
{
|
||||
socket = nullptr;
|
||||
router = new Router(this, socket, Router::TYPE_SERVER);
|
||||
|
||||
setState(Player::Online);
|
||||
this->room = room;
|
||||
server = room->getServer();
|
||||
}
|
||||
|
@ -68,6 +68,16 @@ void ServerPlayer::doRequest(const QString& command, const QString& jsonData, in
|
|||
router->request(type, command, jsonData, timeout);
|
||||
}
|
||||
|
||||
QString ServerPlayer::waitForReply()
|
||||
{
|
||||
return router->waitForReply();
|
||||
}
|
||||
|
||||
QString ServerPlayer::waitForReply(int timeout)
|
||||
{
|
||||
return router->waitForReply(timeout);
|
||||
}
|
||||
|
||||
void ServerPlayer::doNotify(const QString& command, const QString& jsonData)
|
||||
{
|
||||
int type = Router::TYPE_NOTIFICATION | Router::SRC_SERVER | Router::DEST_CLIENT;
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
|
||||
void doRequest(const QString &command,
|
||||
const QString &jsonData, int timeout = -1);
|
||||
QString waitForReply(int timeout);
|
||||
QString waitForReply();
|
||||
void doNotify(const QString &command, const QString &jsonData);
|
||||
|
||||
void prepareForRequest(const QString &command,
|
||||
|
|
|
@ -46,7 +46,9 @@ public:
|
|||
void speak(const QString &message);
|
||||
|
||||
void doRequest(const QString &command,
|
||||
const QString &json_data, int timeout = -1);
|
||||
const QString &json_data, int timeout);
|
||||
QString waitForReply();
|
||||
QString waitForReply(int timeout);
|
||||
void doNotify(const QString &command, const QString &json_data);
|
||||
|
||||
void prepareForRequest(const QString &command, const QString &data);
|
||||
|
|
|
@ -34,3 +34,15 @@ public:
|
|||
%template(PlayerList) QList<const Player *>;
|
||||
%template(IntList) QList<int>;
|
||||
%template(BoolList) QList<bool>;
|
||||
|
||||
%native(GetMicroSecond) int GetMicroSecond(lua_State *L);
|
||||
%{
|
||||
#include <sys/time.h>
|
||||
static int GetMicroSecond(lua_State *L) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, nullptr);
|
||||
long microsecond = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
lua_pushnumber(L, microsecond);
|
||||
return 1;
|
||||
}
|
||||
%}
|
||||
|
|
|
@ -71,6 +71,8 @@ public:
|
|||
QList<ServerPlayer *> getPlayers() const;
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
|
||||
int getTimeout() const;
|
||||
|
||||
bool isStarted() const;
|
||||
// ====================================}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user