From 0325c734434046d3fdaecaab25b16f336b83ca02 Mon Sep 17 00:00:00 2001 From: notify Date: Wed, 3 Jul 2024 01:31:22 +0800 Subject: [PATCH] Serverlist (#360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 服务器列表 - 重制了之前的加入服务器与保存密码的页面,以及功能 - 密码在本地以明文保存 - 根据游戏目录中的server-list.json读取公共服务器列表,还没做自动更新 - 可能有不少bug --- .gitignore | 1 + CMakeLists.txt | 2 +- Fk/Config.qml | 47 ++- Fk/Logic.js | 43 +-- Fk/Pages/Init.qml | 12 +- Fk/Pages/JoinServer.qml | 507 +++++++++++++--------------- Fk/skin-bank.js | 1 + android/AndroidManifest.xml | 4 +- freekill.server.config.json.example | 2 +- image/misc/favorite.png | Bin 0 -> 4345 bytes image/misc/network_local.png | Bin 0 -> 1722 bytes image/misc/server_icon.png | Bin 0 -> 3791 bytes lang/en_US.ts | 2 +- lang/zh_CN.ts | 2 +- src/server/server.cpp | 2 +- src/ui/qmlbackend.cpp | 39 ++- src/ui/qmlbackend.h | 5 +- 17 files changed, 356 insertions(+), 313 deletions(-) create mode 100644 image/misc/favorite.png create mode 100644 image/misc/network_local.png create mode 100644 image/misc/server_icon.png diff --git a/.gitignore b/.gitignore index 449381e9..e98194ec 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ freekill-wrap.cxx /freekill.server.error.log /freekill.server.info.log /flist.txt +/server-list.json # windeployqt /bearer/ diff --git a/CMakeLists.txt b/CMakeLists.txt index da082a00..500a8dc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.16) -project(FreeKill VERSION 0.4.18) +project(FreeKill VERSION 0.4.19) add_definitions(-DFK_VERSION=\"${CMAKE_PROJECT_VERSION}\") find_package(Qt6 REQUIRED COMPONENTS diff --git a/Fk/Config.qml b/Fk/Config.qml index 452a0e09..cc8babcc 100644 --- a/Fk/Config.qml +++ b/Fk/Config.qml @@ -10,7 +10,8 @@ QtObject { property real winHeight property var conf: ({}) property string lastLoginServer - property var savedPassword: ({}) + //property var savedPassword: ({}) + property var favoriteServers: [] property string lobbyBg property string roomBg property string bgmFile @@ -39,6 +40,7 @@ QtObject { // Player property of client property string serverAddr + property int serverPort property string screenName: "" property string password: "" property string cipherText @@ -63,6 +65,43 @@ QtObject { // disableGeneralSchemes[disableSchemeIdx] = disabledGenerals; // } + function findFavorite(addr, port) { + for (const s of favoriteServers) { + if (s.addr === addr && s.port === port) { + return s; + } + } + return undefined; + } + + function removeFavorite(addr, port) { + for (const i in favoriteServers) { + const s = favoriteServers[i]; + if (s.addr === addr && s.port === port) { + favoriteServers.splice(i, 1); + saveConf(); + return; + } + } + } + + function addFavorite(addr, port, name, username, password) { + for (const i in favoriteServers) { + const s = favoriteServers[i]; + if (s.addr === addr && s.port === port) { + s.name = name; + s.username = username; + s.password = password; + saveConf(); + return false; + } + } + favoriteServers.unshift({ addr, port, name, username, password }); + saveConf(); + return true; + } + + function loadConf() { conf = JSON.parse(Backend.loadConf()); winX = conf.winX ?? 100; @@ -70,7 +109,8 @@ QtObject { winWidth = conf.winWidth ?? 960; winHeight = conf.winHeight ?? 540; lastLoginServer = conf.lastLoginServer ?? "127.0.0.1"; - savedPassword = conf.savedPassword ?? {}; + //savedPassword = conf.savedPassword ?? {}; + favoriteServers = conf.favoriteServers ?? []; lobbyBg = conf.lobbyBg ?? AppPath + "/image/background"; roomBg = conf.roomBg ?? AppPath + "/image/gamebg"; bgmFile = conf.bgmFile ?? AppPath + "/audio/system/bgm.mp3"; @@ -116,7 +156,8 @@ QtObject { conf.winWidth = realMainWin.width; conf.winHeight = realMainWin.height; conf.lastLoginServer = lastLoginServer; - conf.savedPassword = savedPassword; + //conf.savedPassword = savedPassword; + conf.favoriteServers = favoriteServers; conf.lobbyBg = lobbyBg; conf.roomBg = roomBg; conf.bgmFile = bgmFile; diff --git a/Fk/Logic.js b/Fk/Logic.js index b098e7ef..c0446a0a 100644 --- a/Fk/Logic.js +++ b/Fk/Logic.js @@ -26,7 +26,8 @@ callbacks["ServerDetected"] = (j) => { } const item = serverDialog.item; if (item) { - toast.show(qsTr("Detected Server %1").arg(j.slice(7)), 10000); + // toast.show(qsTr("Detected Server %1").arg(j.slice(7)), 10000); + item.addLANServer(j.slice(7)) } } @@ -38,7 +39,9 @@ callbacks["GetServerDetail"] = (j) => { } const item = serverDialog.item; if (item) { - item.updateServerDetail(addr, [ver, icon, desc, capacity, count]); + let [_addr, port] = addr.split(','); + port = parseInt(port); + item.updateServerDetail(_addr, port, [ver, icon, desc, capacity, count]); } } @@ -46,18 +49,18 @@ callbacks["NetworkDelayTest"] = (jsonData) => { // jsonData: RSA pub key let cipherText; let aeskey; - const savedPw = config.savedPassword[config.serverAddr]; - if (savedPw?.shorten_password === config.password) { - cipherText = config.savedPassword[config.serverAddr].password; - aeskey = config.savedPassword[config.serverAddr].key; - config.aeskey = aeskey ?? ""; - Backend.setAESKey(aeskey); - if (Debugging) - console.log("use remembered password", config.password); - } else { - cipherText = Backend.pubEncrypt(jsonData, config.password); - config.aeskey = Backend.getAESKey(); - } + // const savedPw = config.savedPassword[config.serverAddr]; + // if (savedPw?.shorten_password === config.password) { + // cipherText = config.savedPassword[config.serverAddr].password; + // aeskey = config.savedPassword[config.serverAddr].key; + // config.aeskey = aeskey ?? ""; + // Backend.setAESKey(aeskey); + // if (Debugging) + // console.log("use remembered password", config.password); + // } else { + cipherText = Backend.pubEncrypt(jsonData, config.password); + config.aeskey = Backend.getAESKey(); + // } config.cipherText = cipherText; Backend.replyDelayTest(config.screenName, cipherText); } @@ -130,12 +133,12 @@ callbacks["EnterLobby"] = (jsonData) => { if (mainStack.depth === 1) { // we enter the lobby successfully, so save password now. config.lastLoginServer = config.serverAddr; - config.savedPassword[config.serverAddr] = { - username: config.screenName, - password: config.cipherText, - key: config.aeskey, - shorten_password: config.cipherText.slice(0, 8) - } + // config.savedPassword[config.serverAddr] = { + // username: config.screenName, + // password: config.cipherText, + // key: config.aeskey, + // shorten_password: config.cipherText.slice(0, 8) + // } mainStack.push(lobby); } else { mainStack.pop(); diff --git a/Fk/Pages/Init.qml b/Fk/Pages/Init.qml index 884c2edb..41e564d5 100644 --- a/Fk/Pages/Init.qml +++ b/Fk/Pages/Init.qml @@ -60,12 +60,16 @@ Item { text: qsTr("Console start") onClicked: { config.serverAddr = "127.0.0.1"; - const serverCfg = config.savedPassword["127.0.0.1"] ?? {}; - config.screenName = serverCfg.username ?? "player"; - config.password = serverCfg.shorten_password ?? "1234"; + config.serverPort = 9527; + // const serverCfg = config.savedPassword["127.0.0.1"] ?? {}; + const serverCfg = config.findFavorite("127.0.0.1", 9527); + config.screenName = serverCfg?.username ?? "player"; + config.password = serverCfg?.password ?? "1234"; mainWindow.busy = true; + config.addFavorite(config.serverAddr, config.serverPort, "", + config.screenName, config.password); Backend.startServer(9527); - Backend.joinServer("127.0.0.1"); + Backend.joinServer("127.0.0.1", 9527); } } diff --git a/Fk/Pages/JoinServer.qml b/Fk/Pages/JoinServer.qml index 4a716f2b..c2f65ace 100644 --- a/Fk/Pages/JoinServer.qml +++ b/Fk/Pages/JoinServer.qml @@ -3,10 +3,12 @@ import QtQuick import QtQuick.Layouts import QtQuick.Controls +import Fk Item { id: root anchors.fill: parent + property var selectedServer: serverModel.get(serverList.currentIndex) Timer { id: opTimer @@ -18,18 +20,24 @@ Item { Item { height: 64 - width: serverList.width - 48 - clip: true + width: serverList.width / 2 - 4 RowLayout { anchors.fill: parent spacing: 16 + Item {} + Image { - Layout.preferredHeight: 60 - Layout.preferredWidth: 60 + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + Layout.preferredHeight: 56 + Layout.preferredWidth: 56 fillMode: Image.PreserveAspectFit - source: favicon + source: { + if (!favicon) return SkinBank.MISC_DIR + "server_icon"; + if (favicon === "default") return AppPath + "/image/icon.png"; + return favicon; + } } ColumnLayout { @@ -37,22 +45,51 @@ Item { Text { Layout.fillWidth: true horizontalAlignment: Text.AlignLeft - text: serverIP + " " + misMatchMsg + text: { + if (name) return name; + let a = addr; + let p = port; + if (p === 9527) p = 0; + if (a.includes(":") && p) { // IPv6 + a = `[${a}]`; + } + if (p) { + p = `:${p}`; + } else { + p = ""; + } + return `${a}${p}`; + } font.bold: true + color: favicon ? "black" : "gray" } Text { Layout.fillWidth: true horizontalAlignment: Text.AlignLeft - text: description + text: delay + " ms " + misMatchMsg textFormat: TextEdit.RichText + color: { + if (delay < 0) { + return "gray"; + } else if (delay >= 0 && delay < 100) { + return "green"; + } else if (delay >= 100 && delay < 500) { + return "orange"; + } else { + return "red"; + } + } } } Text { - text: online + "/" + capacity - font.pixelSize: 30 + text: online + "/" + capacity + "" + font.pixelSize: 26 + color: favicon ? "black" : "gray" } + + Item {} } TapHandler { @@ -64,90 +101,51 @@ Item { } } } + + ColumnLayout { + x: 6 + height: parent.height + Item { Layout.fillHeight: true } + Image { + Layout.preferredWidth: 24; Layout.preferredHeight: 23 + source: SkinBank.MISC_DIR + "network_local" + visible: lan + } + Image { + Layout.preferredWidth: 24; Layout.preferredHeight: 23 + source: SkinBank.MISC_DIR + "favorite" + visible: favorite + } + } } } - ListView { - id: serverList - height: parent.height - controlPanel.height - 30 - width: parent.width - 80 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: 10 - contentHeight: serverDelegate.height * count - model: ListModel { - id: serverModel + RowLayout { + id: serverListBar + height: childrenRect.height + width: serverList.width + Text { + text: "已收藏服务器与公共服务器列表" + font.pixelSize: 18 + font.bold: true + x: 32; y: 8 } - delegate: serverDelegate - ScrollBar.vertical: ScrollBar {} - clip: true - highlight: Rectangle { - color: "#AA9ABFEF"; radius: 5 - // border.color: "black"; border.width: 2 - } - // highlightMoveDuration: 0 - currentIndex: -1 - } - - GridLayout { - id: controlPanel - anchors.top: serverList.bottom - anchors.topMargin: 10 - width: parent.width - 80 - anchors.horizontalCenter: parent.horizontalCenter - height: joinButton.height * 2 + 10 - columns: 3 - + Item { Layout.fillWidth: true } Button { - id: joinButton - Layout.fillWidth: true - enabled: serverList.currentIndex !== -1 - text: qsTr("Join Server") - onClicked: { - const item = serverModel.get(serverList.currentIndex); - const serverCfg = config.savedPassword[item.serverIP]; - config.serverAddr = item.serverIP; - config.screenName = serverCfg.username; - config.password = serverCfg.shorten_password ?? serverCfg.password; - mainWindow.busy = true; - Backend.joinServer(item.serverIP); - } - } - - Button { - Layout.fillWidth: true - text: qsTr("Add New Server") - onClicked: { - drawerLoader.sourceComponent = newServerComponent; - drawer.open(); - } - } - - Button { - Layout.fillWidth: true - enabled: serverList.currentIndex !== -1 - text: qsTr("Edit Server") - onClicked: { - drawerLoader.sourceComponent = editServerComponent; - drawer.open(); - } - } - - Button { - Layout.fillWidth: true text: qsTr("Refresh List") enabled: !opTimer.running onClicked: { opTimer.start(); for (let i = 0; i < serverModel.count; i++) { const item = serverModel.get(i); - Backend.getServerInfo(item.serverIP); + if (!item.favorite && !item.lan) break; + item.delayBegin = (new Date).getTime(); + Backend.getServerInfo(item.addr, item.port); } } } Button { - Layout.fillWidth: true text: qsTr("Detect LAN") enabled: !opTimer.running onClicked: { @@ -157,251 +155,234 @@ Item { } Button { - Layout.fillWidth: true text: qsTr("Go Back") onClicked: serverDialog.hide(); } } - Component { - id: newServerComponent - ColumnLayout { - signal finished(); - + ColumnLayout { + id: serverPanel + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 8 + height: parent.height - 16 + width: parent.width * 0.3 + TextField { + id: addressEdit + maximumLength: 64 + Layout.fillWidth: true + placeholderText: "服务器地址" + text: selectedServer?.addr ?? "" + } + TextField { + id: portEdit + maximumLength: 6 + Layout.fillWidth: true + placeholderText: "端口" + text: selectedServer?.port ?? "" + } + Flickable { + Layout.fillHeight: true + Layout.fillWidth: true + contentHeight: descText.height + clip: true Text { - text: qsTr("@NewServer") - font.pixelSize: 24 - font.bold: true - Layout.fillWidth: true - wrapMode: Text.WordWrap + id: descText + width: parent.width + text: selectedServer?.description ?? "" + wrapMode: Text.WrapAnywhere + font.pixelSize: 18 } - - Text { - text: qsTr("@NewServerHint") - font.pixelSize: 16 - Layout.fillWidth: true - wrapMode: Text.WordWrap - } - + } + RowLayout { + Layout.fillWidth: true TextField { - id: serverAddrEdit - Layout.fillWidth: true - placeholderText: qsTr("Server Addr") - text: "" - } - - TextField { - id: screenNameEdit + id: usernameEdit maximumLength: 32 Layout.fillWidth: true - placeholderText: qsTr("Username") - text: "" + placeholderText: "用户名" + text: selectedServer?.username ?? "" } - TextField { id: passwordEdit - maximumLength: 64 + maximumLength: 32 Layout.fillWidth: true - placeholderText: qsTr("Password") - text: "" - echoMode: showPasswordCheck.checked ? TextInput.Normal - : TextInput.Password + placeholderText: "密码" passwordCharacter: "*" + echoMode: TextInput.Password + text: selectedServer?.password ?? "" } - - CheckBox { - id: showPasswordCheck - text: qsTr("Show Password") - } - - Button { - Layout.fillWidth: true - enabled: serverAddrEdit.text !== "" && screenNameEdit.text !== "" - && passwordEdit.text !== "" - text: "OK" - onClicked: { - root.addNewServer(serverAddrEdit.text, screenNameEdit.text, - passwordEdit.text); - finished(); + } + Button { + text: "登录(首次登录自动注册)" + Layout.fillWidth: true + enabled: !!(addressEdit.text && portEdit.text && + usernameEdit.text && passwordEdit.text) + onClicked: { + const _addr = addressEdit.text; + const _port = parseInt(portEdit.text); + const _username = usernameEdit.text; + const _password = passwordEdit.text; + config.screenName = _username; + config.password = _password; + mainWindow.busy = true; + config.serverAddr = _addr; + config.serverPort = _port; + let name = selectedServer?.name; + if (_addr !== selectedServer?.addr || _port !== selectedServer?.port) { + name = ""; } + addFavorite(config.serverAddr, config.serverPort, name, + config.screenName, config.password); + Backend.joinServer(_addr, _port); + } + } + Button { + text: "从收藏夹删除" + Layout.fillWidth: true + visible: !!(selectedServer?.favorite) + onClicked: { + removeFavorite(selectedServer.addr, selectedServer.port); } } } - Component { - id: editServerComponent - ColumnLayout { - signal finished(); - - Text { - text: qsTr("@EditServer") - font.pixelSize: 24 - font.bold: true - Layout.fillWidth: true - wrapMode: Text.WordWrap - } - - Text { - text: qsTr("@EditServerHint") - font.pixelSize: 16 - Layout.fillWidth: true - wrapMode: Text.WordWrap - } - - TextField { - id: screenNameEdit - maximumLength: 32 - Layout.fillWidth: true - placeholderText: qsTr("Username") - text: "" - } - - TextField { - id: passwordEdit - maximumLength: 64 - Layout.fillWidth: true - placeholderText: qsTr("Password") - text: "" - echoMode: showPasswordCheck.checked ? TextInput.Normal - : TextInput.Password - passwordCharacter: "*" - } - - CheckBox { - id: showPasswordCheck - text: qsTr("Show Password") - } - - Button { - Layout.fillWidth: true - enabled: screenNameEdit.text !== "" && passwordEdit.text !== "" - text: "OK" - onClicked: { - root.editCurrentServer(screenNameEdit.text, passwordEdit.text); - finished(); - } - } - - Button { - Layout.fillWidth: true - text: qsTr("Delete Server") - onClicked: { - root.deleteCurrentServer(); - finished(); - } - } - } - } - - Drawer { - id: drawer - width: parent.width * 0.3 / mainWindow.scale - height: parent.height / mainWindow.scale - dim: false + GridView { + id: serverList + height: parent.height - 16 - serverListBar.height + width: parent.width - 24 - serverPanel.width + anchors.top: serverListBar.bottom + anchors.left: parent.left + anchors.margins: 8 + model: ListModel { id: serverModel } + delegate: serverDelegate + cellHeight: 64 + 8 + cellWidth: serverList.width / 2 clip: true - dragMargin: 0 - scale: mainWindow.scale - transformOrigin: Item.TopLeft - - Loader { - id: drawerLoader - anchors.fill: parent - anchors.margins: 16 - onSourceChanged: { - if (item === null) - return; - item.finished.connect(() => { - sourceComponent = undefined; - drawer.close(); - }); - } - onSourceComponentChanged: sourceChanged(); + highlight: Rectangle { + color: "#AA9ABFEF"; radius: 5 + // border.color: "black"; border.width: 2 } + currentIndex: -1 } - function addNewServer(addr, name, password) { - if (config.savedPassword[addr]) { - return; + function addFavorite(addr, port, name, username, password) { + const newItem = config.addFavorite(addr, port, name, username, password); + if (!newItem) { + for (let i = 0; i < serverModel.count; i++) { + const s = serverModel.get(i); + if (s.addr === addr && s.port === port && s.favorite) { + s.name = name; + s.username = username; + s.password = password; + return; + } + } } - - config.savedPassword[addr] = { - username: name, - password: password, - }; - config.saveConf(); - - serverModel.append({ - serverIP: addr, + serverModel.insert(0, { + addr, port, name, username, password, misMatchMsg: "", description: qsTr("Server not up"), - online: "-", - capacity: "-", - favicon: "https://img1.imgtp.com/2023/07/01/DGUdj8eu.png", + online: "?", + capacity: "??", + favicon: "", + delayBegin: (new Date).getTime(), + delay: -1, + favorite: true, + lan: false, }); - Backend.getServerInfo(addr); + Backend.getServerInfo(addr, port); } - function editCurrentServer(name, password) { - const addr = serverModel.get(serverList.currentIndex).serverIP; - if (!config.savedPassword[addr]) { - return; + function removeFavorite(addr, port) { + config.removeFavorite(addr, port); + for (let i = 0; i < serverModel.count; i++) { + const s = serverModel.get(i); + if (s.addr === addr && s.port === port && s.favorite) { + serverModel.remove(i); + serverList.currentIndex = -1; + return; + } } - - config.savedPassword[addr] = { - username: name, - password: password, - shorten_password: undefined, - key: undefined, - }; - config.saveConf(); } - function deleteCurrentServer() { - const addr = serverModel.get(serverList.currentIndex).serverIP; - if (!config.savedPassword[addr]) { - return; + function addLANServer(addr) { + const port = 9527; + if (config.findFavorite(addr, port)) return; + for (let i = 0; i < serverModel.count; i++) { + const s = serverModel.get(i); + if (s.addr === addr && s.port === port && s.lan) { + s.delayBegin = (new Date).getTime(); + Backend.getServerInfo(addr, port); + return; + } + if (!s.lan && !s.favorite) break; } - - config.savedPassword[addr] = undefined; - config.saveConf(); - - serverModel.remove(serverList.currentIndex, 1); - serverList.currentIndex = -1; + serverModel.insert(0, { + addr, port, + name: "", + username: "", + password: "", + misMatchMsg: "", + description: qsTr("Server not up"), + online: "?", + capacity: "??", + favicon: "", + delayBegin: (new Date).getTime(), + delay: -1, + favorite: false, + lan: true, + }); + Backend.getServerInfo(addr, port); } - function updateServerDetail(addr, data) { + function updateServerDetail(addr, port, data) { const [ver, icon, desc, capacity, count] = data; for (let i = 0; i < serverModel.count; i++) { const item = serverModel.get(i); - const ip = item.serverIP; - if (addr.endsWith(ip)) { // endsWith是为了应付IPv6格式的ip + const ip = item.addr; + const itemPort = item.port; + if (addr === ip && port == itemPort) { + const ms = (new Date).getTime(); item.misMatchMsg = ""; if (FkVersion !== ver) { item.misMatchMsg = qsTr("@VersionMismatch").arg(ver); } + item.delay = ms - item.delayBegin; item.description = desc; item.favicon = icon; item.online = count.toString(); item.capacity = capacity.toString(); + return; } } } function loadConfig() { - if (serverModel.count > 0) { - return; - } - for (let key in config.savedPassword) { + if (serverModel.count > 0) { return; } + const serverList = JSON.parse(Backend.getPublicServerList()); + serverList.unshift(...config.favoriteServers); + for (const server of serverList) { + let { addr, port, name, username, password } = server; + name = name ?? ""; + username = username ?? ""; + password = password ?? ""; + if (port === -1) break; + if (!password && config.findFavorite(addr, port)) continue; serverModel.append({ - serverIP: key, + addr, port, name, username, password, misMatchMsg: "", description: qsTr("Server not up"), - online: "-", - capacity: "-", + online: "?", + capacity: "??", favicon: "", + delayBegin: (new Date).getTime(), + delay: -1, + favorite: !!password, + lan: false, }); - Backend.getServerInfo(key); + Backend.getServerInfo(addr, port); } } } diff --git a/Fk/skin-bank.js b/Fk/skin-bank.js index ca305c01..f5c43364 100644 --- a/Fk/skin-bank.js +++ b/Fk/skin-bank.js @@ -18,6 +18,7 @@ var EQUIP_ICON_DIR = AppPath + "/image/card/equipIcon/"; var PIXANIM_DIR = AppPath + "/image/anim/" var TILE_ICON_DIR = AppPath + "/image/button/tileicon/" var LOBBY_IMG_DIR = AppPath + "/image/lobby/"; +var MISC_DIR = AppPath + "/image/misc/"; const searchPkgResource = function(path, name, suffix) { let ret; diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index de717dd4..18108dbf 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -3,8 +3,8 @@ + android:versionCode="419" + android:versionName="0.4.19"> diff --git a/freekill.server.config.json.example b/freekill.server.config.json.example index cc807afb..fdebb1b4 100644 --- a/freekill.server.config.json.example +++ b/freekill.server.config.json.example @@ -1,7 +1,7 @@ { "banwords": [], "description": "FreeKill Server", - "iconUrl": "https://img1.imgtp.com/2023/07/01/DGUdj8eu.png", + "iconUrl": "default", "capacity": 100, "tempBanTime": 20, "motd": "Welcome!", diff --git a/image/misc/favorite.png b/image/misc/favorite.png new file mode 100644 index 0000000000000000000000000000000000000000..d20f24cb6e07325b5c18d1b92df305834081c13f GIT binary patch literal 4345 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 QqyPW_07*qoM6N<$f>-hc+5i9m literal 0 HcmV?d00001 diff --git a/image/misc/server_icon.png b/image/misc/server_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..63bbda92ccb7b5e05570733de3f1d44b06429ec0 GIT binary patch literal 3791 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 FV1l3K5^Dee literal 0 HcmV?d00001 diff --git a/lang/en_US.ts b/lang/en_US.ts index 600bacda..dc62d504 100644 --- a/lang/en_US.ts +++ b/lang/en_US.ts @@ -21,7 +21,7 @@ @VersionMismatch - <font color="red" size="4"><b>Mismatch version: server is at v%1</b></font> + <font color="red" size="4"><b>!! v%1</b></font> diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts index bf2ecc4b..d5336259 100644 --- a/lang/zh_CN.ts +++ b/lang/zh_CN.ts @@ -242,7 +242,7 @@ @VersionMismatch - <font color="red" size="4"><b>版本不同:服务器为v%1</b></font> + <font color="red" size="4"><b>!! v%1</b></font> Server not up diff --git a/src/server/server.cpp b/src/server/server.cpp index fbda6f88..43f1fe16 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -386,7 +386,7 @@ void Server::readConfig() { // defaults SET_DEFAULT_CONFIG("description", "FreeKill Server"); - SET_DEFAULT_CONFIG("iconUrl", "https://img1.imgtp.com/2023/07/01/DGUdj8eu.png"); + SET_DEFAULT_CONFIG("iconUrl", "default"); SET_DEFAULT_CONFIG("capacity", 100); SET_DEFAULT_CONFIG("tempBanTime", 20); SET_DEFAULT_CONFIG("motd", "Welcome!"); diff --git a/src/ui/qmlbackend.cpp b/src/ui/qmlbackend.cpp index 5bb6a5a7..419dea73 100644 --- a/src/ui/qmlbackend.cpp +++ b/src/ui/qmlbackend.cpp @@ -210,7 +210,7 @@ void QmlBackend::startServer(ushort port) { } } -void QmlBackend::joinServer(QString address) { +void QmlBackend::joinServer(QString address, ushort port) { if (ClientInstance != nullptr) return; Client *client = new Client(this); @@ -222,6 +222,7 @@ void QmlBackend::joinServer(QString address) { emit notifyUI("ErrorMsg", msg); emit notifyUI("BackToStart", "[]"); }); + /* QString addr = "127.0.0.1"; ushort port = 9527u; @@ -232,7 +233,7 @@ void QmlBackend::joinServer(QString address) { } else { addr = address; // SRV解析查询 - QDnsLookup* dns = new QDnsLookup(QDnsLookup::SRV, "_freekill._tcp." + addr); + QDnsLookup *dns = new QDnsLookup(QDnsLookup::SRV, "_freekill._tcp." + addr); QEventLoop eventLoop; // 阻塞的SRV解析查询回调 connect(dns, &QDnsLookup::finished,[&eventLoop](void){ @@ -250,8 +251,9 @@ void QmlBackend::joinServer(QString address) { } } } + */ - client->connectToHost(addr, port); + client->connectToHost(address, port); } void QmlBackend::quitLobby(bool close) { @@ -327,6 +329,22 @@ QVariant QmlBackend::evalLuaExp(const QString &lua) { return result; } +QString QmlBackend::getPublicServerList() { + QFile conf("server-list.json"); + // TODO: Download new JSON via http + if (!conf.exists()) { + conf.open(QIODevice::WriteOnly); + static const char *init_conf = "{}"; + conf.write(init_conf); + conf.close(); + return init_conf; + } + conf.open(QIODevice::ReadOnly); + auto ret = conf.readAll(); + conf.close(); + return ret; +} + QString QmlBackend::pubEncrypt(const QString &key, const QString &data) { // 在用公钥加密口令时,也随机生成AES密钥/IV,并随着口令一起加密 // AES密钥和IV都是固定16字节的,所以可以放在开头 @@ -473,21 +491,14 @@ void QmlBackend::detectServer() { 9527); } -void QmlBackend::getServerInfo(const QString &address) { - QString addr = "127.0.0.1"; - ushort port = 9527u; +void QmlBackend::getServerInfo(const QString &address, ushort port) { + QString addr = address; + // ushort port = 9527u; static const char *ask_str = "fkGetDetail,"; - if (address.contains(QChar(':'))) { - QStringList texts = address.split(QChar(':')); - addr = texts.value(0); - port = texts.value(1).toUShort(); - } else { - addr = address; - } - QByteArray ask(ask_str); ask.append(address.toLatin1()); + ask.append(QString(",%1").arg(port).toUtf8()); if (QHostAddress(addr).isNull()) { // 不是ip?考虑解析域名 QHostInfo::lookupHost(addr, this, [=](const QHostInfo &host) { diff --git a/src/ui/qmlbackend.h b/src/ui/qmlbackend.h index 8aaba5bd..2f3e949c 100644 --- a/src/ui/qmlbackend.h +++ b/src/ui/qmlbackend.h @@ -33,7 +33,7 @@ public: void setEngine(QQmlApplicationEngine *engine); Q_INVOKABLE void startServer(ushort port); - Q_INVOKABLE void joinServer(QString address); + Q_INVOKABLE void joinServer(QString address, ushort port = 9527); // Lobby Q_INVOKABLE void quitLobby(bool close = true); @@ -44,6 +44,7 @@ public: QVariantList params); Q_INVOKABLE QVariant evalLuaExp(const QString &lua); + Q_INVOKABLE QString getPublicServerList(); Q_INVOKABLE QString pubEncrypt(const QString &key, const QString &data); Q_INVOKABLE QString loadConf(); Q_INVOKABLE QString loadTips(); @@ -62,7 +63,7 @@ public: Q_INVOKABLE void createModBackend(); Q_INVOKABLE void detectServer(); - Q_INVOKABLE void getServerInfo(const QString &addr); + Q_INVOKABLE void getServerInfo(const QString &addr, ushort port = 9527u); Q_INVOKABLE void showDialog(const QString &type, const QString &text, const QString &orig = QString());