Skip to content

Commit

Permalink
单机热更新,以及Docker (Qsgs-Fans#336)
Browse files Browse the repository at this point in the history
以及emo公主的判定小卡换图

---------

Co-authored-by: seven <[email protected]>
  • Loading branch information
Notify-ctrl and seven committed Apr 1, 2024
1 parent e840a3b commit 9dd4f55
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 44 deletions.
39 changes: 26 additions & 13 deletions Fk/Cheat/PlayerDetail.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Fk.Common
import Fk.Pages
import Fk.RoomElement

Expand All @@ -22,18 +23,29 @@ Flickable {
width: parent.width - 40
x: 20

// TODO: player details
Text {
id: screenName
font.pixelSize: 18
color: "#E4D5A0"
}
RowLayout {
spacing: 8
Avatar {
id: avatar
Layout.preferredWidth: 56
Layout.preferredHeight: 56
general: "diaochan"
}

ColumnLayout {
Text {
id: screenName
font.pixelSize: 18
color: "#E4D5A0"
}

Text {
id: playerGameData
Layout.fillWidth: true
font.pixelSize: 18
color: "#E4D5A0"
Text {
id: playerGameData
Layout.fillWidth: true
font.pixelSize: 18
color: "#E4D5A0"
}
}
}

RowLayout {
Expand Down Expand Up @@ -163,6 +175,7 @@ Flickable {
if (id === 0) return;
root.pid = id;

avatar.general = extra_data.photo.avatar;
screenName.text = extra_data.photo.screenName;
mainChara.name = extra_data.photo.general;
deputyChara.name = extra_data.photo.deputyGeneral;
Expand All @@ -182,9 +195,9 @@ Flickable {
const h = (totalTime / 3600).toFixed(2);
const m = Math.floor(totalTime / 60);
if (m < 100) {
playerGameData.text += " " + luatr("TotalGameTime: %1 min").arg(m);
screenName.text += " (" + luatr("TotalGameTime: %1 min").arg(m) + ")";
} else {
playerGameData.text += " " + luatr("TotalGameTime: %1 h").arg(h);
screenName.text += " (" + luatr("TotalGameTime: %1 h").arg(h) + ")";
}
}

Expand Down
42 changes: 23 additions & 19 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
FROM debian
USER root

FROM linuxcontainers/debian-slim:latest

# install dependencies
RUN apt update -y && apt upgrade -y && \
apt install -y \
gcc g++ cmake \
liblua5.4-dev libsqlite3-dev libreadline-dev libssl-dev libgit2-dev swig qt6-base-dev qt6-tools-dev-tools \
gosu && \
apt clean -y && \
rm -rf /var/lib/apt/lists/*

# prepare source code
COPY . /FreeKill

#update apt dependencies
RUN apt update -y && apt upgrade -y

#install compile tools
RUN apt install -y gcc g++ cmake
RUN apt install -y liblua5.4-dev libsqlite3-dev libreadline-dev libssl-dev libgit2-dev swig qt6-base-dev qt6-tools-dev-tools

#change workdir to FreeKill
WORKDIR /FreeKill
# compile and install
RUN mkdir -p /FreeKill/build && \
cd /FreeKill/build && cp -r /usr/include/lua5.4/* ../include && cmake .. -DFK_SERVER_ONLY= && make && \
cd /FreeKill && cmake --install build --config Release && \
cp /FreeKill/docker/docker-entrypoint.sh / && chmod +x /docker-entrypoint.sh && \
mkdir /data && \
cd / && rm -rf /FreeKill

#compile source code
RUN mkdir build && cd build && cp -r /usr/include/lua5.4/* ../include && cmake .. -DFK_SERVER_ONLY=
RUN cd build && make

#build soft link
RUN ln -s build/FreeKill
WORKDIR /data

EXPOSE 9527

ENTRYPOINT ["/FreeKill/FreeKill", "-s"]
ENTRYPOINT ["/docker-entrypoint.sh"]

CMD ["FreeKill", "-s"]
29 changes: 29 additions & 0 deletions docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

USER_ID=${LOCAL_USER_ID:-1000}

if [ "${1#-}" != "$1" ]; then
set -- FreeKill -s "$@"
fi

if [ "$1" = 'FreeKill' -a "$(id -u)" = '0' ]; then
id -u freekill >&/dev/null
if [ $? -ne 0 ]; then
useradd --shell /bin/bash -u $USER_ID -o -c "" -m freekill
usermod -aG root freekill
export HOME=/home/freekill
mkdir -p $HOME/.local/share
ln -s /data $HOME/.local/share/FreeKill
chown -R freekill:freekill $HOME
if [ ! -d "/data/server" ]; then
cp -r /usr/local/share/FreeKill/server /data
fi
if [ ! -d "/data/packages" ]; then
cp -r /usr/local/share/FreeKill/packages /data
fi
fi
chown -R freekill /data
exec gosu freekill "$0" "$@"
fi

exec "$@"
Binary file modified image/card/delayedTrick/unknown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions lua/client/client_util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -784,4 +784,8 @@ function GetMiniGame(gtype, p, data)
}
end

function ReloadPackage(path)
Fk:reloadPackage(path)
end

dofile "lua/client/i18n/init.lua"
73 changes: 71 additions & 2 deletions lua/core/engine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ function Engine:initialize()
end

Fk = self

self.extensions = {
["standard"] = { "standard" },
["standard_cards"] = { "standard_cards" },
Expand Down Expand Up @@ -123,6 +122,76 @@ function Engine:loadPackage(pack)
self:addGameModes(pack.game_modes)
end

-- Don't do this
local package = package
function Engine:reloadPackage(path)
path = path:sub(1, #path - 4)
local oldPkg = package.loaded[path]
package.loaded[path] = nil
local ok, err = pcall(require, path)
if not ok then
package.loaded[path] = oldPkg
print("reload failed:", err)
return
end

-- 阉割版重载机制,反正单机用
local function replace(t, skill)
if not t then return end
for k, s in pairs(t) do
if s.name == skill.name then
t[k] = skill
break
end
end
end

local function f(p)
self.packages[p.name] = p
local room = Fk:currentRoom()
local skills = p:getSkills()
local related = {}
for _, skill in ipairs(skills) do
table.insertTableIfNeed(related, skill.related_skills)
end
table.insertTableIfNeed(skills, related)

for _, skill in ipairs(skills) do
if self.skills[skill.name].class ~= skill.class then
fk.qCritical("cannot change class of skill: " .. skill.name)
goto CONTINUE
end
self.skills[skill.name] = skill
if skill:isInstanceOf(TriggerSkill) and RoomInstance then
local logic = room.logic
for _, event in ipairs(skill.refresh_events) do
replace(logic.refresh_skill_table[event], skill)
end
for _, event in ipairs(skill.events) do
replace(logic.skill_table[event], skill)
end
end
if skill:isInstanceOf(StatusSkill) then
replace(room.status_skills[skill.class], skill)
end

for _, p in ipairs(room.players) do
replace(p.player_skills, skill)
end
::CONTINUE::
end
end

local pkg = package.loaded[path]
if type(pkg) ~= "table" then return end
if pkg.class and pkg:isInstanceOf(Package) then
f(pkg)
elseif path:endsWith("init") and not path:find("/ai/") then
for _, p in ipairs(pkg) do f(p) end
end
end


--- 加载所有拓展包。
---
--- Engine会在packages/下搜索所有含有init.lua的文件夹,并把它们作为拓展包加载进来。
Expand Down Expand Up @@ -215,7 +284,7 @@ end
function Engine:addSkill(skill)
assert(skill.class:isSubclassOf(Skill))
if self.skills[skill.name] ~= nil then
error(string.format("Duplicate skill %s detected", skill.name))
fk.qWarning(string.format("Duplicate skill %s detected", skill.name))
end
self.skills[skill.name] = skill

Expand Down
3 changes: 3 additions & 0 deletions lua/server/ai/random_ai.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ function RandomAI:useActiveSkill(skill, card)
local room = self.room
local player = self.player

if skill:isInstanceOf(ViewAsSkill) then return "" end

local filter_func = skill.cardFilter
if card then
filter_func = Util.FalseFunc
Expand Down Expand Up @@ -68,6 +70,7 @@ function RandomAI:useVSSkill(skill, pattern, cancelable, extra_data)
local player = self.player
local room = self.room
local precondition
if not skill then return nil end

if self.command == "PlayCard" then
precondition = skill:enabledAtPlay(player)
Expand Down
6 changes: 6 additions & 0 deletions lua/server/request.lua
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ request_handlers["newroom"] = function(s, id)
s:registerRoom(id)
end

request_handlers["reloadpackage"] = function(room, id, reqlist)
if not IsConsoleStart() then return end
local path = reqlist[3]
Fk:reloadPackage(path)
end

-- 处理异步请求的协程,本身也是个死循环就是了。
-- 为了适应调度器,目前又暂且将请求分为“耗时请求”和不耗时请求。
-- 耗时请求处理后会立刻挂起。不耗时的请求则会不断处理直到请求队列空后再挂起。
Expand Down
4 changes: 4 additions & 0 deletions lua/server/scheduler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,7 @@ function InitScheduler(_thread)
requestRoom.thread = _thread
Pcall(mainLoop)
end

function IsConsoleStart()
return requestRoom.thread:isConsoleStart()
end
22 changes: 22 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,25 @@ target_link_libraries(FreeKill PRIVATE
)

install(TARGETS FreeKill DESTINATION bin)
install(DIRECTORY
${PROJECT_SOURCE_DIR}/audio
${PROJECT_SOURCE_DIR}/fonts
${PROJECT_SOURCE_DIR}/image
${PROJECT_SOURCE_DIR}/lua
${PROJECT_SOURCE_DIR}/packages
${PROJECT_SOURCE_DIR}/Fk
${PROJECT_SOURCE_DIR}/server
DESTINATION share/FreeKill
)
install(FILES
${PROJECT_SOURCE_DIR}/fk_ver
DESTINATION share/FreeKill
)

if (NOT DEFINED FK_SERVER_ONLY)
install(FILES
${CMAKE_BINARY_DIR}/zh_CN.qm
${CMAKE_BINARY_DIR}/en_US.qm
DESTINATION share/FreeKill
)
endif()
51 changes: 50 additions & 1 deletion src/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
#include "client.h"
#include "client_socket.h"
#include "clientplayer.h"
#include "qmlbackend.h"
#include "util.h"
#include "server.h"
#include <qforeach.h>
#include <qlogging.h>

Client *ClientInstance = nullptr;
ClientPlayer *Self = nullptr;
Expand Down Expand Up @@ -78,7 +82,10 @@ void Client::changeSelf(int id) {

lua_State *Client::getLuaState() { return L; }

void Client::installAESKey(const QByteArray &key) { router->installAESKey(key); }
void Client::installAESKey(const QByteArray &key) {
startWatchFiles();
router->installAESKey(key);
}

void Client::saveRecord(const QString &json, const QString &fname) {
if (!QDir("recording").exists()) {
Expand All @@ -90,6 +97,48 @@ void Client::saveRecord(const QString &json, const QString &fname) {
c.close();
}

bool Client::isConsoleStart() const {
if (!ClientInstance || !ServerInstance) {
return false;
}

return router->isConsoleStart();
}

void Client::startWatchFiles() {
if (!isConsoleStart()) return;
if (!fsWatcher.files().empty()) return;
QFile flist("flist.txt");
if (!flist.open(QIODevice::ReadOnly)) {
qCritical("Cannot open flist.txt. Won't watch files.");
fsWatcher.addPath("fk_ver"); // dummy
}
auto md5pairs = flist.readAll().split(';');
foreach (auto md5, md5pairs) {
if (md5.isEmpty()) continue;
auto fname = md5.split('=')[0];
if (fname.startsWith("packages") && fname.endsWith(".lua")) {
fsWatcher.addPath(fname);
}
}
connect(&fsWatcher, &QFileSystemWatcher::fileChanged, this,
&Client::updateLuaFiles);
}

void Client::processReplay(const QString &c, const QString &j) {
callLua(c, j);
}

void Client::updateLuaFiles(const QString &path) {
if (!isConsoleStart()) return;
Backend->showToast(tr("File %1 changed, reloading...").arg(path));
QThread::msleep(100);
Backend->callLuaFunction("ReloadPackage", { path });
ClientInstance->notifyServer("PushRequest",
QString("reloadpackage,%1").arg(path));

// according to QT documentation
if (!fsWatcher.files().contains(path) && QFile::exists(path)) {
fsWatcher.addPath(path);
}
}
Loading

0 comments on commit 9dd4f55

Please sign in to comment.