mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-16 11:42:45 +08:00
Heg (#242)
- 游戏结束时离线玩家增加逃率 - 退出房间时取消准备状态 - 副技能的 `main_skill` - 预亮相关优化 - 自定义身份,图从拓展包随便找一张 - 无懈可击使用时带1200毫秒延迟 - 未开始的房间显示开启的所有牌堆,衍生牌灰色字体化 - 可以随意打开fk.rep文件并播放录像 - 服务器Shell新增重置密码命令
This commit is contained in:
parent
4bee447327
commit
0745863863
|
@ -3,6 +3,7 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
import Fk
|
||||
|
||||
Item {
|
||||
|
@ -29,6 +30,12 @@ Item {
|
|||
Menu {
|
||||
id: menu
|
||||
y: bar.height
|
||||
MenuItem {
|
||||
text: qsTr("Replay from file")
|
||||
onTriggered: {
|
||||
fdialog.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +111,7 @@ Item {
|
|||
onClicked: {
|
||||
config.observing = true;
|
||||
config.replaying = true;
|
||||
Backend.playRecord(fileName);
|
||||
Backend.playRecord("recording/" + fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +129,17 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: fdialog
|
||||
nameFilters: ["FK Rep Files (*.fk.rep)"];
|
||||
onAccepted: {
|
||||
config.observing = true;
|
||||
config.replaying = true;
|
||||
let str = selectedFile.toString(); // QUrl -> string
|
||||
Backend.playRecord(str);
|
||||
}
|
||||
}
|
||||
|
||||
function updateList() {
|
||||
model.clear();
|
||||
const data = Backend.ls("recording");
|
||||
|
|
|
@ -210,22 +210,55 @@ Item {
|
|||
}
|
||||
}
|
||||
Rectangle {
|
||||
x: parent.width / 2 + 80
|
||||
y: parent.height / 2
|
||||
x: parent.width / 2 + 60
|
||||
y: parent.height / 2 - 30
|
||||
color: "snow"
|
||||
opacity: 0.8
|
||||
radius: 6
|
||||
height: childrenRect.height + 16
|
||||
width: childrenRect.width + 16
|
||||
visible: !isStarted
|
||||
width: 280
|
||||
height: 280
|
||||
|
||||
Text {
|
||||
x: 8; y: 8
|
||||
Component.onCompleted: {
|
||||
const data = JSON.parse(Backend.callLuaFunction("GetRoomConfig", []));
|
||||
text = Backend.translate("LuckCardNum") + data.luckTime + "<br />" + Backend.translate("ResponseTime") + config.roomTimeout
|
||||
+ "<br />" + Backend.translate("GeneralBoxNum") + data.generalNum + (data.enableFreeAssign ? "<br />" + Backend.translate("IncludeFreeAssign") : "")
|
||||
+ (data.enableDeputy ? "<br />" + Backend.translate("IncludeDeputy") : "")
|
||||
Flickable {
|
||||
id: flickableContainer
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 10
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
width: parent.width - 10
|
||||
height: parent.height - 10
|
||||
contentHeight: roominfo.height
|
||||
clip: true
|
||||
|
||||
Text {
|
||||
id: roominfo
|
||||
font.pixelSize: 16
|
||||
width: parent.width
|
||||
wrapMode: TextEdit.WordWrap
|
||||
Component.onCompleted: {
|
||||
const data = JSON.parse(Backend.callLuaFunction("GetRoomConfig", []));
|
||||
let cardpack = JSON.parse(Backend.callLuaFunction("GetAllCardPack", []));
|
||||
cardpack = cardpack.filter(p => !data.disabledPack.includes(p));
|
||||
|
||||
text = "游戏模式:" + Backend.translate(data.gameMode) + "<br />"
|
||||
+ Backend.translate("LuckCardNum") + "<b>" + data.luckTime + "</b><br />"
|
||||
+ Backend.translate("ResponseTime") + "<b>" + config.roomTimeout + "</b><br />"
|
||||
+ Backend.translate("GeneralBoxNum") + "<b>" + data.generalNum + "</b>"
|
||||
+ (data.enableFreeAssign ? "<br />" + Backend.translate("IncludeFreeAssign") : "")
|
||||
+ (data.enableDeputy ? " " + Backend.translate("IncludeDeputy") : "")
|
||||
+ '<br />使用牌堆:' + cardpack.map(e => {
|
||||
let ret = Backend.translate(e);
|
||||
if (ret.search(/特殊牌|衍生牌/) === -1) { // TODO: 这种东西最好还是变量名规范化= =
|
||||
ret = "<b>" + ret + "</b>";
|
||||
} else {
|
||||
ret = '<font color="grey"><i>' + ret + "</i></font>";
|
||||
}
|
||||
return ret;
|
||||
}).join(',')
|
||||
//+ '<br /><b>禁包</b>:' + data.disabledPack.map(e => Backend.translate(e)).join(',')
|
||||
//+ '<br /><b>禁将</b>:' + data.disabledGenerals.map(e => Backend.translate(e)).join(',')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ ColumnLayout {
|
|||
const data = skills.get(i);
|
||||
if (data.skillname_ === skill) {
|
||||
data.times = times;
|
||||
if (times == -1) {
|
||||
skills.remove(i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ Image {
|
|||
property var options: ["unknown", "loyalist", "rebel", "renegade"]
|
||||
|
||||
id: root
|
||||
source: visible ? SkinBank.ROLE_DIR + value : ""
|
||||
source: visible ? SkinBank.getRolePic(value) : ""
|
||||
visible: value != "hidden"
|
||||
|
||||
Image {
|
||||
|
|
|
@ -55,6 +55,7 @@ function getCardPicture(cidOrName) {
|
|||
return path;
|
||||
} else {
|
||||
for (let dir of Backend.ls(AppPath + "/packages/")) {
|
||||
if (dir.endsWith(".disabled")) continue;
|
||||
path = AppPath + "/packages/" + dir + "/image/card/" + name + ".png";
|
||||
if (Backend.exists(path)) return path;
|
||||
}
|
||||
|
@ -70,6 +71,7 @@ function getDelayedTrickPicture(name) {
|
|||
return path;
|
||||
} else {
|
||||
for (let dir of Backend.ls(AppPath + "/packages/")) {
|
||||
if (dir.endsWith(".disabled")) continue;
|
||||
path = AppPath + "/packages/" + dir + "/image/card/delayedTrick/" + name + ".png";
|
||||
if (Backend.exists(path)) return path;
|
||||
}
|
||||
|
@ -87,6 +89,7 @@ function getEquipIcon(cid, icon) {
|
|||
return path;
|
||||
} else {
|
||||
for (let dir of Backend.ls(AppPath + "/packages/")) {
|
||||
if (dir.endsWith(".disabled")) continue;
|
||||
path = AppPath + "/packages/" + dir + "/image/card/equipIcon/" + name + ".png";
|
||||
if (Backend.exists(path)) return path;
|
||||
}
|
||||
|
@ -98,6 +101,7 @@ function getPhotoBack(kingdom) {
|
|||
let path = PHOTO_BACK_DIR + kingdom + ".png";
|
||||
if (!Backend.exists(path)) {
|
||||
for (let dir of Backend.ls(AppPath + "/packages/")) {
|
||||
if (dir.endsWith(".disabled")) continue;
|
||||
path = AppPath + "/packages/" + dir + "/image/kingdom/" + kingdom + "-back.png";
|
||||
if (Backend.exists(path)) return path;
|
||||
}
|
||||
|
@ -111,6 +115,7 @@ function getGeneralCardDir(kingdom) {
|
|||
let path = GENERALCARD_DIR + kingdom + ".png";
|
||||
if (!Backend.exists(path)) {
|
||||
for (let dir of Backend.ls(AppPath + "/packages/")) {
|
||||
if (dir.endsWith(".disabled")) continue;
|
||||
path = AppPath + "/packages/" + dir + "/image/kingdom/" + kingdom + "-back.png";
|
||||
if (Backend.exists(path))
|
||||
return AppPath + "/packages/" + dir + "/image/kingdom/";
|
||||
|
@ -119,3 +124,17 @@ function getGeneralCardDir(kingdom) {
|
|||
return GENERALCARD_DIR;
|
||||
}
|
||||
}
|
||||
|
||||
function getRolePic(role) {
|
||||
let path = ROLE_DIR + role + ".png";
|
||||
if (Backend.exists(path)) {
|
||||
return path;
|
||||
} else {
|
||||
for (let dir of Backend.ls(AppPath + "/packages/")) {
|
||||
if (dir.endsWith(".disabled")) continue;
|
||||
path = AppPath + "/packages/" + dir + "/image/role/" + name + ".png";
|
||||
if (Backend.exists(path)) return path;
|
||||
}
|
||||
}
|
||||
return ROLE_DIR + "unknown.png";
|
||||
}
|
||||
|
|
|
@ -585,21 +585,6 @@ fk.client_callback["ShowCard"] = function(jsonData)
|
|||
})
|
||||
end
|
||||
|
||||
fk.client_callback["LoseSkill"] = function(jsonData)
|
||||
-- jsonData: [ int player_id, string skill_name ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, skill_name, prelight = data[1], data[2], data[3]
|
||||
local target = ClientInstance:getPlayerById(id)
|
||||
local skill = Fk.skills[skill_name]
|
||||
if not prelight then
|
||||
target:loseSkill(skill)
|
||||
end
|
||||
|
||||
if skill.visible then
|
||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
||||
end
|
||||
end
|
||||
|
||||
-- 说是限定技,其实也适用于觉醒技、转换技、使命技
|
||||
---@param skill Skill
|
||||
---@param times integer
|
||||
|
@ -613,15 +598,99 @@ local function updateLimitSkill(pid, skill, times)
|
|||
end
|
||||
end
|
||||
|
||||
fk.client_callback["LoseSkill"] = function(jsonData)
|
||||
-- jsonData: [ int player_id, string skill_name ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, skill_name, fake = data[1], data[2], data[3]
|
||||
local target = ClientInstance:getPlayerById(id)
|
||||
local skill = Fk.skills[skill_name]
|
||||
|
||||
if not fake then
|
||||
target:loseSkill(skill)
|
||||
if skill.visible then
|
||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
||||
end
|
||||
elseif skill.visible then
|
||||
-- 按理说能弄得更好的但还是复制粘贴舒服
|
||||
local sks = { table.unpack(skill.related_skills) }
|
||||
--[[ 需要大伙都适配好main_skill或者讨论出更好方案才行。不敢轻举妄动
|
||||
local sks = table.filter(skill.related_skills, function(s)
|
||||
return s.main_skill == skill
|
||||
end)
|
||||
--]]
|
||||
table.insert(sks, skill)
|
||||
table.removeOne(target.player_skills, skill)
|
||||
local chk = false
|
||||
|
||||
if table.find(sks, function(s) return s:isInstanceOf(TriggerSkill) end) then
|
||||
chk = true
|
||||
ClientInstance:notifyUI("LoseSkill", jsonData)
|
||||
end
|
||||
|
||||
local active = table.filter(sks, function(s)
|
||||
return s:isInstanceOf(ActiveSkill) or s:isInstanceOf(ViewAsSkill)
|
||||
end)
|
||||
|
||||
if #active > 0 then
|
||||
chk = true
|
||||
ClientInstance:notifyUI("LoseSkill", json.encode {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
|
||||
if not chk then
|
||||
ClientInstance:notifyUI("LoseSkill", json.encode {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
updateLimitSkill(id, skill, -1)
|
||||
end
|
||||
|
||||
fk.client_callback["AddSkill"] = function(jsonData)
|
||||
-- jsonData: [ int player_id, string skill_name ]
|
||||
local data = json.decode(jsonData)
|
||||
local id, skill_name = data[1], data[2]
|
||||
local id, skill_name, fake = data[1], data[2], data[3]
|
||||
local target = ClientInstance:getPlayerById(id)
|
||||
local skill = Fk.skills[skill_name]
|
||||
target:addSkill(skill)
|
||||
if skill.visible then
|
||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
||||
|
||||
if not fake then
|
||||
target:addSkill(skill)
|
||||
if skill.visible then
|
||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
||||
end
|
||||
elseif skill.visible then
|
||||
-- 添加假技能:服务器只会传一个主技能来。
|
||||
-- 若有主动技则添加按钮,若有触发技则添加预亮按钮。
|
||||
-- 无视状态技。
|
||||
local sks = { table.unpack(skill.related_skills) }
|
||||
table.insert(sks, skill)
|
||||
table.insert(target.player_skills, skill)
|
||||
local chk = false
|
||||
|
||||
if table.find(sks, function(s) return s:isInstanceOf(TriggerSkill) end) then
|
||||
chk = true
|
||||
ClientInstance:notifyUI("AddSkill", jsonData)
|
||||
end
|
||||
|
||||
local active = table.filter(sks, function(s)
|
||||
return s:isInstanceOf(ActiveSkill) or s:isInstanceOf(ViewAsSkill)
|
||||
end)
|
||||
|
||||
if #active > 0 then
|
||||
chk = true
|
||||
ClientInstance:notifyUI("AddSkill", json.encode {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
|
||||
-- 面板上总得有点啥东西表明自己有技能吧 = =
|
||||
if not chk then
|
||||
ClientInstance:notifyUI("AddSkill", json.encode {
|
||||
id, skill_name,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if skill.frequency == Skill.Quest then
|
||||
|
|
|
@ -678,6 +678,13 @@ function Player:hasSkill(skill, ignoreNullified, ignoreAlive)
|
|||
return true
|
||||
end
|
||||
|
||||
if self:isInstanceOf(ServerPlayer) and -- isInstanceOf(nil) will return false
|
||||
table.contains(self._fake_skills, skill) and
|
||||
table.contains(self.prelighted_skills, skill) then
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
for _, v in pairs(self.derivative_skills) do
|
||||
if table.contains(v, skill) then
|
||||
return true
|
||||
|
|
|
@ -56,8 +56,15 @@ end
|
|||
-- do cost and skill effect.
|
||||
-- DO NOT modify this function
|
||||
function TriggerSkill:doCost(event, target, player, data)
|
||||
local start_time = os.getms()
|
||||
local ret = self:cost(event, target, player, data)
|
||||
local end_time = os.getms()
|
||||
|
||||
local room = player.room
|
||||
-- 对于那种cost直接返回true的锁定技,如果是预亮技,那么还是询问一下好
|
||||
if ret and player:isFakeSkill(self) and end_time - start_time < 10000 then
|
||||
ret = room:askForSkillInvoke(player, self.name)
|
||||
end
|
||||
|
||||
local cost_data_bak = self.cost_data
|
||||
room.logic:trigger(fk.BeforeTriggerSkillUse, player, { skill = self, willUse = ret })
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
---@class UsableSkill : Skill
|
||||
---@field public main_skill UsableSkill
|
||||
---@field public max_use_time integer[]
|
||||
---@field public expand_pile string
|
||||
local UsableSkill = Skill:subclass("UsableSkill")
|
||||
|
|
|
@ -42,6 +42,8 @@ end
|
|||
|
||||
local function readUsableSpecToSkill(skill, spec)
|
||||
readCommonSpecToSkill(skill, spec)
|
||||
assert(spec.main_skill == nil or spec.main_skill:isInstanceOf(UsableSkill))
|
||||
skill.main_skill = spec.main_skill
|
||||
skill.target_num = spec.target_num or skill.target_num
|
||||
skill.min_target_num = spec.min_target_num or skill.min_target_num
|
||||
skill.max_target_num = spec.max_target_num or skill.max_target_num
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
-- SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
GameEvent.functions[GameEvent.SkillEffect] = function(self)
|
||||
local effect_cb, player, skill = table.unpack(self.data)
|
||||
local effect_cb, player, _skill = table.unpack(self.data)
|
||||
local room = self.room
|
||||
local logic = room.logic
|
||||
local skill = _skill.main_skill and _skill.main_skill or _skill
|
||||
|
||||
if player then
|
||||
player:addSkillUseHistory(skill.name)
|
||||
end
|
||||
|
||||
local cost_data_bak = skill.cost_data
|
||||
logic:trigger(fk.SkillEffect, player, skill)
|
||||
|
|
|
@ -829,6 +829,15 @@ function Room:notifyMoveFocus(players, command)
|
|||
table.insert(ids, p.id)
|
||||
end
|
||||
|
||||
local tempSk = Fk.skills[command]
|
||||
if tempSk and #players == 1 then
|
||||
local p = players[1]
|
||||
if p:isFakeSkill(tempSk) then
|
||||
command = ""
|
||||
ids = table.map(self.alive_players, Util.IdMapper)
|
||||
end
|
||||
end
|
||||
|
||||
self:doBroadcastNotify("MoveFocus", json.encode{
|
||||
ids,
|
||||
command
|
||||
|
@ -2987,7 +2996,6 @@ function Room:useSkill(player, skill, effect_cb)
|
|||
player:getSwitchSkillState(switchSkillName, true)
|
||||
)
|
||||
end
|
||||
player:addSkillUseHistory(skill.name)
|
||||
|
||||
if effect_cb then
|
||||
return execGameEvent(GameEvent.SkillEffect, effect_cb, player, skill)
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
---@field public phase_state table[]
|
||||
---@field public phase_index integer
|
||||
---@field public role_shown boolean
|
||||
---@field private _fake_skills Skill[]
|
||||
---@field public prelighted_skills Skill[]
|
||||
---@field private _timewaste_count integer
|
||||
---@field public ai AI
|
||||
---@field public ai_data any
|
||||
|
@ -35,6 +37,11 @@ function ServerPlayer:initialize(_self)
|
|||
self.reply_cancel = false
|
||||
self.phases = {}
|
||||
self.skipped_phases = {}
|
||||
|
||||
self._fake_skills = {}
|
||||
self.prelighted_skills = {}
|
||||
self._prelighted_skills = {}
|
||||
|
||||
self._timewaste_count = 0
|
||||
self.ai = RandomAI:new(self)
|
||||
end
|
||||
|
@ -702,13 +709,70 @@ end
|
|||
|
||||
-- Hegemony func
|
||||
|
||||
---@param skill Skill
|
||||
function ServerPlayer:addFakeSkill(skill)
|
||||
assert(skill:isInstanceOf(Skill))
|
||||
if table.contains(self._fake_skills, skill) then return end
|
||||
|
||||
table.insert(self._fake_skills, skill)
|
||||
for _, s in ipairs(skill.related_skills) do
|
||||
-- if s.main_skill == skill then -- TODO: need more detailed
|
||||
table.insert(self._fake_skills, s)
|
||||
-- end
|
||||
end
|
||||
|
||||
-- TODO
|
||||
self:doNotify("AddSkill", json.encode{ self.id, skill.name, true })
|
||||
end
|
||||
|
||||
---@param skill Skill
|
||||
function ServerPlayer:loseFakeSkill(skill)
|
||||
assert(skill:isInstanceOf(Skill))
|
||||
if not table.contains(self._fake_skills, skill) then return end
|
||||
|
||||
table.removeOne(self._fake_skills, skill)
|
||||
for _, s in ipairs(skill.related_skills) do
|
||||
table.removeOne(self._fake_skills, s)
|
||||
end
|
||||
|
||||
-- TODO
|
||||
self:doNotify("LoseSkill", json.encode{ self.id, skill.name, true })
|
||||
end
|
||||
|
||||
function ServerPlayer:isFakeSkill(skill)
|
||||
if type(skill) == "string" then skill = Fk.skills[skill] end
|
||||
assert(skill:isInstanceOf(Skill))
|
||||
return table.contains(self._fake_skills, skill)
|
||||
end
|
||||
|
||||
---@param skill string | Skill
|
||||
---@param isPrelight boolean | nil
|
||||
function ServerPlayer:prelightSkill(skill, isPrelight)
|
||||
if isPrelight then
|
||||
if type(skill) == "string" then skill = Fk.skills[skill] end
|
||||
assert(skill:isInstanceOf(Skill))
|
||||
|
||||
if not self._prelighted_skills[skill] and not self:hasSkill(skill) then
|
||||
self._prelighted_skills[skill] = true
|
||||
-- to attach skill to room
|
||||
self:addSkill(skill)
|
||||
else
|
||||
self:loseSkill(skill)
|
||||
end
|
||||
self:doNotify("PrelightSkill", json.encode{ skill, isPrelight })
|
||||
|
||||
if isPrelight then
|
||||
-- self:addSkill(skill)
|
||||
table.insert(self.prelighted_skills, skill)
|
||||
for _, s in ipairs(skill.related_skills) do
|
||||
table.insert(self.prelighted_skills, s)
|
||||
end
|
||||
else
|
||||
-- self:loseSkill(skill)
|
||||
table.removeOne(self.prelighted_skills, skill)
|
||||
for _, s in ipairs(skill.related_skills) do
|
||||
table.removeOne(self.prelighted_skills, s)
|
||||
end
|
||||
end
|
||||
|
||||
self:doNotify("PrelightSkill", json.encode{ skill.name, isPrelight })
|
||||
end
|
||||
|
||||
function ServerPlayer:revealGeneral(isDeputy)
|
||||
|
@ -725,10 +789,7 @@ function ServerPlayer:revealGeneral(isDeputy)
|
|||
local general = Fk.generals[generalName]
|
||||
for _, s in ipairs(general:getSkillNameList()) do
|
||||
local skill = Fk.skills[s]
|
||||
if skill:isInstanceOf(TriggerSkill) or table.find(skill.related_skills,
|
||||
function(s) return s:isInstanceOf(TriggerSkill) end) then
|
||||
self:doNotify("LoseSkill", json.encode{ self.id, s, true })
|
||||
end
|
||||
self:loseFakeSkill(skill)
|
||||
end
|
||||
|
||||
local oldKingdom = self.kingdom
|
||||
|
|
|
@ -229,13 +229,7 @@ function HegLogic:attachSkillToPlayers()
|
|||
return
|
||||
end
|
||||
|
||||
-- room:handleAddLoseSkills(player, skillName, nil, false)
|
||||
player:doNotify("AddSkill", json.encode{ player.id, skillName })
|
||||
|
||||
if skill:isInstanceOf(TriggerSkill) or table.find(skill.related_skills,
|
||||
function(s) return s:isInstanceOf(TriggerSkill) end) then
|
||||
player:doNotify("AddSkill", json.encode{ player.id, skillName, true })
|
||||
end
|
||||
player:addFakeSkill(skill)
|
||||
end
|
||||
|
||||
for _, p in ipairs(room.alive_players) do
|
||||
|
|
|
@ -413,6 +413,7 @@ local nullificationSkill = fk.CreateActiveSkill{
|
|||
can_use = function()
|
||||
return false
|
||||
end,
|
||||
on_use = function() RoomInstance:delay(1200) end,
|
||||
on_effect = function(self, room, effect)
|
||||
if effect.responseToEvent then
|
||||
effect.responseToEvent.isCancellOut = true
|
||||
|
|
|
@ -11,7 +11,12 @@ Replayer::Replayer(QObject *parent, const QString &filename) :
|
|||
{
|
||||
setObjectName("Replayer");
|
||||
|
||||
QFile file("recording/" + filename);
|
||||
auto s = filename;
|
||||
#ifdef Q_OS_WIN
|
||||
if (s.startsWith("file:///"))
|
||||
s.replace(0, 8, "file://");
|
||||
#endif
|
||||
QFile file(QUrl(s).path());
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QByteArray raw = file.readAll();
|
||||
file.close();
|
||||
|
|
|
@ -234,6 +234,7 @@ void Room::removePlayer(ServerPlayer *player) {
|
|||
if (!gameStarted) {
|
||||
// 游戏还没开始的话,直接删除这名玩家
|
||||
if (players.contains(player) && !players.isEmpty()) {
|
||||
player->setReady(false);
|
||||
players.removeOne(player);
|
||||
}
|
||||
emit playerRemoved(player);
|
||||
|
@ -533,10 +534,15 @@ void Room::gameOver() {
|
|||
gameStarted = false;
|
||||
runned_players.clear();
|
||||
// 清理所有状态不是“在线”的玩家
|
||||
auto settings = QJsonDocument::fromJson(this->settings);
|
||||
auto mode = settings["gameMode"].toString();
|
||||
foreach (ServerPlayer *p, players) {
|
||||
if (p->getState() != Player::Online) {
|
||||
if (p->getState() == Player::Offline) {
|
||||
server->temporarilyBan(p->getId());
|
||||
auto pid = p->getId();
|
||||
addRunRate(pid, mode);
|
||||
addRunRate(pid, mode);
|
||||
server->temporarilyBan(pid);
|
||||
}
|
||||
p->deleteLater();
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ void Shell::helpCommand(QStringList &) {
|
|||
HELP_MSG("%s: Crash the server. Useful when encounter dead loop.", "crash");
|
||||
HELP_MSG("%s: List all online players.", "lsplayer");
|
||||
HELP_MSG("%s: List all running rooms.", "lsroom");
|
||||
HELP_MSG("%s: Reload server config file.", "reloadconf");
|
||||
HELP_MSG("%s: Reload server config file.", "reloadconf/r");
|
||||
HELP_MSG("%s: Kick a player by his <id>.", "kick");
|
||||
HELP_MSG("%s: Broadcast message.", "msg");
|
||||
HELP_MSG("%s: Broadcast message.", "msg/m");
|
||||
HELP_MSG("%s: Ban 1 or more accounts, IP, UUID by their <name>.", "ban");
|
||||
HELP_MSG("%s: Unban 1 or more accounts by their <name>.", "unban");
|
||||
HELP_MSG(
|
||||
|
@ -49,6 +49,7 @@ void Shell::helpCommand(QStringList &) {
|
|||
"%s: Unban 1 or more UUID. "
|
||||
"At least 1 <name> required.",
|
||||
"unbanuuid");
|
||||
HELP_MSG("%s: reset <name>'s password to 1234.", "resetpassword/rp");
|
||||
qInfo();
|
||||
qInfo("===== Package commands =====");
|
||||
HELP_MSG("%s: Install a new package from <url>.", "install");
|
||||
|
@ -56,7 +57,7 @@ void Shell::helpCommand(QStringList &) {
|
|||
HELP_MSG("%s: List all packages.", "lspkg");
|
||||
HELP_MSG("%s: Enable a package.", "enable");
|
||||
HELP_MSG("%s: Disable a package.", "disable");
|
||||
HELP_MSG("%s: Upgrade a package. Leave empty to upgrade all.", "upgrade");
|
||||
HELP_MSG("%s: Upgrade a package. Leave empty to upgrade all.", "upgrade/u");
|
||||
qInfo("For more commands, check the documentation.");
|
||||
|
||||
#undef HELP_MSG
|
||||
|
@ -356,6 +357,21 @@ void Shell::reloadConfCommand(QStringList &) {
|
|||
qInfo("Reloaded server config file.");
|
||||
}
|
||||
|
||||
void Shell::resetPasswordCommand(QStringList &list) {
|
||||
if (list.isEmpty()) {
|
||||
qWarning("The 'resetpassword' command needs at least 1 <name>.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto db = ServerInstance->getDatabase();
|
||||
foreach (auto name, list) {
|
||||
// 重置为1234
|
||||
ExecSQL(db, QString("UPDATE userinfo SET password=\
|
||||
'dbdc2ad3d9625407f55674a00b58904242545bfafedac67485ac398508403ade',\
|
||||
salt='00000000' WHERE name='%1';").arg(name));
|
||||
}
|
||||
}
|
||||
|
||||
Shell::Shell() {
|
||||
setObjectName("Shell");
|
||||
signal(SIGINT, sigintHandler);
|
||||
|
@ -369,11 +385,13 @@ Shell::Shell() {
|
|||
handlers["install"] = &Shell::installCommand;
|
||||
handlers["remove"] = &Shell::removeCommand;
|
||||
handlers["upgrade"] = &Shell::upgradeCommand;
|
||||
handlers["u"] = &Shell::upgradeCommand;
|
||||
handlers["lspkg"] = &Shell::lspkgCommand;
|
||||
handlers["enable"] = &Shell::enableCommand;
|
||||
handlers["disable"] = &Shell::disableCommand;
|
||||
handlers["kick"] = &Shell::kickCommand;
|
||||
handlers["msg"] = &Shell::msgCommand;
|
||||
handlers["m"] = &Shell::msgCommand;
|
||||
handlers["ban"] = &Shell::banCommand;
|
||||
handlers["unban"] = &Shell::unbanCommand;
|
||||
handlers["banip"] = &Shell::banipCommand;
|
||||
|
@ -381,6 +399,9 @@ Shell::Shell() {
|
|||
handlers["banuuid"] = &Shell::banUuidCommand;
|
||||
handlers["unbanuuid"] = &Shell::unbanUuidCommand;
|
||||
handlers["reloadconf"] = &Shell::reloadConfCommand;
|
||||
handlers["r"] = &Shell::reloadConfCommand;
|
||||
handlers["resetpassword"] = &Shell::resetPasswordCommand;
|
||||
handlers["rp"] = &Shell::resetPasswordCommand;
|
||||
}
|
||||
handler_map = handlers;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ private:
|
|||
void unbanipCommand(QStringList &);
|
||||
void unbanUuidCommand(QStringList &);
|
||||
void reloadConfCommand(QStringList &);
|
||||
void resetPasswordCommand(QStringList &);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user