* more comment

* create standard card pack

* create card classes

* freekill -> fk

* fk_ex
This commit is contained in:
Notify-ctrl 2022-03-31 13:29:23 +08:00 committed by GitHub
parent a85f510c98
commit 957fefe881
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 360 additions and 161 deletions

View File

@ -3,15 +3,15 @@ Client = class('Client')
-- load client classes -- load client classes
ClientPlayer = require "client.clientplayer" ClientPlayer = require "client.clientplayer"
freekill.client_callback = {} fk.client_callback = {}
function Client:initialize() function Client:initialize()
self.client = freekill.ClientInstance self.client = fk.ClientInstance
self.notifyUI = function(self, command, jsonData) self.notifyUI = function(self, command, jsonData)
freekill.Backend:emitNotifyUI(command, jsonData) fk.Backend:emitNotifyUI(command, jsonData)
end end
self.client.callback = function(_self, command, jsonData) self.client.callback = function(_self, command, jsonData)
local cb = freekill.client_callback[command] local cb = fk.client_callback[command]
if (type(cb) == "function") then if (type(cb) == "function") then
cb(jsonData) cb(jsonData)
else else
@ -22,31 +22,31 @@ function Client:initialize()
self.players = {} -- ClientPlayer[] self.players = {} -- ClientPlayer[]
end end
freekill.client_callback["Setup"] = function(jsonData) fk.client_callback["Setup"] = function(jsonData)
-- jsonData: [ int id, string screenName, string avatar ] -- jsonData: [ int id, string screenName, string avatar ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local id, name, avatar = data[1], data[2], data[3] local id, name, avatar = data[1], data[2], data[3]
local self = freekill.Self local self = fk.Self
self:setId(id) self:setId(id)
self:setScreenName(name) self:setScreenName(name)
self:setAvatar(avatar) self:setAvatar(avatar)
end end
freekill.client_callback["AddPlayer"] = function(jsonData) fk.client_callback["AddPlayer"] = function(jsonData)
-- jsonData: [ int id, string screenName, string avatar ] -- jsonData: [ int id, string screenName, string avatar ]
-- when other player enter the room, we create clientplayer(C and lua) for them -- when other player enter the room, we create clientplayer(C and lua) for them
local data = json.decode(jsonData) local data = json.decode(jsonData)
local id, name, avatar = data[1], data[2], data[3] local id, name, avatar = data[1], data[2], data[3]
local player = freekill.ClientInstance:addPlayer(id, name, avatar) local player = fk.ClientInstance:addPlayer(id, name, avatar)
table.insert(ClientInstance.players, ClientPlayer:new(player)) table.insert(ClientInstance.players, ClientPlayer:new(player))
ClientInstance:notifyUI("AddPlayer", jsonData) ClientInstance:notifyUI("AddPlayer", jsonData)
end end
freekill.client_callback["RemovePlayer"] = function(jsonData) fk.client_callback["RemovePlayer"] = function(jsonData)
-- jsonData: [ int id ] -- jsonData: [ int id ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local id = data[1] local id = data[1]
freekill.ClientInstance:removePlayer(id) fk.ClientInstance:removePlayer(id)
for _, p in ipairs(ClientInstance.players) do for _, p in ipairs(ClientInstance.players) do
if p.player:getId() == id then if p.player:getId() == id then
table.removeOne(ClientInstance.players, p) table.removeOne(ClientInstance.players, p)
@ -56,7 +56,7 @@ freekill.client_callback["RemovePlayer"] = function(jsonData)
ClientInstance:notifyUI("RemovePlayer", jsonData) ClientInstance:notifyUI("RemovePlayer", jsonData)
end end
freekill.client_callback["ArrangeSeats"] = function(jsonData) fk.client_callback["ArrangeSeats"] = function(jsonData)
local data = json.decode(jsonData) local data = json.decode(jsonData)
local n = #ClientInstance.players local n = #ClientInstance.players
local players = {} local players = {}

View File

@ -1,37 +1,55 @@
local SUITS = { ---@class Card : Object
"Spade", ---@field package Package
"Club", ---@field name string
"Diamond", ---@field suit number # enum suit
"Heart", ---@field number number
"NonSuit", ---@field color number # enum color
} ---@field id number
---@field type number # enum type
CardSuit = Util:createEnum(SUITS)
local COLOR = {
"Red",
"Black",
"NonColor",
}
CardColor = Util:createEnum(COLOR)
local Card = class("Card") local Card = class("Card")
function Card:initialize(name, suit, cardNumber) -- enum Suit
self.name = name fk.createEnum(Card, {
self.suit = suit "Spade",
self.cardNumber = cardNumber "Club",
end "Heart",
"Diamond",
"NoSuit"
})
function Card:getColor() -- enum Color
if self.suit == CardSuit.Spade or self.suit == CardSuit.Club then fk.createEnum(Card, {
return CardColor.Red "Black",
elseif self.suit == CardSuit.Diamond or self.suit == CardSuit.Heart then "Red",
return CardColor.Black "NoColor"
})
-- enum Type
fk.createEnum(Card, {
"TypeSkill",
"TypeBasic",
"TypeTrick",
"TypeEquip"
})
function Card:initialize(name, suit, number, color)
self.name = name
self.suit = suit or Card.NoSuit
self.number = number or 0
if suit == Card.Spade or suit == Card.Club then
self.color = Card.Black
elseif suit == Card.Heart or suit == Card.Diamond then
self.color = Card.Red
elseif color ~= nil then
self.color = color
else else
return CardColor.NonColor self.color = Card.NoColor
end end
self.package = nil
self.id = 0
self.type = 0
end end
return Card return Card

View File

@ -0,0 +1,9 @@
---@class BasicCard : Card
local BasicCard = Card:subclass("BasicCard")
function BasicCard:initialize(name, suit, number)
Card.initialize(self, name, suit, number)
self.type = Card.TypeBasic
end
return BasicCard

View File

@ -0,0 +1,9 @@
---@class EquipCard : Card
local EquipCard = Card:subclass("EquipCard")
function EquipCard:initialize(name, suit, number)
Card.initialize(self, name, suit, number)
self.type = Card.TypeEquip
end
return EquipCard

View File

@ -0,0 +1,9 @@
---@class SkillCard : Card
local SkillCard = Card:subclass("SkillCard")
function SkillCard:initialize(name)
Card.initialize(self, name, Card.NoSuit, 0)
self.type = Card.TypeSkill
end
return SkillCard

View File

@ -0,0 +1,9 @@
---@class TrickCard : Card
local TrickCard = Card:subclass("TrickCard")
function TrickCard:initialize(name, suit, number)
Card.initialize(self, name, suit, number)
self.type = Card.TypeTrick
end
return TrickCard

View File

@ -46,14 +46,11 @@ function Engine:loadPackage(pack)
end end
function Engine:loadPackages() function Engine:loadPackages()
assert(FileIO.isDir("packages")) for _, dir in ipairs(FileIO.ls("packages")) do
FileIO.cd("packages") if FileIO.isDir("packages/" .. dir) then
for _, dir in ipairs(FileIO.ls()) do self:loadPackage(require(string.format("packages.%s", dir)))
if FileIO.isDir(dir) then
self:loadPackage(require(dir))
end end
end end
FileIO.cd("..")
end end
---@param t table ---@param t table
@ -98,13 +95,17 @@ function Engine:addGenerals(generals)
end end
end end
local cardId = 1
---@param card Card
function Engine:addCard(card) function Engine:addCard(card)
assert(card.class:isSubclassOf(Card)) assert(card.class:isSubclassOf(Card))
card.id = cardId
cardId = cardId + 1
table.insert(self.cards, card) table.insert(self.cards, card)
end end
---@param cards Card[]
function Engine:addCards(cards) function Engine:addCards(cards)
assert(type(cards) == "table")
for _, card in ipairs(cards) do for _, card in ipairs(cards) do
self:addCard(card) self:addCard(card)
end end

View File

@ -1,9 +1,19 @@
--- @class General : Object ---@class General : Object
---@field package Package
---@field name string
---@field kingdom string
---@field hp number
---@field maxHp number
---@field gender number
---@field skills table
---@field other_skills table
General = class("General") General = class("General")
-- enum Gender -- enum Gender
General.Male = 0 fk.createEnum(General, {
General.Female = 1 "Male",
"Female"
})
function General:initialize(package, name, kingdom, hp, maxHp, gender, initialHp) function General:initialize(package, name, kingdom, hp, maxHp, gender, initialHp)
self.package = package self.package = package
@ -12,7 +22,6 @@ function General:initialize(package, name, kingdom, hp, maxHp, gender, initialHp
self.hp = hp self.hp = hp
self.maxHp = maxHp or hp self.maxHp = maxHp or hp
self.gender = gender or General.Male self.gender = gender or General.Male
self.initialHp = initialHp or maxHp
self.skills = {} -- Skill[] self.skills = {} -- Skill[]
-- skill belongs other general, e.g. "mashu" of pangde -- skill belongs other general, e.g. "mashu" of pangde

View File

@ -8,9 +8,11 @@
local Package = class("Package") local Package = class("Package")
-- enum Type -- enum Type
Package.GeneralPack = 0 fk.createEnum(Package, {
Package.CardPack = 1 "GeneralPack",
Package.SpecialPack = 2 "CardPack",
"SpecialPack"
})
function Package:initialize(name, _type) function Package:initialize(name, _type)
assert(type(name) == "string") assert(type(name) == "string")
@ -45,4 +47,18 @@ function Package:addGeneral(general)
table.insert(self.generals, general) table.insert(self.generals, general)
end end
---@param card Card
function Package:addCard(card)
assert(card.class and card:isInstanceOf(Card))
card.package = self
table.insert(self.cards, card)
end
---@param cards Card[]
function Package:addCards(cards)
for _, card in ipairs(cards) do
self:addCard(card)
end
end
return Package return Package

View File

@ -19,11 +19,14 @@ function Player:initialize()
self.playerSkills = {} self.playerSkills = {}
end end
---@param general General
---@param setHp boolean
---@param addSkills boolean
function Player:setGeneral(general, setHp, addSkills) function Player:setGeneral(general, setHp, addSkills)
self.general = general self.general = general
if setHp then if setHp then
self.maxHp = general.maxHp self.maxHp = general.maxHp
self.hp = general.initialHp self.hp = general.hp
end end
if addSkills then if addSkills then
@ -31,9 +34,4 @@ function Player:setGeneral(general, setHp, addSkills)
end end
end end
function Player:setHp(maxHp, initialHp)
self.maxHp = maxHp
self.hp = initialHp or maxHp
end
return Player return Player

View File

@ -1,15 +1,13 @@
local SKILL_TYPE = { ---@class Skill
local Skill = class("Skill")
fk.createEnum(Skill, {
"Common", "Common",
"Frequent", "Frequent",
"Compulsory", "Compulsory",
"Awaken", "Awaken",
"Limit", "Limit",
"Lord", })
}
SkillType = Util:createEnum(SKILL_TYPE)
local Skill = class("Skill")
function Skill:initialize(name, skillType) function Skill:initialize(name, skillType)
self.name = name self.name = name

View File

@ -5,7 +5,7 @@ local qlist_iterator = function(list, n)
end end
end end
function freekill.qlist(list) function fk.qlist(list)
return qlist_iterator, list, -1 return qlist_iterator, list, -1
end end
@ -33,46 +33,47 @@ end
Sql = { Sql = {
---@param filename string ---@param filename string
open = function(filename) open = function(filename)
return freekill.OpenDatabase(filename) return fk.OpenDatabase(filename)
end, end,
---@param db freekill.SQLite3 ---@param db fk.SQLite3
close = function(db) close = function(db)
freekill.CloseDatabase(db) fk.CloseDatabase(db)
end, end,
--- Execute an SQL statement. --- Execute an SQL statement.
---@param db freekill.SQLite3 ---@param db fk.SQLite3
---@param sql string ---@param sql string
exec = function(db, sql) exec = function(db, sql)
freekill.ExecSQL(db, sql) fk.ExecSQL(db, sql)
end, end,
--- Execute a `SELECT` SQL statement. --- Execute a `SELECT` SQL statement.
---@param db freekill.SQLite3 ---@param db fk.SQLite3
---@param sql string ---@param sql string
---@return table data # { [columnName] --> result : string[] } ---@return table data # { [columnName] --> result : string[] }
exec_select = function(db, sql) exec_select = function(db, sql)
return json.decode(freekill.SelectFromDb(db, sql)) return json.decode(fk.SelectFromDb(db, sql))
end, end,
} }
FileIO = { FileIO = {
pwd = freekill.QmlBackend_pwd, pwd = fk.QmlBackend_pwd,
ls = function(filename) ls = function(filename)
if filename == nil then if filename == nil then
return freekill.QmlBackend_ls(".") return fk.QmlBackend_ls(".")
else else
return freekill.QmlBackend_ls(filename) return fk.QmlBackend_ls(filename)
end end
end, end,
cd = freekill.QmlBackend_cd, cd = fk.QmlBackend_cd,
exists = freekill.QmlBackend_exists, exists = fk.QmlBackend_exists,
isDir = freekill.QmlBackend_isDir isDir = fk.QmlBackend_isDir
} }
os.getms = freekill.GetMicroSecond os.getms = fk.GetMicroSecond
---@class Stack : Object
Stack = class("Stack") Stack = class("Stack")
function Stack:initialize() function Stack:initialize()
self.t = {} self.t = {}
@ -106,16 +107,11 @@ function table:removeOne(element)
return false return false
end end
local Util = class("Util") --- convert a table to enum, e.g. core/card.lua
---@param table table # class to store the enum
function Util.static:createEnum(tbl, index) ---@param enum string[]
assert(type(tbl) == "table") function fk.createEnum(table, enum)
local enumtbl = {} for i, v in ipairs(enum) do
local enumindex = index or 0 table[v] = i
for i, v in ipairs(tbl) do
enumtbl[v] = enumindex + i
end end
return enumtbl
end end
return Util

38
lua/fk_ex.lua Normal file
View File

@ -0,0 +1,38 @@
---@param spec table
---@return BasicCard
function fk.CreateBasicCard(spec)
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
if not spec.name then spec.name = spec.class_name
elseif not spec.class_name then spec.class_name = spec.name end
if spec.suit then assert(type(spec.suit) == "number") end
if spec.number then assert(type(spec.number) == "number") end
local card = BasicCard:new(spec.name, spec.suit, spec.number)
return card
end
---@param spec table
---@return TrickCard
function fk.CreateTrickCard(spec)
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
if not spec.name then spec.name = spec.class_name
elseif not spec.class_name then spec.class_name = spec.name end
if spec.suit then assert(type(spec.suit) == "number") end
if spec.number then assert(type(spec.number) == "number") end
local card = TrickCard:new(spec.name, spec.suit, spec.number)
return card
end
---@param spec table
---@return EquipCard
function fk.CreateEquipCard(spec)
assert(type(spec.name) == "string" or type(spec.class_name) == "string")
if not spec.name then spec.name = spec.class_name
elseif not spec.class_name then spec.class_name = spec.name end
if spec.suit then assert(type(spec.suit) == "number") end
if spec.number then assert(type(spec.number) == "number") end
local card = EquipCard:new(spec.name, spec.suit, spec.number)
return card
end

View File

@ -6,14 +6,12 @@ package.path = package.path .. ";./lua/lib/?.lua"
-- load libraries -- load libraries
---@type class
class = require "middleclass" class = require "middleclass"
---@type json
json = require "json" json = require "json"
require "sha256" dofile "lua/lib/sha256.lua"
Util = require "core.util" dofile "lua/core/util.lua"
math.randomseed(os.time()) math.randomseed(os.time())
DebugMode = true DebugMode = true
@ -29,8 +27,13 @@ Engine = require "core.engine"
Package = require "core.package" Package = require "core.package"
General = require "core.general" General = require "core.general"
Card = require "core.card" Card = require "core.card"
SkillCard = require "core.card_type.skill"
BasicCard = require "core.card_type.basic"
TrickCard = require "core.card_type.trick"
EquipCard = require "core.card_type.equip"
Skill = require "core.skill" Skill = require "core.skill"
Player = require "core.player" Player = require "core.player"
-- load packages -- load packages
dofile "lua/fk_ex.lua"
Fk = Engine:new() Fk = Engine:new()

View File

@ -1,4 +1,9 @@
---@class GameLogic: Object ---@class GameLogic: Object
---@field room Room
---@field skill_table table
---@filed skills table
---@field event_stack Stack
---@field role_table table
local GameLogic = class("GameLogic") local GameLogic = class("GameLogic")
function GameLogic:initialize(room) function GameLogic:initialize(room)

View File

@ -1,8 +1,15 @@
---@class Room : Object ---@class Room : Object
---@field room fk.Room
---@field server Server
---@field players table
---@field alive_players table
---@field game_finished boolean
---@field timeout number
local Room = class("Room") local Room = class("Room")
function Room:initialize(_room) function Room:initialize(_room)
self.room = _room self.room = _room
self.server = nil
self.players = {} -- ServerPlayer[] self.players = {} -- ServerPlayer[]
self.alive_players = {} self.alive_players = {}
self.game_finished = false self.game_finished = false
@ -11,7 +18,7 @@ end
-- When this function returns, the Room(C++) thread stopped. -- When this function returns, the Room(C++) thread stopped.
function Room:run() function Room:run()
for _, p in freekill.qlist(self.room:getPlayers()) do for _, p in fk.qlist(self.room:getPlayers()) do
local player = ServerPlayer:new(p) local player = ServerPlayer:new(p)
player.state = p:getStateString() player.state = p:getStateString()
player.room = self player.room = self
@ -23,12 +30,17 @@ function Room:run()
self.logic:run() self.logic:run()
end end
---@param player ServerPlayer
---@param property string
function Room:broadcastProperty(player, property) function Room:broadcastProperty(player, property)
for _, p in ipairs(self.players) do for _, p in ipairs(self.players) do
self:notifyProperty(p, player, property) self:notifyProperty(p, player, property)
end end
end end
---@param p ServerPlayer
---@param player ServerPlayer
---@param property string
function Room:notifyProperty(p, player, property) function Room:notifyProperty(p, player, property)
p:doNotify("PropertyUpdate", json.encode{ p:doNotify("PropertyUpdate", json.encode{
player:getId(), player:getId(),
@ -37,15 +49,23 @@ function Room:notifyProperty(p, player, property)
}) })
end end
---@param command string
---@param jsonData string
---@param players ServerPlayer[] # default all players
function Room:doBroadcastNotify(command, jsonData, players) function Room:doBroadcastNotify(command, jsonData, players)
players = players or self.players players = players or self.players
local tolist = freekill.SPlayerList() local tolist = fk.SPlayerList()
for _, p in ipairs(players) do for _, p in ipairs(players) do
tolist:append(p.serverplayer) tolist:append(p.serverplayer)
end end
self.room:doBroadcastNotify(tolist, command, jsonData) self.room:doBroadcastNotify(tolist, command, jsonData)
end end
---@param player ServerPlayer
---@param command string
---@param jsonData string
---@param wait boolean # default true
---@return string | nil
function Room:doRequest(player, command, jsonData, wait) function Room:doRequest(player, command, jsonData, wait)
if wait == nil then wait = true end if wait == nil then wait = true end
player:doRequest(command, jsonData, self.timeout) player:doRequest(command, jsonData, self.timeout)
@ -55,6 +75,8 @@ function Room:doRequest(player, command, jsonData, wait)
end end
end end
---@param command string
---@param players ServerPlayer[]
function Room:doBroadcastRequest(command, players) function Room:doBroadcastRequest(command, players)
players = players or self.players players = players or self.players
self:notifyMoveFocus(players, command) self:notifyMoveFocus(players, command)
@ -72,6 +94,8 @@ function Room:doBroadcastRequest(command, players)
end end
end end
---@param players ServerPlayer | ServerPlayer[]
---@param command string
function Room:notifyMoveFocus(players, command) function Room:notifyMoveFocus(players, command)
if (players.class) then if (players.class) then
players = {players} players = {players}
@ -116,6 +140,7 @@ function Room:adjustSeats()
self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle)) self:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
end end
---@return ServerPlayer | nil
function Room:getLord() function Room:getLord()
local lord = self.players[1] local lord = self.players[1]
if lord.role == "lord" then return lord end if lord.role == "lord" then return lord end
@ -126,12 +151,17 @@ function Room:getLord()
return nil return nil
end end
---@param expect ServerPlayer
---@return ServerPlayer[]
function Room:getOtherPlayers(expect) function Room:getOtherPlayers(expect)
local ret = {table.unpack(self.players)} local ret = {table.unpack(self.players)}
table.removeOne(ret, expect) table.removeOne(ret, expect)
return ret return ret
end end
---@param player ServerPlayer
---@param generals string[]
---@return string
function Room:askForGeneral(player, generals) function Room:askForGeneral(player, generals)
local command = "AskForGeneral" local command = "AskForGeneral"
self:notifyMoveFocus(player, command) self:notifyMoveFocus(player, command)

View File

@ -1,4 +1,8 @@
---@class Server : Object ---@class Server : Object
---@field server fk.Server
---@field db fk.SQLite3
---@field rooms table
---@field players table
Server = class('Server') Server = class('Server')
-- load server classes -- load server classes
@ -6,13 +10,13 @@ Room = require "server.room"
GameLogic = require "server.gamelogic" GameLogic = require "server.gamelogic"
ServerPlayer = require "server.serverplayer" ServerPlayer = require "server.serverplayer"
freekill.server_callback = {} fk.server_callback = {}
function Server:initialize() function Server:initialize()
self.server = freekill.ServerInstance self.server = fk.ServerInstance
self.db = freekill.ServerInstance:getDatabase() self.db = fk.ServerInstance:getDatabase()
self.server.callback = function(_self, command, jsonData) self.server.callback = function(_self, command, jsonData)
local cb = freekill.server_callback[command] local cb = fk.server_callback[command]
if (type(cb) == "function") then if (type(cb) == "function") then
cb(jsonData) cb(jsonData)
else else
@ -37,18 +41,18 @@ function Server:initialize()
self.players = {} -- id --> ServerPlayer self.players = {} -- id --> ServerPlayer
end end
freekill.server_callback["UpdateAvatar"] = function(jsonData) fk.server_callback["UpdateAvatar"] = function(jsonData)
-- jsonData: [ int uid, string newavatar ] -- jsonData: [ int uid, string newavatar ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local id, avatar = data[1], data[2] local id, avatar = data[1], data[2]
local sql = "UPDATE userinfo SET avatar='%s' WHERE id=%d;" local sql = "UPDATE userinfo SET avatar='%s' WHERE id=%d;"
Sql.exec(ServerInstance.db, string.format(sql, avatar, id)) Sql.exec(ServerInstance.db, string.format(sql, avatar, id))
local player = freekill.ServerInstance:findPlayer(id) local player = fk.ServerInstance:findPlayer(id)
player:setAvatar(avatar) player:setAvatar(avatar)
player:doNotify("UpdateAvatar", avatar) player:doNotify("UpdateAvatar", avatar)
end end
freekill.server_callback["UpdatePassword"] = function(jsonData) fk.server_callback["UpdatePassword"] = function(jsonData)
-- jsonData: [ int uid, string oldpassword, int newpassword ] -- jsonData: [ int uid, string oldpassword, int newpassword ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local id, old, new = data[1], data[2], data[3] local id, old, new = data[1], data[2], data[3]
@ -63,38 +67,38 @@ freekill.server_callback["UpdatePassword"] = function(jsonData)
Sql.exec(db, string.format(sql_update, sha256(new), id)) Sql.exec(db, string.format(sql_update, sha256(new), id))
end end
local player = freekill.ServerInstance:findPlayer(tonumber(id)) local player = fk.ServerInstance:findPlayer(tonumber(id))
player:doNotify("UpdatePassword", passed and "1" or "0") player:doNotify("UpdatePassword", passed and "1" or "0")
end end
freekill.server_callback["CreateRoom"] = function(jsonData) fk.server_callback["CreateRoom"] = function(jsonData)
-- jsonData: [ int uid, string name, int capacity ] -- jsonData: [ int uid, string name, int capacity ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local owner = freekill.ServerInstance:findPlayer(tonumber(data[1])) local owner = fk.ServerInstance:findPlayer(tonumber(data[1]))
local roomName = data[2] local roomName = data[2]
local capacity = data[3] local capacity = data[3]
freekill.ServerInstance:createRoom(owner, roomName, capacity) fk.ServerInstance:createRoom(owner, roomName, capacity)
end end
freekill.server_callback["EnterRoom"] = function(jsonData) fk.server_callback["EnterRoom"] = function(jsonData)
-- jsonData: [ int uid, int roomId ] -- jsonData: [ int uid, int roomId ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local player = freekill.ServerInstance:findPlayer(tonumber(data[1])) local player = fk.ServerInstance:findPlayer(tonumber(data[1]))
local room = freekill.ServerInstance:findRoom(tonumber(data[2])) local room = fk.ServerInstance:findRoom(tonumber(data[2]))
room:addPlayer(player) room:addPlayer(player)
end end
freekill.server_callback["QuitRoom"] = function(jsonData) fk.server_callback["QuitRoom"] = function(jsonData)
-- jsonData: [ int uid ] -- jsonData: [ int uid ]
local data = json.decode(jsonData) local data = json.decode(jsonData)
local player = freekill.ServerInstance:findPlayer(tonumber(data[1])) local player = fk.ServerInstance:findPlayer(tonumber(data[1]))
local room = player:getRoom() local room = player:getRoom()
if not room:isLobby() then if not room:isLobby() then
room:removePlayer(player) room:removePlayer(player)
end end
end end
freekill.server_callback["DoLuaScript"] = function(jsonData) fk.server_callback["DoLuaScript"] = function(jsonData)
-- jsonData: [ int uid, string luaScript ] -- jsonData: [ int uid, string luaScript ]
-- warning: only use this in debugging mode. -- warning: only use this in debugging mode.
if not DebugMode then return end if not DebugMode then return end
@ -102,7 +106,7 @@ freekill.server_callback["DoLuaScript"] = function(jsonData)
assert(load(data[2]))() assert(load(data[2]))()
end end
freekill.server_callback["PlayerStateChanged"] = function(jsonData) fk.server_callback["PlayerStateChanged"] = function(jsonData)
-- jsonData: [ int uid, string stateString ] -- jsonData: [ int uid, string stateString ]
-- note: this function is not called by Router. -- note: this function is not called by Router.
local data = json.decode(jsonData) local data = json.decode(jsonData)

View File

@ -1,4 +1,11 @@
---@class ServerPlayer : Player ---@class ServerPlayer : Player
---@field serverplayer fk.ServerPlayer
---@field room Room
---@field next ServerPlayer
---@field request_data string
---@field client_reply string
---@field default_reply string
---@field reply_ready boolean
local ServerPlayer = Player:subclass("ServerPlayer") local ServerPlayer = Player:subclass("ServerPlayer")
function ServerPlayer:initialize(_self) function ServerPlayer:initialize(_self)
@ -15,14 +22,23 @@ function ServerPlayer:initialize(_self)
self.reply_ready = false self.reply_ready = false
end end
---@return number
function ServerPlayer:getId() function ServerPlayer:getId()
return self.serverplayer:getId() return self.serverplayer:getId()
end end
---@param command string
---@param jsonData string
function ServerPlayer:doNotify(command, jsonData) function ServerPlayer:doNotify(command, jsonData)
self.serverplayer:doNotify(command, jsonData) self.serverplayer:doNotify(command, jsonData)
end end
--- Send a request to client, and allow client to reply within *timeout* seconds.
---
--- *timeout* must not be negative. If nil, room.timeout is used.
---@param command string
---@param jsonData string
---@param timeout number
function ServerPlayer:doRequest(command, jsonData, timeout) function ServerPlayer:doRequest(command, jsonData, timeout)
timeout = timeout or self.room.timeout timeout = timeout or self.room.timeout
self.client_reply = "" self.client_reply = ""
@ -30,6 +46,11 @@ function ServerPlayer:doRequest(command, jsonData, timeout)
self.serverplayer:doRequest(command, jsonData, timeout) self.serverplayer:doRequest(command, jsonData, timeout)
end end
--- Wait for at most *timeout* seconds for reply from client.
---
--- If *timeout* is negative or **nil**, the function will wait forever until get reply.
---@param timeout number # seconds to wait
---@return string reply # JSON data
function ServerPlayer:waitForReply(timeout) function ServerPlayer:waitForReply(timeout)
local result = "" local result = ""
if timeout == nil then if timeout == nil then

View File

@ -3,23 +3,23 @@
-- Note: these files are not used by FreeKill. -- Note: these files are not used by FreeKill.
-- Just for convenience when using sumneko.lua -- Just for convenience when using sumneko.lua
---@class freekill ---@class fk
---FreeKill's lua API ---FreeKill's lua API
freekill = {} fk = {}
---@class freekill.SPlayerList ---@class fk.SPlayerList
SPlayerList = {} SPlayerList = {}
--- * get microsecond from Epoch --- * get microsecond from Epoch
---@return number microsecond ---@return number microsecond
function freekill:GetMicroSecond()end function fk:GetMicroSecond()end
--- construct a QList<ServerPlayer *>. --- construct a QList<ServerPlayer *>.
---@return freekill.SPlayerList ---@return fk.SPlayerList
function freekill:SPlayerList()end function fk:SPlayerList()end
function freekill.QmlBackend_pwd()end function fk.QmlBackend_pwd()end
function freekill.QmlBackend_ls(filename)end function fk.QmlBackend_ls(filename)end
function freekill.QmlBackend_cd(dir)end function fk.QmlBackend_cd(dir)end
function freekill.QmlBackend_exists(file)end function fk.QmlBackend_exists(file)end
function freekill.QmlBackend_isDir(file)end function fk.QmlBackend_isDir(file)end

View File

@ -20,6 +20,10 @@ function Object:subclass(name)end
---@return boolean ---@return boolean
function Object:isInstanceOf(class) end function Object:isInstanceOf(class) end
---@param class class
---@return boolean
function Object:isSubclassOf(class) end
---@class json ---@class json
json = {} json = {}

View File

@ -1,6 +1,6 @@
---@meta ---@meta
---@class freekill.Player ---@class fk.Player
FPlayer = {} FPlayer = {}
---@return number id ---@return number id
@ -27,16 +27,16 @@ function FPlayer:getStateString()end
---@param state string ---@param state string
function FPlayer:setStateString(state)end function FPlayer:setStateString(state)end
---@class freekill.ServerPlayer : freekill.Player ---@class fk.ServerPlayer : fk.Player
FServerPlayer = {} FServerPlayer = {}
---@return freekill.Server ---@return fk.Server
function FServerPlayer:getServer()end function FServerPlayer:getServer()end
---@return freekill.Room ---@return fk.Room
function FServerPlayer:getRoom()end function FServerPlayer:getRoom()end
---@param room freekill.Room ---@param room fk.Room
function FServerPlayer:setRoom(room)end function FServerPlayer:setRoom(room)end
---@param msg string ---@param msg string

View File

@ -3,15 +3,15 @@
---@return number length ---@return number length
function SPlayerList:length()end function SPlayerList:length()end
---@param e freekill.ServerPlayer ---@param e fk.ServerPlayer
function SPlayerList:append(e)end function SPlayerList:append(e)end
---@param e freekill.ServerPlayer ---@param e fk.ServerPlayer
---@return boolean ---@return boolean
function SPlayerList:contains(e)end function SPlayerList:contains(e)end
---@param index number ---@param index number
---@return freekill.ServerPlayer | nil ---@return fk.ServerPlayer | nil
function SPlayerList:at(index)end function SPlayerList:at(index)end
function SPlayerList:first()end function SPlayerList:first()end

View File

@ -1,29 +1,29 @@
---@meta ---@meta
---@class freekill.Server ---@class fk.Server
FServer = {} FServer = {}
---@type freekill.Server ---@type fk.Server
freekill.ServerInstance = {} fk.ServerInstance = {}
---@class freekill.Room ---@class fk.Room
--- Room (C++) --- Room (C++)
FRoom = {} FRoom = {}
---@param owner freekill.ServerPlayer ---@param owner fk.ServerPlayer
---@param name string ---@param name string
---@param capacity number ---@param capacity number
function FServer:createRoom(owner,name,capacity)end function FServer:createRoom(owner,name,capacity)end
---@param id number ---@param id number
---@return freekill.Room room ---@return fk.Room room
function FServer:findRoom(id)end function FServer:findRoom(id)end
---@param id number ---@param id number
---@return freekill.ServerPlayer player ---@return fk.ServerPlayer player
function FServer:findPlayer(id)end function FServer:findPlayer(id)end
---@return freekill.SQLite3 db ---@return fk.SQLite3 db
function FServer:getDatabase()end function FServer:getDatabase()end
function FRoom:getServer()end function FRoom:getServer()end

View File

@ -1,20 +1,20 @@
---@meta ---@meta
---@class freekill.SQLite3 ---@class fk.SQLite3
SQLite3 = {} SQLite3 = {}
---@param filename string ---@param filename string
---@return freekill.SQLite3 ---@return fk.SQLite3
function freekill.OpenDatabase(filename)end function fk.OpenDatabase(filename)end
---@param db freekill.SQLite3 ---@param db fk.SQLite3
---@param sql string ---@param sql string
---@return string jsonData ---@return string jsonData
function freekill.SelectFromDb(db, sql)end function fk.SelectFromDb(db, sql)end
---@param db freekill.SQLite3 ---@param db fk.SQLite3
---@param sql string ---@param sql string
function freekill.ExecSQL(db, sql)end function fk.ExecSQL(db, sql)end
---@param db freekill.SQLite3 ---@param db fk.SQLite3
function freekill.CloseDatabase(db)end function fk.CloseDatabase(db)end

View File

@ -1,5 +1,5 @@
local extension = Package:new("standard") local extension = Package:new("standard")
extension.metadata = require "standard.metadata" extension.metadata = require "packages.standard.metadata"
Fk:loadTranslationTable{ Fk:loadTranslationTable{
["wei"] = "", ["wei"] = "",

View File

@ -0,0 +1,8 @@
local extension = Package:new("standard_cards", Package.CardPack)
extension.metadata = require "packages.standard_cards.metadata"
local slash = fk.CreateBasicCard{
name = "slash",
}
return extension

View File

@ -0,0 +1,14 @@
return {
name = "standard_cards",
author = "official",
description = "",
collaborators = {
program = {},
designer = {},
cv = {},
illustrator = {},
},
dependencies = {},
extra_files = {},
}

View File

@ -1,14 +1,14 @@
#include "util.h" #include "util.h"
extern "C" { extern "C" {
int luaopen_freekill(lua_State *); int luaopen_fk(lua_State *);
} }
lua_State *CreateLuaState() lua_State *CreateLuaState()
{ {
lua_State *L = luaL_newstate(); lua_State *L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
luaopen_freekill(L); luaopen_fk(L);
return L; return L;
} }

View File

@ -1,4 +1,4 @@
%module freekill %module fk
%{ %{
#include "client.h" #include "client.h"