Room (#4)
* Run room in lua * handle offline player * Better toast and other * delete useless stuff * todo: edit profile * use pch
This commit is contained in:
parent
3dc95ebc49
commit
a67175f8eb
|
@ -17,7 +17,6 @@ set(CMAKE_CXX_STANDARD 11)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(REQUIRED_QT_VERSION "5.15.2")
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/)
|
||||
include_directories(include/lua)
|
||||
include_directories(include/sqlite3)
|
||||
include_directories(src)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# FreeKill 的数据库(TODO)
|
||||
# FreeKill 的数据库
|
||||
|
||||
> [dev](./index.md) > 数据库
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ $ ./FreeKill -s <port>
|
|||
1. 检查IP是否被封禁。 // TODO: 数据库
|
||||
2. 检查客户端的延迟是否小于30秒。
|
||||
3. 在网络检测环节,若客户端网速达标的话,客户端应该会发回一个字符串。这个字符串保存着用户的用户名和密码,服务端检查这个字符串是否合法。
|
||||
4. 上述检查都通过后,重连(TODO)
|
||||
4. 上述检查都通过后,重连(TODO:)
|
||||
5. 不要重连的话,服务端便为新连接新建一个`ServerPlayer`对象,并将其添加到大厅中。
|
||||
|
||||
___
|
||||
|
@ -78,6 +78,8 @@ ___
|
|||
|
||||
对于情况4,因为游戏已经开始,所以不能直接删除玩家,需要把玩家的状态设为“离线”并继续游戏。在游戏结束后,若玩家仍未重连,则按情况2、3处理。
|
||||
|
||||
> Note: 这部分处理见于ServerPlayer类的析构函数。
|
||||
|
||||
___
|
||||
|
||||
## 断线重连(TODO)
|
||||
|
|
|
@ -17,5 +17,23 @@ function Client:initialize()
|
|||
end
|
||||
end
|
||||
|
||||
freekill.client_callback["Setup"] = function(jsonData)
|
||||
-- jsonData: [ int id, string screenName, string avatar ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, name, avatar = data[1], data[2], data[3]
|
||||
local self = freekill.Self
|
||||
self:setId(id)
|
||||
self:setScreenName(name)
|
||||
self:setAvatar(avatar)
|
||||
end
|
||||
|
||||
freekill.client_callback["AddPlayer"] = function(jsonData)
|
||||
-- jsonData: [ int id, string screenName, string avatar ]
|
||||
-- when other player enter the room, we create clientplayer(C and lua) for them
|
||||
local data = json.decode(jsonData)
|
||||
local id, name, avatar = data[1], data[2], data[3]
|
||||
ClientInstance:notifyUI("AddPlayer", json.encode({ name, avatar }))
|
||||
end
|
||||
|
||||
-- Create ClientInstance (used by Lua)
|
||||
ClientInstance = Client:new()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
local Player = class("Skill")
|
||||
local Player = class("Player")
|
||||
|
||||
function Player:initialize()
|
||||
self.hp = nil
|
||||
|
@ -25,3 +25,5 @@ function Player:setHp(maxHp, initialHp)
|
|||
self.maxHp = maxHp
|
||||
self.hp = initialHp or maxHp
|
||||
end
|
||||
|
||||
return Player
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
-- the iterator of QList object
|
||||
local qlist_iterator = function(list, n)
|
||||
if n < list:length() - 1 then
|
||||
return n + 1, list:at(n + 1) -- the next element of list
|
||||
end
|
||||
end
|
||||
|
||||
function freekill.qlist(list)
|
||||
return qlist_iterator, list, -1
|
||||
end
|
||||
|
||||
function table:contains(element)
|
||||
if #self == 0 or type(self[1]) ~= type(element) then return false end
|
||||
for _, e in ipairs(self) do
|
||||
if e == element then return true end
|
||||
end
|
||||
end
|
||||
|
||||
function table:insertTable(list)
|
||||
for _, e in ipairs(list) do
|
||||
table.insert(self, e)
|
||||
end
|
||||
end
|
||||
|
||||
Sql = {
|
||||
open = function(filename)
|
||||
return freekill.OpenDatabase(filename)
|
||||
end,
|
||||
close = function(db)
|
||||
freekill.CloseDatabase(db)
|
||||
end,
|
||||
exec = function(db, sql)
|
||||
freekill.ExecSQL(db, sql)
|
||||
end,
|
||||
exec_select = function(db, sql)
|
||||
return json.decode(freekill.SelectFromDb(db, sql))
|
||||
end,
|
||||
}
|
||||
|
||||
function table:removeOne(element)
|
||||
if #self == 0 or type(self[1]) ~= type(element) then return false end
|
||||
|
||||
for i = 1, #self do
|
||||
if self[i] == element then
|
||||
table.remove(self, i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local Util = class("Util")
|
||||
|
||||
function Util.static:createEnum(tbl, index)
|
||||
assert(type(tbl) == "table")
|
||||
local enumtbl = {}
|
||||
local enumindex = index or 0
|
||||
for i, v in ipairs(tbl) do
|
||||
enumtbl[v] = enumindex + i
|
||||
end
|
||||
return enumtbl
|
||||
end
|
||||
|
||||
return Util
|
|
@ -7,6 +7,7 @@ package.path = package.path .. ";./lua/lib/?.lua"
|
|||
-- load libraries
|
||||
class = require "middleclass"
|
||||
json = require "json"
|
||||
require "sha256"
|
||||
Util = require "util"
|
||||
|
||||
DebugMode = true
|
||||
|
@ -22,5 +23,6 @@ Sanguosha = require "engine"
|
|||
General = require "general"
|
||||
Card = require "card"
|
||||
Skill = require "skill"
|
||||
Player = require "player"
|
||||
|
||||
-- load packages
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
-- From http://pastebin.com/gsFrNjbt linked from http://www.computercraft.info/forums2/index.php?/topic/8169-sha-256-in-pure-lua/
|
||||
|
||||
--
|
||||
-- Adaptation of the Secure Hashing Algorithm (SHA-244/256)
|
||||
-- Found Here: http://lua-users.org/wiki/SecureHashAlgorithm
|
||||
--
|
||||
-- Using an adapted version of the bit library
|
||||
-- Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua
|
||||
--
|
||||
|
||||
local MOD = 2^32
|
||||
local MODM = MOD-1
|
||||
|
||||
local function memoize(f)
|
||||
local mt = {}
|
||||
local t = setmetatable({}, mt)
|
||||
function mt:__index(k)
|
||||
local v = f(k)
|
||||
t[k] = v
|
||||
return v
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function make_bitop_uncached(t, m)
|
||||
local function bitop(a, b)
|
||||
local res,p = 0,1
|
||||
while a ~= 0 and b ~= 0 do
|
||||
local am, bm = a % m, b % m
|
||||
res = res + t[am][bm] * p
|
||||
a = (a - am) / m
|
||||
b = (b - bm) / m
|
||||
p = p*m
|
||||
end
|
||||
res = res + (a + b) * p
|
||||
return res
|
||||
end
|
||||
return bitop
|
||||
end
|
||||
|
||||
local function make_bitop(t)
|
||||
local op1 = make_bitop_uncached(t,2^1)
|
||||
local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)
|
||||
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
|
||||
end
|
||||
|
||||
local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})
|
||||
|
||||
local function bxor(a, b, c, ...)
|
||||
local z = nil
|
||||
if b then
|
||||
a = a % MOD
|
||||
b = b % MOD
|
||||
z = bxor1(a, b)
|
||||
if c then z = bxor(z, c, ...) end
|
||||
return z
|
||||
elseif a then return a % MOD
|
||||
else return 0 end
|
||||
end
|
||||
|
||||
local function band(a, b, c, ...)
|
||||
local z
|
||||
if b then
|
||||
a = a % MOD
|
||||
b = b % MOD
|
||||
z = ((a + b) - bxor1(a,b)) / 2
|
||||
if c then z = bit32_band(z, c, ...) end
|
||||
return z
|
||||
elseif a then return a % MOD
|
||||
else return MODM end
|
||||
end
|
||||
|
||||
local function bnot(x) return (-1 - x) % MOD end
|
||||
|
||||
local function rshift1(a, disp)
|
||||
if disp < 0 then return lshift(a,-disp) end
|
||||
return math.floor(a % 2 ^ 32 / 2 ^ disp)
|
||||
end
|
||||
|
||||
local function rshift(x, disp)
|
||||
if disp > 31 or disp < -31 then return 0 end
|
||||
return rshift1(x % MOD, disp)
|
||||
end
|
||||
|
||||
local function lshift(a, disp)
|
||||
if disp < 0 then return rshift(a,-disp) end
|
||||
return (a * 2 ^ disp) % 2 ^ 32
|
||||
end
|
||||
|
||||
local function rrotate(x, disp)
|
||||
x = x % MOD
|
||||
disp = disp % 32
|
||||
local low = band(x, 2 ^ disp - 1)
|
||||
return rshift(x, disp) + lshift(low, 32 - disp)
|
||||
end
|
||||
|
||||
local k = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||
}
|
||||
|
||||
local function str2hexa(s)
|
||||
return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end))
|
||||
end
|
||||
|
||||
local function num2s(l, n)
|
||||
local s = ""
|
||||
for i = 1, n do
|
||||
local rem = l % 256
|
||||
s = string.char(rem) .. s
|
||||
l = (l - rem) / 256
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
local function s232num(s, i)
|
||||
local n = 0
|
||||
for i = i, i + 3 do n = n*256 + string.byte(s, i) end
|
||||
return n
|
||||
end
|
||||
|
||||
local function preproc(msg, len)
|
||||
local extra = 64 - ((len + 9) % 64)
|
||||
len = num2s(8 * len, 8)
|
||||
msg = msg .. "\128" .. string.rep("\0", extra) .. len
|
||||
assert(#msg % 64 == 0)
|
||||
return msg
|
||||
end
|
||||
|
||||
local function initH256(H)
|
||||
H[1] = 0x6a09e667
|
||||
H[2] = 0xbb67ae85
|
||||
H[3] = 0x3c6ef372
|
||||
H[4] = 0xa54ff53a
|
||||
H[5] = 0x510e527f
|
||||
H[6] = 0x9b05688c
|
||||
H[7] = 0x1f83d9ab
|
||||
H[8] = 0x5be0cd19
|
||||
return H
|
||||
end
|
||||
|
||||
local function digestblock(msg, i, H)
|
||||
local w = {}
|
||||
for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end
|
||||
for j = 17, 64 do
|
||||
local v = w[j - 15]
|
||||
local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))
|
||||
v = w[j - 2]
|
||||
w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))
|
||||
end
|
||||
|
||||
local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]
|
||||
for i = 1, 64 do
|
||||
local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))
|
||||
local maj = bxor(band(a, b), band(a, c), band(b, c))
|
||||
local t2 = s0 + maj
|
||||
local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))
|
||||
local ch = bxor (band(e, f), band(bnot(e), g))
|
||||
local t1 = h + s1 + ch + k[i] + w[i]
|
||||
h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2
|
||||
end
|
||||
|
||||
H[1] = band(H[1] + a)
|
||||
H[2] = band(H[2] + b)
|
||||
H[3] = band(H[3] + c)
|
||||
H[4] = band(H[4] + d)
|
||||
H[5] = band(H[5] + e)
|
||||
H[6] = band(H[6] + f)
|
||||
H[7] = band(H[7] + g)
|
||||
H[8] = band(H[8] + h)
|
||||
end
|
||||
|
||||
-- Made this global
|
||||
function sha256(msg)
|
||||
msg = preproc(msg, #msg)
|
||||
local H = initH256({})
|
||||
for i = 1, #msg, 64 do digestblock(msg, i, H) end
|
||||
return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..
|
||||
num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))
|
||||
end
|
||||
|
|
@ -1,18 +1,34 @@
|
|||
Room = class("Room")
|
||||
local Room = class("Room")
|
||||
|
||||
-- Just same as "static int roomId" in cpp
|
||||
-- However id 0 is for lobby, so we start at 1
|
||||
local roomId = 1
|
||||
|
||||
function Room:initialize()
|
||||
self.id = roomId
|
||||
roomId = roomId + 1
|
||||
self.room = ServerInstace:findRoom(self.id)
|
||||
function Room:initialize(_room)
|
||||
self.room = _room
|
||||
self.players = {}
|
||||
self.gameFinished = false
|
||||
end
|
||||
|
||||
function Room:getCProperties()
|
||||
self.name = self.room:getName()
|
||||
self.capacity = self.room:getCapacity()
|
||||
-- When this function returns, the Room(C++) thread stopped.
|
||||
function Room:run()
|
||||
print 'Room is running!'
|
||||
-- First, create players(Lua) from ServerPlayer(C++)
|
||||
for _, p in freekill.qlist(self.room:getPlayers()) do
|
||||
local player = ServerPlayer:new(p)
|
||||
print(player:getId())
|
||||
table.insert(self.players, p)
|
||||
end
|
||||
-- Second, assign role and adjust seats
|
||||
-- Then let's choose general and start the game!
|
||||
end
|
||||
|
||||
function Room:startGame()
|
||||
while true do
|
||||
if self.gameFinished then break end
|
||||
end
|
||||
end
|
||||
|
||||
function Room:gameOver()
|
||||
self.gameFinished = true
|
||||
-- dosomething
|
||||
self.room:gameOver()
|
||||
end
|
||||
|
||||
return Room
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
local Server = class("Server")
|
||||
Server = class('Server')
|
||||
package.path = package.path .. ';./lua/server/?.lua'
|
||||
Room = require "room"
|
||||
ServerPlayer = require "serverplayer"
|
||||
|
||||
freekill.server_callback = {}
|
||||
|
||||
|
@ -13,12 +16,21 @@ function Server:initialize()
|
|||
end
|
||||
end
|
||||
|
||||
self.rooms = {} -- hashtable: uid --> room
|
||||
self.players = {} -- hashtable: uid --> splayer
|
||||
end
|
||||
self.server.startRoom = function(_self, _room)
|
||||
local room = Room:new(_room)
|
||||
room.server = self
|
||||
table.insert(self.rooms, room)
|
||||
|
||||
function Server:createRoom(owner, roomName, capacity)
|
||||
room:run()
|
||||
|
||||
-- If room.run returns, the game is over and lua room
|
||||
-- should be destoried now.
|
||||
-- This behavior does not affect C++ Room.
|
||||
table.removeOne(self.rooms, room)
|
||||
end
|
||||
|
||||
self.rooms = {}
|
||||
self.players = {}
|
||||
end
|
||||
|
||||
freekill.server_callback["CreateRoom"] = function(jsonData)
|
||||
|
@ -28,7 +40,6 @@ freekill.server_callback["CreateRoom"] = function(jsonData)
|
|||
local roomName = data[2]
|
||||
local capacity = data[3]
|
||||
freekill.ServerInstance:createRoom(owner, roomName, capacity)
|
||||
ServerInstance:createRoom()
|
||||
end
|
||||
|
||||
freekill.server_callback["EnterRoom"] = function(jsonData)
|
||||
|
@ -57,4 +68,13 @@ freekill.server_callback["DoLuaScript"] = function(jsonData)
|
|||
assert(load(data[2]))()
|
||||
end
|
||||
|
||||
freekill.server_callback["PlayerStateChanged"] = function(jsonData)
|
||||
-- jsonData: [ int uid, string stateString ]
|
||||
-- note: this function is not called by Router.
|
||||
local data = json.decode(jsonData)
|
||||
local id = data[1]
|
||||
local stateString = data[2]
|
||||
ServerInstance.players[id].state = stateString
|
||||
end
|
||||
|
||||
ServerInstance = Server:new()
|
||||
|
|
|
@ -1 +1,12 @@
|
|||
local ServerPlayer = Player:subclass("ServerPlayer")
|
||||
|
||||
function ServerPlayer:initialize(_self)
|
||||
Player.initialize(self)
|
||||
self.serverplayer = _self
|
||||
end
|
||||
|
||||
function ServerPlayer:getId()
|
||||
return self.serverplayer:getId()
|
||||
end
|
||||
|
||||
return ServerPlayer
|
||||
|
|
26
lua/util.lua
26
lua/util.lua
|
@ -1,26 +0,0 @@
|
|||
function table:contains(element)
|
||||
if #self == 0 or type(self[1]) ~= type(element) then return false end
|
||||
for _, e in ipairs(self) do
|
||||
if e == element then return true end
|
||||
end
|
||||
end
|
||||
|
||||
function table:insertTable(list)
|
||||
for _, e in ipairs(list) do
|
||||
table.insert(self, e)
|
||||
end
|
||||
end
|
||||
|
||||
local Util = class("Util")
|
||||
|
||||
function Util.static:createEnum(tbl, index)
|
||||
assert(type(tbl) == "table")
|
||||
local enumtbl = {}
|
||||
local enumindex = index or 0
|
||||
for i, v in ipairs(tbl) do
|
||||
enumtbl[v] = enumindex + i
|
||||
end
|
||||
return enumtbl
|
||||
end
|
||||
|
||||
return Util
|
10
qml/Logic.js
10
qml/Logic.js
|
@ -1,17 +1,23 @@
|
|||
var callbacks = {};
|
||||
|
||||
callbacks["NetworkDelayTest"] = function(jsonData) {
|
||||
Backend.notifyServer("Setup", JSON.stringify([
|
||||
ClientInstance.notifyServer("Setup", JSON.stringify([
|
||||
config.screenName,
|
||||
config.password
|
||||
]));
|
||||
}
|
||||
|
||||
callbacks["ErrorMsg"] = function(jsonData) {
|
||||
toast.show(jsonData);
|
||||
toast.show(jsonData, 5000);
|
||||
mainWindow.busy = false;
|
||||
}
|
||||
|
||||
callbacks["BackToStart"] = function(jsonData) {
|
||||
while (mainStack.depth > 1) {
|
||||
mainStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
callbacks["EnterLobby"] = function(jsonData) {
|
||||
// depth == 1 means the lobby page is not present in mainStack
|
||||
if (mainStack.depth === 1) {
|
||||
|
|
|
@ -45,7 +45,7 @@ Item {
|
|||
onClicked: {
|
||||
mainWindow.busy = true;
|
||||
mainStack.pop();
|
||||
Backend.notifyServer(
|
||||
ClientInstance.notifyServer(
|
||||
"CreateRoom",
|
||||
JSON.stringify([roomName.text, playerNum.value])
|
||||
);
|
||||
|
|
|
@ -33,7 +33,6 @@ Item {
|
|||
config.screenName = screenNameEdit.text;
|
||||
config.password = passwordEdit.text;
|
||||
mainWindow.busy = true;
|
||||
toast.show("Connecting to host...");
|
||||
Backend.joinServer(server_addr.text);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +42,6 @@ Item {
|
|||
config.screenName = screenNameEdit.text;
|
||||
config.password = passwordEdit.text;
|
||||
mainWindow.busy = true;
|
||||
toast.show("Connecting to host...");
|
||||
Backend.startServer(9527);
|
||||
Backend.joinServer("127.0.0.1");
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ Item {
|
|||
onExited: { parent.color = "black" }
|
||||
onClicked: {
|
||||
mainWindow.busy = true;
|
||||
Backend.notifyServer(
|
||||
ClientInstance.notifyServer(
|
||||
"EnterRoom",
|
||||
JSON.stringify([roomId])
|
||||
);
|
||||
|
@ -86,8 +86,11 @@ Item {
|
|||
}
|
||||
|
||||
ColumnLayout {
|
||||
Text {
|
||||
text: "Avatar"
|
||||
Button {
|
||||
text: "Edit Profile"
|
||||
onClicked: {
|
||||
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Create Room"
|
||||
|
|
|
@ -11,6 +11,9 @@ Item {
|
|||
property int playerNum: 0
|
||||
property var dashboardModel
|
||||
|
||||
property bool isOwner: false
|
||||
property bool isStarted: false
|
||||
|
||||
// tmp
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
|
@ -20,9 +23,14 @@ Item {
|
|||
text: "quit"
|
||||
anchors.bottom: parent.bottom
|
||||
onClicked: {
|
||||
Backend.notifyServer("QuitRoom", "[]");
|
||||
ClientInstance.notifyServer("QuitRoom", "[]");
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "start game"
|
||||
visible: isOwner && !isStarted
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
// For debugging
|
||||
RowLayout {
|
||||
|
@ -36,7 +44,7 @@ Item {
|
|||
Button {
|
||||
text: "DoLuaScript"
|
||||
onClicked: {
|
||||
Backend.notifyServer("DoLuaScript", JSON.stringify([lua.text]));
|
||||
ClientInstance.notifyServer("DoLuaScript", JSON.stringify([lua.text]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +82,7 @@ Item {
|
|||
faceturned: modelData.faceturned
|
||||
chained: modelData.chained
|
||||
drank: modelData.drank
|
||||
isOwner: modelData.isOwner
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,14 +122,15 @@ Item {
|
|||
self.faceturned: dashboardModel.faceturned
|
||||
self.chained: dashboardModel.chained
|
||||
self.drank: dashboardModel.drank
|
||||
self.isOwner: dashboardModel.isOwner
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
toast.show("Sucesessfully entered room.");
|
||||
|
||||
dashboardModel = {
|
||||
general: "liubei",
|
||||
screenName: config.screenName,
|
||||
general: Self.avatar,
|
||||
screenName: Self.screenName,
|
||||
role: "unknown",
|
||||
kingdom: "qun",
|
||||
netstate: "online",
|
||||
|
@ -131,7 +141,8 @@ Item {
|
|||
dying: false,
|
||||
faceturned: false,
|
||||
chained: false,
|
||||
drank: false
|
||||
drank: false,
|
||||
isOwner: false
|
||||
}
|
||||
|
||||
playerNum = config.roomCapacity;
|
||||
|
@ -151,7 +162,8 @@ Item {
|
|||
dying: false,
|
||||
faceturned: false,
|
||||
chained: false,
|
||||
drank: false
|
||||
drank: false,
|
||||
isOwner: false
|
||||
});
|
||||
}
|
||||
photoModel = photoModel; // Force the Repeater reload
|
||||
|
|
|
@ -22,6 +22,7 @@ Item {
|
|||
property bool faceturned: false
|
||||
property bool chained: false
|
||||
property bool drank: false
|
||||
property bool isOwner: false
|
||||
|
||||
Image {
|
||||
id: back
|
||||
|
|
|
@ -68,7 +68,8 @@ callbacks["AddPlayer"] = function(jsonData) {
|
|||
dying: false,
|
||||
faceturned: false,
|
||||
chained: false,
|
||||
drank: false
|
||||
drank: false,
|
||||
isOwner: false
|
||||
};
|
||||
photoModel = photoModel;
|
||||
arrangePhotos();
|
||||
|
@ -95,7 +96,8 @@ callbacks["RemovePlayer"] = function(jsonData) {
|
|||
dying: false,
|
||||
faceturned: false,
|
||||
chained: false,
|
||||
drank: false
|
||||
drank: false,
|
||||
isOwner: false
|
||||
};
|
||||
photoModel = photoModel;
|
||||
arrangePhotos();
|
||||
|
@ -103,3 +105,10 @@ callbacks["RemovePlayer"] = function(jsonData) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
callbacks["RoomOwner"] = function(jsonData) {
|
||||
// jsonData: int uid of the owner
|
||||
toast.show(J)
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
Rectangle {
|
||||
function show(text, duration) {
|
||||
message.text = text;
|
||||
time = Math.max(duration, 2 * fadeTime);
|
||||
animation.start();
|
||||
}
|
||||
|
||||
id: root
|
||||
|
||||
readonly property real defaultTime: 3000
|
||||
property real time: defaultTime
|
||||
readonly property real fadeTime: 300
|
||||
|
||||
anchors.horizontalCenter: parent != null ? parent.horizontalCenter : undefined
|
||||
height: message.height + 20
|
||||
width: message.width + 40
|
||||
radius: 16
|
||||
|
||||
opacity: 0
|
||||
color: "#F2808A87"
|
||||
|
||||
Text {
|
||||
id: message
|
||||
color: "white"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
id: animation
|
||||
running: false
|
||||
|
||||
|
||||
NumberAnimation {
|
||||
to: .9
|
||||
duration: fadeTime
|
||||
}
|
||||
|
||||
PauseAnimation {
|
||||
duration: time - 2 * fadeTime
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
to: 0
|
||||
duration: fadeTime
|
||||
}
|
||||
|
||||
onRunningChanged: {
|
||||
if (!running) {
|
||||
toast.model.remove(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
import QtQuick 2.15
|
||||
|
||||
// copy from https://gist.github.com/jonmcclung/bae669101d17b103e94790341301c129
|
||||
// and modified some code
|
||||
ListView {
|
||||
function show(text, duration) {
|
||||
if (duration === undefined) {
|
||||
duration = 3000;
|
||||
}
|
||||
model.insert(0, {text: text, duration: duration});
|
||||
}
|
||||
|
||||
id: root
|
||||
|
||||
z: Infinity
|
||||
spacing: 5
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: 10
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
|
||||
interactive: false
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
properties: "y"
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Toast {
|
||||
Component.onCompleted: {
|
||||
show(text, duration);
|
||||
}
|
||||
}
|
||||
|
||||
model: ListModel {id: model}
|
||||
}
|
40
qml/main.qml
40
qml/main.qml
|
@ -49,46 +49,8 @@ Window {
|
|||
id: config
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
ToastManager {
|
||||
id: toast
|
||||
opacity: 0
|
||||
z: 998
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: parent.height * 0.8
|
||||
radius: 16
|
||||
color: "#F2808A87"
|
||||
height: toast_text.height + 20
|
||||
width: toast_text.width + 40
|
||||
Text {
|
||||
id: toast_text
|
||||
text: "FreeKill"
|
||||
anchors.centerIn: parent
|
||||
color: "white"
|
||||
}
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 240
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
SequentialAnimation {
|
||||
id: keepAnim
|
||||
running: toast.opacity == 1
|
||||
PauseAnimation {
|
||||
duration: 2800
|
||||
}
|
||||
|
||||
ScriptAction {
|
||||
script: {
|
||||
toast.opacity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function show(text) {
|
||||
opacity = 1;
|
||||
toast_text.text = text;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
set(freekill_SRCS
|
||||
"main.cpp"
|
||||
"core/player.cpp"
|
||||
"core/global.cpp"
|
||||
"core/util.cpp"
|
||||
"network/server_socket.cpp"
|
||||
"network/client_socket.cpp"
|
||||
"network/router.cpp"
|
||||
"server/server.cpp"
|
||||
"server/serverplayer.cpp"
|
||||
"server/room.cpp"
|
||||
"server/gamelogic.cpp"
|
||||
"client/client.cpp"
|
||||
"client/clientplayer.cpp"
|
||||
"ui/qmlbackend.cpp"
|
||||
|
@ -16,7 +15,7 @@ set(freekill_SRCS
|
|||
)
|
||||
|
||||
set(freekill_HEADERS
|
||||
"core/global.h"
|
||||
"core/util.h"
|
||||
"core/player.h"
|
||||
"network/server_socket.h"
|
||||
"network/client_socket.h"
|
||||
|
@ -24,7 +23,6 @@ set(freekill_HEADERS
|
|||
"server/server.h"
|
||||
"server/serverplayer.h"
|
||||
"server/room.h"
|
||||
"server/gamelogic.h"
|
||||
"client/client.h"
|
||||
"client/clientplayer.h"
|
||||
"ui/qmlbackend.h"
|
||||
|
@ -40,6 +38,7 @@ endif ()
|
|||
|
||||
source_group("Include" FILES ${freekill_HEADERS})
|
||||
add_executable(FreeKill ${freekill_SRCS})
|
||||
target_precompile_headers(FreeKill PRIVATE "pch.h")
|
||||
target_link_libraries(FreeKill ${LUA_LIB} ${SQLITE3_LIB} Qt5::Qml Qt5::Gui Qt5::Network Qt5::Multimedia)
|
||||
file(GLOB SWIG_FILES "${PROJECT_SOURCE_DIR}/src/swig/*.i")
|
||||
add_custom_command(
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "client.h"
|
||||
#include "client_socket.h"
|
||||
#include "clientplayer.h"
|
||||
#include "qmlbackend.h"
|
||||
#include "util.h"
|
||||
|
||||
Client *ClientInstance;
|
||||
ClientPlayer *Self;
|
||||
|
@ -9,7 +11,10 @@ Client::Client(QObject* parent)
|
|||
: QObject(parent), callback(0)
|
||||
{
|
||||
ClientInstance = this;
|
||||
Self = nullptr;
|
||||
Self = new ClientPlayer(0, this);
|
||||
QQmlApplicationEngine *engine = Backend->getEngine();
|
||||
engine->rootContext()->setContextProperty("ClientInstance", ClientInstance);
|
||||
engine->rootContext()->setContextProperty("Self", Self);
|
||||
|
||||
ClientSocket *socket = new ClientSocket;
|
||||
connect(socket, &ClientSocket::error_message, this, &Client::error_message);
|
||||
|
@ -33,12 +38,6 @@ void Client::connectToHost(const QHostAddress& server, ushort port)
|
|||
router->getSocket()->connectToHost(server, port);
|
||||
}
|
||||
|
||||
void Client::requestServer(const QString& command, const QString& jsonData, int timeout)
|
||||
{
|
||||
int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER;
|
||||
router->request(type, command, jsonData, timeout);
|
||||
}
|
||||
|
||||
void Client::replyToServer(const QString& command, const QString& jsonData)
|
||||
{
|
||||
int type = Router::TYPE_REPLY | Router::SRC_CLIENT | Router::DEST_SERVER;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#ifndef _CLIENT_H
|
||||
#define _CLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <lua.hpp>
|
||||
#include "router.h"
|
||||
#include "clientplayer.h"
|
||||
#include "global.h"
|
||||
|
||||
class Client : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -15,16 +12,10 @@ public:
|
|||
|
||||
void connectToHost(const QHostAddress &server, ushort port);
|
||||
|
||||
// TODO: database of the server
|
||||
// void signup
|
||||
// void login
|
||||
Q_INVOKABLE void replyToServer(const QString &command, const QString &jsonData);
|
||||
Q_INVOKABLE void notifyServer(const QString &command, const QString &jsonData);
|
||||
|
||||
void requestServer(const QString &command,
|
||||
const QString &jsonData, int timeout = -1);
|
||||
void replyToServer(const QString &command, const QString &jsonData);
|
||||
void notifyServer(const QString &command, const QString &jsonData);
|
||||
|
||||
void callLua(const QString &command, const QString &jsonData);
|
||||
Q_INVOKABLE void callLua(const QString &command, const QString &jsonData);
|
||||
LuaFunction callback;
|
||||
|
||||
signals:
|
||||
|
@ -32,7 +23,7 @@ signals:
|
|||
|
||||
private:
|
||||
Router *router;
|
||||
QMap<uint, ClientPlayer *> players;
|
||||
QMap<int, ClientPlayer *> players;
|
||||
|
||||
lua_State *L;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "clientplayer.h"
|
||||
|
||||
ClientPlayer::ClientPlayer(uint id, QObject* parent)
|
||||
ClientPlayer::ClientPlayer(int id, QObject* parent)
|
||||
: Player(parent)
|
||||
{
|
||||
setId(id);
|
||||
|
|
|
@ -5,8 +5,13 @@
|
|||
|
||||
class ClientPlayer : public Player {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int id READ getId)
|
||||
Q_PROPERTY(QString screenName READ getScreenName WRITE setScreenName)
|
||||
Q_PROPERTY(QString avatar READ getAvatar WRITE setAvatar)
|
||||
|
||||
public:
|
||||
ClientPlayer(uint id, QObject *parent = nullptr);
|
||||
ClientPlayer(int id, QObject *parent = nullptr);
|
||||
~ClientPlayer();
|
||||
|
||||
private:
|
||||
|
|
|
@ -12,12 +12,12 @@ Player::~Player()
|
|||
{
|
||||
}
|
||||
|
||||
uint Player::getId() const
|
||||
int Player::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void Player::setId(uint id)
|
||||
void Player::setId(int id)
|
||||
{
|
||||
this->id = id;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef _PLAYER_H
|
||||
#define _PLAYER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
// Common part of ServerPlayer and ClientPlayer
|
||||
// dont initialize it directly
|
||||
class Player : public QObject {
|
||||
|
@ -19,8 +17,8 @@ public:
|
|||
explicit Player(QObject *parent = nullptr);
|
||||
~Player();
|
||||
|
||||
uint getId() const;
|
||||
void setId(uint id);
|
||||
int getId() const;
|
||||
void setId(int id);
|
||||
|
||||
QString getScreenName() const;
|
||||
void setScreenName(const QString &name);
|
||||
|
@ -43,7 +41,7 @@ signals:
|
|||
void readyChanged();
|
||||
|
||||
private:
|
||||
uint id;
|
||||
int id;
|
||||
QString screenName; // screenName should not be same.
|
||||
QString avatar;
|
||||
State state;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "global.h"
|
||||
#include <QtCore>
|
||||
#include <QFileDevice>
|
||||
#include "util.h"
|
||||
|
||||
extern "C" {
|
||||
int luaopen_freekill(lua_State *);
|
|
@ -1,12 +1,7 @@
|
|||
#ifndef _GLOBAL_H
|
||||
#define _GLOBAL_H
|
||||
|
||||
#include <lua.hpp>
|
||||
#include <sqlite3.h>
|
||||
#include <QtCore>
|
||||
|
||||
// utilities
|
||||
typedef int LuaFunction;
|
||||
|
||||
lua_State *CreateLuaState();
|
||||
bool DoLuaScript(lua_State *L, const char *script);
|
13
src/main.cpp
13
src/main.cpp
|
@ -1,8 +1,3 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQmlContext>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDir>
|
||||
#include "qmlbackend.h"
|
||||
#include "server.h"
|
||||
|
||||
|
@ -29,16 +24,18 @@ int main(int argc, char *argv[])
|
|||
Server *server = new Server;
|
||||
if (!server->listen(QHostAddress::Any, serverPort)) {
|
||||
fprintf(stderr, "cannot listen on port %d!\n", serverPort);
|
||||
exit(1);
|
||||
app.exit(1);
|
||||
}
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
QmlBackend backend;
|
||||
backend.setEngine(&engine);
|
||||
|
||||
engine.rootContext()->setContextProperty("Backend", &backend);
|
||||
QUrl currentDir = QUrl::fromLocalFile(QDir::currentPath());
|
||||
engine.rootContext()->setContextProperty("AppPath", currentDir);
|
||||
engine.rootContext()->setContextProperty("AppPath", QUrl::fromLocalFile(QDir::currentPath()));
|
||||
#ifdef QT_DEBUG
|
||||
bool debugging = true;
|
||||
#else
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "client_socket.h"
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
|
||||
ClientSocket::ClientSocket() : socket(new QTcpSocket(this))
|
||||
{
|
||||
|
@ -92,6 +90,6 @@ void ClientSocket::raiseError(QAbstractSocket::SocketError socket_error)
|
|||
default: reason = tr("Unknow error"); break;
|
||||
}
|
||||
|
||||
emit error_message(tr("Connection failed, error code = %1\n reason:\n %2")
|
||||
emit error_message(tr("Connection failed, error code = %1\n reason: %2")
|
||||
.arg(socket_error).arg(reason));
|
||||
}
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
#ifndef _CLIENT_SOCKET_H
|
||||
#define _CLIENT_SOCKET_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QTimer>
|
||||
|
||||
class QTcpSocket;
|
||||
|
||||
class ClientSocket : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include "router.h"
|
||||
#include "client.h"
|
||||
#include "client_socket.h"
|
||||
#include "server.h"
|
||||
#include "serverplayer.h"
|
||||
|
||||
|
@ -159,7 +158,7 @@ void Router::handlePacket(const QByteArray& rawPacket)
|
|||
// Add the uid of sender to jsonData
|
||||
QJsonArray arr = QJsonDocument::fromJson(jsonData.toUtf8()).array();
|
||||
arr.prepend(
|
||||
(int)qobject_cast<ServerPlayer *>(parent())->getId()
|
||||
qobject_cast<ServerPlayer *>(parent())->getId()
|
||||
);
|
||||
ServerInstance->callLua(command, QJsonDocument(arr).toJson());
|
||||
}
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
#ifndef _ROUTER_H
|
||||
#define _ROUTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QMutex>
|
||||
#include <QVariant>
|
||||
#include <QSemaphore>
|
||||
#include "client_socket.h"
|
||||
class ClientSocket;
|
||||
|
||||
class Router : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "server_socket.h"
|
||||
#include "client_socket.h"
|
||||
#include <QTcpServer>
|
||||
|
||||
ServerSocket::ServerSocket()
|
||||
{
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
#ifndef _SERVER_SOCKET_H
|
||||
#define _SERVER_SOCKET_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
|
||||
class QTcpServer;
|
||||
class ClientSocket;
|
||||
|
||||
class ServerSocket : public QObject {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _PCH_H
|
||||
#define _PCH_H
|
||||
|
||||
// core gui qml
|
||||
#include <QtCore>
|
||||
#include <QGuiApplication>
|
||||
#include <QtQml>
|
||||
|
||||
// network
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
|
||||
// other libraries
|
||||
typedef int LuaFunction;
|
||||
#include "lua.hpp"
|
||||
#include "sqlite3.h"
|
||||
|
||||
#endif // _PCH_H
|
|
@ -1,11 +0,0 @@
|
|||
#include "gamelogic.h"
|
||||
|
||||
GameLogic::GameLogic(Room *room)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GameLogic::run()
|
||||
{
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef _GAMELOGIC_H
|
||||
#define _GAMELOGIC_H
|
||||
|
||||
#include <QThread>
|
||||
class Room;
|
||||
|
||||
// Just like the class 'RoomThread' in QSanguosha
|
||||
class GameLogic : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GameLogic(Room *room);
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
};
|
||||
|
||||
#endif // _GAMELOGIC_H
|
|
@ -1,15 +1,14 @@
|
|||
#include "room.h"
|
||||
#include "serverplayer.h"
|
||||
#include "server.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
Room::Room(Server* server)
|
||||
{
|
||||
static uint roomId = 0;
|
||||
static int roomId = 0;
|
||||
id = roomId;
|
||||
roomId++;
|
||||
this->server = server;
|
||||
gameStarted = false;
|
||||
if (!isLobby()) {
|
||||
connect(this, &Room::playerAdded, server->lobby(), &Room::removePlayer);
|
||||
connect(this, &Room::playerRemoved, server->lobby(), &Room::addPlayer);
|
||||
|
@ -27,7 +26,7 @@ Server *Room::getServer() const
|
|||
return server;
|
||||
}
|
||||
|
||||
uint Room::getId() const
|
||||
int Room::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
@ -47,12 +46,12 @@ void Room::setName(const QString &name)
|
|||
this->name = name;
|
||||
}
|
||||
|
||||
uint Room::getCapacity() const
|
||||
int Room::getCapacity() const
|
||||
{
|
||||
return capacity;
|
||||
}
|
||||
|
||||
void Room::setCapacity(uint capacity)
|
||||
void Room::setCapacity(int capacity)
|
||||
{
|
||||
this->capacity = capacity;
|
||||
}
|
||||
|
@ -75,6 +74,9 @@ ServerPlayer *Room::getOwner() const
|
|||
void Room::setOwner(ServerPlayer *owner)
|
||||
{
|
||||
this->owner = owner;
|
||||
QJsonArray jsonData;
|
||||
jsonData << owner->getId();
|
||||
owner->doNotify("RoomOwner", QJsonDocument(jsonData).toJson());
|
||||
}
|
||||
|
||||
void Room::addPlayer(ServerPlayer *player)
|
||||
|
@ -85,6 +87,7 @@ void Room::addPlayer(ServerPlayer *player)
|
|||
|
||||
// First, notify other players the new player is entering
|
||||
if (!isLobby()) {
|
||||
jsonData << player->getId();
|
||||
jsonData << player->getScreenName();
|
||||
jsonData << player->getAvatar();
|
||||
doBroadcastNotify(getPlayers(), "AddPlayer", QJsonDocument(jsonData).toJson());
|
||||
|
@ -97,15 +100,19 @@ void Room::addPlayer(ServerPlayer *player)
|
|||
} else {
|
||||
// Second, let the player enter room and add other players
|
||||
jsonData = QJsonArray();
|
||||
jsonData << (int)this->capacity;
|
||||
jsonData << this->capacity;
|
||||
player->doNotify("EnterRoom", QJsonDocument(jsonData).toJson());
|
||||
|
||||
foreach (ServerPlayer *p, getOtherPlayers(player)) {
|
||||
jsonData = QJsonArray();
|
||||
jsonData << p->getId();
|
||||
jsonData << p->getScreenName();
|
||||
jsonData << p->getAvatar();
|
||||
player->doNotify("AddPlayer", QJsonDocument(jsonData).toJson());
|
||||
}
|
||||
|
||||
if (isFull())
|
||||
start();
|
||||
}
|
||||
emit playerAdded(player);
|
||||
}
|
||||
|
@ -126,7 +133,6 @@ void Room::removePlayer(ServerPlayer *player)
|
|||
emit abandoned();
|
||||
} else if (player == owner) {
|
||||
setOwner(players.first());
|
||||
owner->doNotify("RoomOwner", "[]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +148,7 @@ QList<ServerPlayer *> Room::getOtherPlayers(ServerPlayer* expect) const
|
|||
return others;
|
||||
}
|
||||
|
||||
ServerPlayer *Room::findPlayer(uint id) const
|
||||
ServerPlayer *Room::findPlayer(int id) const
|
||||
{
|
||||
foreach (ServerPlayer *p, players) {
|
||||
if (p->getId() == id)
|
||||
|
@ -151,19 +157,9 @@ ServerPlayer *Room::findPlayer(uint id) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void Room::setGameLogic(GameLogic *logic)
|
||||
bool Room::isStarted() const
|
||||
{
|
||||
this->logic = logic;
|
||||
}
|
||||
|
||||
GameLogic *Room::getGameLogic() const
|
||||
{
|
||||
return logic;
|
||||
}
|
||||
|
||||
void Room::startGame()
|
||||
{
|
||||
// TODO
|
||||
return gameStarted;
|
||||
}
|
||||
|
||||
void Room::doRequest(const QList<ServerPlayer *> targets, int timeout)
|
||||
|
@ -184,9 +180,20 @@ void Room::doBroadcastNotify(const QList<ServerPlayer *> targets,
|
|||
}
|
||||
}
|
||||
|
||||
void Room::gameOver()
|
||||
{
|
||||
gameStarted = false;
|
||||
// clean offline players
|
||||
foreach (ServerPlayer *p, players) {
|
||||
if (p->getState() == Player::Offline) {
|
||||
p->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Room::run()
|
||||
{
|
||||
// TODO
|
||||
gameStarted = true;
|
||||
getServer()->roomStart(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#ifndef _ROOM_H
|
||||
#define _ROOM_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QList>
|
||||
class Server;
|
||||
class ServerPlayer;
|
||||
class GameLogic;
|
||||
|
||||
class Room : public QThread {
|
||||
Q_OBJECT
|
||||
|
@ -16,12 +13,12 @@ public:
|
|||
// Property reader & setter
|
||||
// ==================================={
|
||||
Server *getServer() const;
|
||||
uint getId() const;
|
||||
int getId() const;
|
||||
bool isLobby() const;
|
||||
QString getName() const;
|
||||
void setName(const QString &name);
|
||||
uint getCapacity() const;
|
||||
void setCapacity(uint capacity);
|
||||
int getCapacity() const;
|
||||
void setCapacity(int capacity);
|
||||
bool isFull() const;
|
||||
bool isAbandoned() const;
|
||||
|
||||
|
@ -32,13 +29,11 @@ public:
|
|||
void removePlayer(ServerPlayer *player);
|
||||
QList<ServerPlayer*> getPlayers() const;
|
||||
QList<ServerPlayer *> getOtherPlayers(ServerPlayer *expect) const;
|
||||
ServerPlayer *findPlayer(uint id) const;
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
|
||||
void setGameLogic(GameLogic *logic);
|
||||
GameLogic *getGameLogic() const;
|
||||
bool isStarted() const;
|
||||
// ====================================}
|
||||
|
||||
void startGame();
|
||||
void doRequest(const QList<ServerPlayer *> targets, int timeout);
|
||||
void doNotify(const QList<ServerPlayer *> targets, int timeout);
|
||||
|
||||
|
@ -48,13 +43,11 @@ public:
|
|||
const QString &jsonData
|
||||
);
|
||||
|
||||
void gameOver();
|
||||
|
||||
signals:
|
||||
void abandoned();
|
||||
|
||||
void aboutToStart();
|
||||
void started();
|
||||
void finished();
|
||||
|
||||
void playerAdded(ServerPlayer *player);
|
||||
void playerRemoved(ServerPlayer *player);
|
||||
|
||||
|
@ -63,14 +56,14 @@ protected:
|
|||
|
||||
private:
|
||||
Server *server;
|
||||
uint id; // Lobby's id is 0
|
||||
int id; // Lobby's id is 0
|
||||
QString name; // “阴间大乱斗”
|
||||
uint capacity; // by default is 5, max is 8
|
||||
int capacity; // by default is 5, max is 8
|
||||
bool m_abandoned; // If room is empty, delete it
|
||||
|
||||
ServerPlayer *owner; // who created this room?
|
||||
QList<ServerPlayer *> players;
|
||||
GameLogic *logic;
|
||||
bool gameStarted;
|
||||
};
|
||||
|
||||
#endif // _ROOM_H
|
||||
|
|
|
@ -2,13 +2,9 @@
|
|||
#include "server_socket.h"
|
||||
#include "client_socket.h"
|
||||
#include "room.h"
|
||||
#include "router.h"
|
||||
#include "serverplayer.h"
|
||||
#include "global.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QRegExp>
|
||||
#include <QCryptographicHash>
|
||||
#include "util.h"
|
||||
|
||||
Server *ServerInstance;
|
||||
|
||||
|
@ -22,8 +18,9 @@ Server::Server(QObject* parent)
|
|||
this, &Server::processNewConnection);
|
||||
|
||||
// create lobby
|
||||
createRoom(NULL, "Lobby", UINT32_MAX);
|
||||
createRoom(nullptr, "Lobby", INT32_MAX);
|
||||
connect(lobby(), &Room::playerAdded, this, &Server::updateRoomList);
|
||||
connect(lobby(), &Room::playerRemoved, this, &Server::updateRoomList);
|
||||
|
||||
L = CreateLuaState();
|
||||
DoLuaScript(L, "lua/freekill.lua");
|
||||
|
@ -45,21 +42,22 @@ bool Server::listen(const QHostAddress& address, ushort port)
|
|||
return server->listen(address, port);
|
||||
}
|
||||
|
||||
void Server::createRoom(ServerPlayer* owner, const QString &name, uint capacity)
|
||||
void Server::createRoom(ServerPlayer* owner, const QString &name, int capacity)
|
||||
{
|
||||
Room *room = new Room(this);
|
||||
connect(room, &Room::abandoned, this, &Server::onRoomAbandoned);
|
||||
room->setName(name);
|
||||
room->setCapacity(capacity);
|
||||
room->setOwner(owner);
|
||||
room->addPlayer(owner);
|
||||
if (room->isLobby())
|
||||
m_lobby = room;
|
||||
else
|
||||
rooms.insert(room->getId(), room);
|
||||
|
||||
room->setName(name);
|
||||
room->setCapacity(capacity);
|
||||
room->addPlayer(owner);
|
||||
if (!room->isLobby()) room->setOwner(owner);
|
||||
}
|
||||
|
||||
Room *Server::findRoom(uint id) const
|
||||
Room *Server::findRoom(int id) const
|
||||
{
|
||||
return rooms.value(id);
|
||||
}
|
||||
|
@ -69,21 +67,25 @@ Room *Server::lobby() const
|
|||
return m_lobby;
|
||||
}
|
||||
|
||||
ServerPlayer *Server::findPlayer(uint id) const
|
||||
ServerPlayer *Server::findPlayer(int id) const
|
||||
{
|
||||
return players.value(id);
|
||||
}
|
||||
|
||||
void Server::removePlayer(int id) {
|
||||
players.remove(id);
|
||||
}
|
||||
|
||||
void Server::updateRoomList()
|
||||
{
|
||||
QJsonArray arr;
|
||||
foreach (Room *room, rooms) {
|
||||
QJsonArray obj;
|
||||
obj << (int)room->getId(); // roomId
|
||||
obj << room->getId(); // roomId
|
||||
obj << room->getName(); // roomName
|
||||
obj << "Role"; // gameMode
|
||||
obj << room->getPlayers().count(); // playerNum
|
||||
obj << (int)room->getCapacity(); // capacity
|
||||
obj << room->getCapacity(); // capacity
|
||||
arr << obj;
|
||||
}
|
||||
lobby()->doBroadcastNotify(
|
||||
|
@ -158,7 +160,9 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString& name, co
|
|||
QRegExp nameExp("[^\\0000-\\0057\\0072-\\0100\\0133-\\0140\\0173-\\0177]+");
|
||||
QByteArray passwordHash = QCryptographicHash::hash(password.toLatin1(), QCryptographicHash::Sha256).toHex();
|
||||
bool passed = false;
|
||||
QString error_msg;
|
||||
QJsonObject result;
|
||||
|
||||
if (nameExp.exactMatch(name)) {
|
||||
// Then we check the database,
|
||||
QString sql_find = QString("SELECT * FROM userinfo \
|
||||
|
@ -178,30 +182,46 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString& name, co
|
|||
result = SelectFromDatabase(db, sql_find); // refresh result
|
||||
passed = true;
|
||||
} else {
|
||||
// check if password is the same
|
||||
passed = (passwordHash == arr[0].toString());
|
||||
// check if this username already login
|
||||
int id = result["id"].toArray()[0].toString().toInt();
|
||||
if (!players.value(id))
|
||||
// check if password is the same
|
||||
passed = (passwordHash == arr[0].toString());
|
||||
if (!passed) error_msg = "username or password error";
|
||||
else {
|
||||
// TODO: reconnect here
|
||||
error_msg = "others logged in with this name";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (passed) {
|
||||
// create new ServerPlayer and setup
|
||||
ServerPlayer *player = new ServerPlayer(lobby());
|
||||
player->setSocket(client);
|
||||
client->disconnect(this);
|
||||
connect(client, &ClientSocket::disconnected, this, [player](){
|
||||
qDebug() << "Player" << player->getId() << "disconnected";
|
||||
});
|
||||
connect(player, &ServerPlayer::disconnected, this, &Server::onUserDisconnected);
|
||||
connect(player, &Player::stateChanged, this, &Server::onUserStateChanged);
|
||||
player->setScreenName(name);
|
||||
player->setAvatar(result["avatar"].toArray()[0].toString());
|
||||
player->setId(result["id"].toArray()[0].toInt());
|
||||
player->setId(result["id"].toArray()[0].toString().toInt());
|
||||
players.insert(player->getId(), player);
|
||||
|
||||
// tell the lobby player's basic property
|
||||
QJsonArray arr;
|
||||
arr << player->getId();
|
||||
arr << player->getScreenName();
|
||||
arr << player->getAvatar();
|
||||
player->doNotify("Setup", QJsonDocument(arr).toJson());
|
||||
|
||||
lobby()->addPlayer(player);
|
||||
} else {
|
||||
qDebug() << client->peerAddress() << "entered wrong password";
|
||||
qDebug() << client->peerAddress() << "lost connection:" << error_msg;
|
||||
QJsonArray body;
|
||||
body << -2;
|
||||
body << (Router::TYPE_NOTIFICATION | Router::SRC_SERVER | Router::DEST_CLIENT);
|
||||
body << "ErrorMsg";
|
||||
body << "username or password error";
|
||||
body << error_msg;
|
||||
client->send(QJsonDocument(body).toJson(QJsonDocument::Compact));
|
||||
client->disconnectFromHost();
|
||||
return;
|
||||
|
@ -218,10 +238,21 @@ void Server::onRoomAbandoned()
|
|||
|
||||
void Server::onUserDisconnected()
|
||||
{
|
||||
qobject_cast<ServerPlayer *>(sender())->setStateString("offline");
|
||||
ServerPlayer *player = qobject_cast<ServerPlayer *>(sender());
|
||||
qDebug() << "Player" << player->getId() << "disconnected";
|
||||
Room *room = player->getRoom();
|
||||
if (room->isStarted()) {
|
||||
player->setState(Player::Offline);
|
||||
} else {
|
||||
player->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void Server::onUserStateChanged()
|
||||
{
|
||||
// TODO
|
||||
Player *player = qobject_cast<Player *>(sender());
|
||||
QJsonArray arr;
|
||||
arr << player->getId();
|
||||
arr << player->getStateString();
|
||||
callLua("PlayerStateChanged", QJsonDocument(arr).toJson());
|
||||
}
|
||||
|
|
|
@ -1,20 +1,11 @@
|
|||
#ifndef _SERVER_H
|
||||
#define _SERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
#include <QHostAddress>
|
||||
#include <lua.hpp>
|
||||
#include <sqlite3.h>
|
||||
|
||||
class ServerSocket;
|
||||
class ClientSocket;
|
||||
class Room;
|
||||
class ServerPlayer;
|
||||
|
||||
typedef int LuaFunction;
|
||||
|
||||
class Server : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -24,17 +15,21 @@ public:
|
|||
|
||||
bool listen(const QHostAddress &address = QHostAddress::Any, ushort port = 9527u);
|
||||
|
||||
void createRoom(ServerPlayer *owner, const QString &name, uint capacity);
|
||||
Room *findRoom(uint id) const;
|
||||
void createRoom(ServerPlayer *owner, const QString &name, int capacity);
|
||||
Room *findRoom(int id) const;
|
||||
Room *lobby() const;
|
||||
|
||||
ServerPlayer *findPlayer(uint id) const;
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
void removePlayer(int id);
|
||||
|
||||
void updateRoomList();
|
||||
|
||||
void callLua(const QString &command, const QString &jsonData);
|
||||
LuaFunction callback;
|
||||
|
||||
void roomStart(Room *room);
|
||||
LuaFunction startRoom;
|
||||
|
||||
signals:
|
||||
void roomCreated(Room *room);
|
||||
void playerAdded(ServerPlayer *player);
|
||||
|
@ -51,8 +46,8 @@ public slots:
|
|||
private:
|
||||
ServerSocket *server;
|
||||
Room *m_lobby;
|
||||
QMap<uint, Room *> rooms;
|
||||
QHash<uint, ServerPlayer *> players;
|
||||
QMap<int, Room *> rooms;
|
||||
QHash<int, ServerPlayer *> players;
|
||||
|
||||
lua_State *L;
|
||||
sqlite3 *db;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "serverplayer.h"
|
||||
#include "room.h"
|
||||
#include "server.h"
|
||||
#include "router.h"
|
||||
#include "client_socket.h"
|
||||
|
||||
ServerPlayer::ServerPlayer(Room *room)
|
||||
{
|
||||
|
@ -8,22 +10,41 @@ ServerPlayer::ServerPlayer(Room *room)
|
|||
router = new Router(this, socket, Router::TYPE_SERVER);
|
||||
|
||||
this->room = room;
|
||||
server = room->getServer();
|
||||
}
|
||||
|
||||
ServerPlayer::~ServerPlayer()
|
||||
{
|
||||
// clean up, quit room and server
|
||||
room->removePlayer(this);
|
||||
if (room != nullptr) {
|
||||
// now we are in lobby, so quit lobby
|
||||
room->removePlayer(this);
|
||||
}
|
||||
server->removePlayer(getId());
|
||||
router->deleteLater();
|
||||
}
|
||||
|
||||
void ServerPlayer::setSocket(ClientSocket *socket)
|
||||
{
|
||||
this->socket = socket;
|
||||
if (this->socket != nullptr) {
|
||||
this->socket->disconnect(this);
|
||||
disconnect(this->socket);
|
||||
this->socket->deleteLater();
|
||||
}
|
||||
|
||||
this->socket = nullptr;
|
||||
if (socket != nullptr) {
|
||||
connect(socket, &ClientSocket::disconnected, this, &ServerPlayer::disconnected);
|
||||
this->socket = socket;
|
||||
}
|
||||
|
||||
router->setSocket(socket);
|
||||
}
|
||||
|
||||
Server *ServerPlayer::getServer() const
|
||||
{
|
||||
return room->getServer();
|
||||
return server;
|
||||
}
|
||||
|
||||
Room *ServerPlayer::getRoom() const
|
||||
|
@ -47,19 +68,14 @@ void ServerPlayer::doRequest(const QString& command, const QString& jsonData, in
|
|||
router->request(type, command, jsonData, timeout);
|
||||
}
|
||||
|
||||
void ServerPlayer::doReply(const QString& command, const QString& jsonData)
|
||||
{
|
||||
int type = Router::TYPE_REPLY | Router::SRC_SERVER | Router::DEST_CLIENT;
|
||||
router->reply(type, command, jsonData);
|
||||
}
|
||||
|
||||
void ServerPlayer::doNotify(const QString& command, const QString& jsonData)
|
||||
{
|
||||
int type = Router::TYPE_NOTIFICATION | Router::SRC_SERVER | Router::DEST_CLIENT;
|
||||
router->notify(type, command, jsonData);
|
||||
}
|
||||
|
||||
void ServerPlayer::prepareForRequest(const QString& command, const QVariant& data)
|
||||
void ServerPlayer::prepareForRequest(const QString& command, const QString& data)
|
||||
{
|
||||
;
|
||||
requestCommand = command;
|
||||
requestData = data;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#define _SERVERPLAYER_H
|
||||
|
||||
#include "player.h"
|
||||
#include "router.h"
|
||||
#include <QVariant>
|
||||
|
||||
class ClientSocket;
|
||||
class Router;
|
||||
class Server;
|
||||
class Room;
|
||||
|
||||
|
@ -24,11 +24,14 @@ public:
|
|||
|
||||
void doRequest(const QString &command,
|
||||
const QString &jsonData, int timeout = -1);
|
||||
void doReply(const QString &command, const QString &jsonData);
|
||||
void doNotify(const QString &command, const QString &jsonData);
|
||||
|
||||
void prepareForRequest(const QString &command,
|
||||
const QVariant &data = QVariant());
|
||||
const QString &data);
|
||||
|
||||
signals:
|
||||
void disconnected();
|
||||
|
||||
private:
|
||||
ClientSocket *socket; // socket for communicating with client
|
||||
Router *router;
|
||||
|
@ -36,7 +39,7 @@ private:
|
|||
Room *room; // Room that player is in, maybe lobby
|
||||
|
||||
QString requestCommand;
|
||||
QVariant requestData;
|
||||
QString requestData;
|
||||
};
|
||||
|
||||
#endif // _SERVERPLAYER_H
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%nodefaultdtor QmlBackend;
|
||||
class QmlBackend : public QObject {
|
||||
public:
|
||||
void emitNotifyUI(const char *command, const char *json_data);
|
||||
void emitNotifyUI(const QString &command, const QString &json_data);
|
||||
};
|
||||
|
||||
extern QmlBackend *Backend;
|
||||
|
@ -11,8 +11,6 @@ extern QmlBackend *Backend;
|
|||
%nodefaultdtor Client;
|
||||
class Client : public QObject {
|
||||
public:
|
||||
void requestServer(const QString &command,
|
||||
const QString &json_data, int timeout = -1);
|
||||
void replyToServer(const QString &command, const QString &json_data);
|
||||
void notifyServer(const QString &command, const QString &json_data);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "clientplayer.h"
|
||||
#include "room.h"
|
||||
#include "qmlbackend.h"
|
||||
#include "util.h"
|
||||
%}
|
||||
|
||||
%include "naturalvar.i"
|
||||
|
|
|
@ -9,8 +9,8 @@ public:
|
|||
Offline
|
||||
};
|
||||
|
||||
unsigned int getId() const;
|
||||
void setId(unsigned int id);
|
||||
int getId() const;
|
||||
void setId(int id);
|
||||
|
||||
QString getScreenName() const;
|
||||
void setScreenName(const QString &name);
|
||||
|
@ -39,8 +39,6 @@ extern ClientPlayer *Self;
|
|||
%nodefaultdtor ServerPlayer;
|
||||
class ServerPlayer : public Player {
|
||||
public:
|
||||
void setSocket(ClientSocket *socket);
|
||||
|
||||
Server *getServer() const;
|
||||
Room *getRoom() const;
|
||||
void setRoom(Room *room);
|
||||
|
@ -49,9 +47,7 @@ public:
|
|||
|
||||
void doRequest(const QString &command,
|
||||
const QString &json_data, int timeout = -1);
|
||||
void doReply(const QString &command, const QString &json_data);
|
||||
void doNotify(const QString &command, const QString &json_data);
|
||||
|
||||
void prepareForRequest(const QString &command,
|
||||
const QVariant &data = QVariant());
|
||||
void prepareForRequest(const QString &command, const QString &data);
|
||||
};
|
||||
|
|
|
@ -1,12 +1,36 @@
|
|||
class QObject {
|
||||
// Make the base classes look like "complete"
|
||||
class QObject {};
|
||||
class QThread {};
|
||||
|
||||
template <class T>
|
||||
class QList {
|
||||
public:
|
||||
QString objectName();
|
||||
void setObjectName(const char *name);
|
||||
bool inherits(const char *class_name);
|
||||
bool setProperty(const char *name, const QVariant &value);
|
||||
QVariant property(const char *name) const;
|
||||
void setParent(QObject *parent);
|
||||
void deleteLater();
|
||||
QList();
|
||||
~QList();
|
||||
int length() const;
|
||||
void append(const T &elem);
|
||||
void prepend(const T &elem);
|
||||
bool isEmpty() const;
|
||||
bool contains(const T &value) const;
|
||||
T first() const;
|
||||
T last() const;
|
||||
void removeAt(int i);
|
||||
int removeAll(const T &value);
|
||||
bool removeOne(const T &value);
|
||||
QList<T> mid(int pos, int length = -1) const;
|
||||
int indexOf(const T &value, int from = 0);
|
||||
void replace(int i, const T &value);
|
||||
void swapItemsAt(int i, int j);
|
||||
};
|
||||
|
||||
class QThread {};
|
||||
%extend QList {
|
||||
T at(int i) const
|
||||
{
|
||||
return $self->value(i);
|
||||
}
|
||||
}
|
||||
|
||||
%template(SPlayerList) QList<ServerPlayer *>;
|
||||
%template(PlayerList) QList<const Player *>;
|
||||
%template(IntList) QList<int>;
|
||||
%template(BoolList) QList<bool>;
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
%nodefaultdtor Server;
|
||||
class Server : public QObject {
|
||||
public:
|
||||
void createRoom(ServerPlayer *owner, const QString &name, unsigned int capacity);
|
||||
Room *findRoom(unsigned int id) const;
|
||||
Room *lobby() const;
|
||||
|
||||
ServerPlayer *findPlayer(unsigned int id) const;
|
||||
|
||||
void updateRoomList();
|
||||
void createRoom(ServerPlayer *owner, const QString &name, int capacity);
|
||||
Room *findRoom(int id) const;
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
|
||||
LuaFunction callback;
|
||||
LuaFunction startRoom;
|
||||
};
|
||||
|
||||
%{
|
||||
|
@ -29,6 +26,21 @@ void Server::callLua(const QString& command, const QString& json_data)
|
|||
qDebug() << error_msg;
|
||||
}
|
||||
}
|
||||
|
||||
void Server::roomStart(Room *room) {
|
||||
Q_ASSERT(startRoom);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, startRoom);
|
||||
SWIG_NewPointerObj(L, this, SWIGTYPE_p_Server, 0);
|
||||
SWIG_NewPointerObj(L, room, SWIGTYPE_p_Room, 0);
|
||||
|
||||
int error = lua_pcall(L, 2, 0, 0);
|
||||
if (error) {
|
||||
const char *error_msg = lua_tostring(L, -1);
|
||||
qDebug() << error_msg;
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
extern Server *ServerInstance;
|
||||
|
@ -40,12 +52,12 @@ public:
|
|||
// Property reader & setter
|
||||
// ==================================={
|
||||
Server *getServer() const;
|
||||
unsigned int getId() const;
|
||||
int getId() const;
|
||||
bool isLobby() const;
|
||||
QString getName() const;
|
||||
void setName(const QString &name);
|
||||
unsigned int getCapacity() const;
|
||||
void setCapacity(unsigned int capacity);
|
||||
int getCapacity() const;
|
||||
void setCapacity(int capacity);
|
||||
bool isFull() const;
|
||||
bool isAbandoned() const;
|
||||
|
||||
|
@ -55,14 +67,19 @@ public:
|
|||
void addPlayer(ServerPlayer *player);
|
||||
void removePlayer(ServerPlayer *player);
|
||||
QList<ServerPlayer *> getPlayers() const;
|
||||
ServerPlayer *findPlayer(unsigned int id) const;
|
||||
ServerPlayer *findPlayer(int id) const;
|
||||
|
||||
void setGameLogic(GameLogic *logic);
|
||||
GameLogic *getGameLogic() const;
|
||||
bool isStarted() const;
|
||||
// ====================================}
|
||||
|
||||
void startGame();
|
||||
void doRequest(const QList<ServerPlayer *> targets, int timeout);
|
||||
void doNotify(const QList<ServerPlayer *> targets, int timeout);
|
||||
void doBroadcastNotify(
|
||||
const QList<ServerPlayer *> targets,
|
||||
const QString &command,
|
||||
const QString &jsonData
|
||||
);
|
||||
|
||||
void gameOver();
|
||||
};
|
||||
|
||||
|
|
|
@ -8,13 +8,23 @@ QmlBackend::QmlBackend(QObject* parent)
|
|||
: QObject(parent)
|
||||
{
|
||||
Backend = this;
|
||||
engine = nullptr;
|
||||
}
|
||||
|
||||
QQmlApplicationEngine *QmlBackend::getEngine() const
|
||||
{
|
||||
return engine;
|
||||
}
|
||||
|
||||
void QmlBackend::setEngine(QQmlApplicationEngine *engine)
|
||||
{
|
||||
this->engine = engine;
|
||||
}
|
||||
|
||||
void QmlBackend::startServer(ushort port)
|
||||
{
|
||||
if (!ServerInstance) {
|
||||
class Server *server = new class Server(this);
|
||||
Server *server = new Server(this);
|
||||
|
||||
if (!server->listen(QHostAddress::Any, port)) {
|
||||
server->deleteLater();
|
||||
|
@ -26,10 +36,11 @@ void QmlBackend::startServer(ushort port)
|
|||
void QmlBackend::joinServer(QString address)
|
||||
{
|
||||
if (ClientInstance != nullptr) return;
|
||||
class Client *client = new class Client(this);
|
||||
Client *client = new Client(this);
|
||||
connect(client, &Client::error_message, [this, client](const QString &msg){
|
||||
client->deleteLater();
|
||||
emit notifyUI("ErrorMsg", msg);
|
||||
emit notifyUI("BackToStart", "[]");
|
||||
});
|
||||
QString addr = "127.0.0.1";
|
||||
ushort port = 9527u;
|
||||
|
@ -45,17 +56,11 @@ void QmlBackend::joinServer(QString address)
|
|||
client->connectToHost(QHostAddress(addr), port);
|
||||
}
|
||||
|
||||
void QmlBackend::replyToServer(const QString& command, const QString& jsonData)
|
||||
{
|
||||
ClientInstance->replyToServer(command, jsonData);
|
||||
}
|
||||
|
||||
void QmlBackend::notifyServer(const QString& command, const QString& jsonData)
|
||||
{
|
||||
ClientInstance->notifyServer(command, jsonData);
|
||||
}
|
||||
|
||||
void QmlBackend::quitLobby()
|
||||
{
|
||||
delete ClientInstance;
|
||||
}
|
||||
|
||||
void QmlBackend::emitNotifyUI(const QString &command, const QString &jsonData) {
|
||||
emit notifyUI(command, jsonData);
|
||||
}
|
||||
|
|
|
@ -1,41 +1,28 @@
|
|||
#ifndef _QMLBACKEND_H
|
||||
#define _QMLBACKEND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QJsonDocument>
|
||||
#include "client.h"
|
||||
|
||||
class QmlBackend : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum WindowType {
|
||||
Server,
|
||||
Lobby,
|
||||
Room,
|
||||
NotStarted
|
||||
};
|
||||
|
||||
QmlBackend(QObject *parent = nullptr);
|
||||
|
||||
// For lua use
|
||||
void emitNotifyUI(const char *command, const char *jsonData) {
|
||||
emit notifyUI(command, jsonData);
|
||||
}
|
||||
QQmlApplicationEngine *getEngine() const;
|
||||
void setEngine(QQmlApplicationEngine *engine);
|
||||
|
||||
Q_INVOKABLE void startServer(ushort port);
|
||||
Q_INVOKABLE void joinServer(QString address);
|
||||
|
||||
// Lobby
|
||||
Q_INVOKABLE void quitLobby();
|
||||
|
||||
// lua --> qml
|
||||
void emitNotifyUI(const QString &command, const QString &jsonData);
|
||||
|
||||
signals:
|
||||
void notifyUI(const QString &command, const QString &jsonData);
|
||||
|
||||
public slots:
|
||||
void startServer(ushort port);
|
||||
void joinServer(QString address);
|
||||
void replyToServer(const QString &command, const QString &jsonData);
|
||||
void notifyServer(const QString &command, const QString &jsonData);
|
||||
|
||||
// Lobby
|
||||
void quitLobby();
|
||||
|
||||
private:
|
||||
WindowType type;
|
||||
QQmlApplicationEngine *engine;
|
||||
};
|
||||
|
||||
extern QmlBackend *Backend;
|
||||
|
|
Loading…
Reference in New Issue