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 00000000..d20f24cb
Binary files /dev/null and b/image/misc/favorite.png differ
diff --git a/image/misc/network_local.png b/image/misc/network_local.png
new file mode 100644
index 00000000..bc8b63d7
Binary files /dev/null and b/image/misc/network_local.png differ
diff --git a/image/misc/server_icon.png b/image/misc/server_icon.png
new file mode 100644
index 00000000..63bbda92
Binary files /dev/null and b/image/misc/server_icon.png differ
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 @@
- <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 @@
- <font color="red" size="4"><b>版本不同:服务器为v%1</b></font>
+ <font color="red" size="4"><b>!! v%1</b></font>
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());