mirror of
https://github.com/Qsgs-Fans/FreeKill.git
synced 2024-11-15 19:22:25 +08:00
Serverlist (#360)
## 服务器列表 - 重制了之前的加入服务器与保存密码的页面,以及功能 - 密码在本地以明文保存 - 根据游戏目录中的server-list.json读取公共服务器列表,还没做自动更新 - 可能有不少bug
This commit is contained in:
parent
79ede70b6b
commit
0325c73443
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -31,6 +31,7 @@ freekill-wrap.cxx
|
|||
/freekill.server.error.log
|
||||
/freekill.server.info.log
|
||||
/flist.txt
|
||||
/server-list.json
|
||||
|
||||
# windeployqt
|
||||
/bearer/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
39
Fk/Logic.js
39
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 {
|
||||
// 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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 + "/<font size='1'>" + capacity + "</font>"
|
||||
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();
|
||||
|
||||
Text {
|
||||
text: qsTr("@NewServer")
|
||||
font.pixelSize: 24
|
||||
font.bold: true
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("@NewServerHint")
|
||||
font.pixelSize: 16
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
id: serverPanel
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 8
|
||||
height: parent.height - 16
|
||||
width: parent.width * 0.3
|
||||
TextField {
|
||||
id: serverAddrEdit
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Server Addr")
|
||||
text: ""
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: screenNameEdit
|
||||
maximumLength: 32
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Username")
|
||||
text: ""
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: passwordEdit
|
||||
id: addressEdit
|
||||
maximumLength: 64
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Password")
|
||||
text: ""
|
||||
echoMode: showPasswordCheck.checked ? TextInput.Normal
|
||||
: TextInput.Password
|
||||
passwordCharacter: "*"
|
||||
placeholderText: "服务器地址"
|
||||
text: selectedServer?.addr ?? ""
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
id: portEdit
|
||||
maximumLength: 6
|
||||
Layout.fillWidth: true
|
||||
placeholderText: qsTr("Username")
|
||||
text: ""
|
||||
placeholderText: "端口"
|
||||
text: selectedServer?.port ?? ""
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: passwordEdit
|
||||
maximumLength: 64
|
||||
Flickable {
|
||||
Layout.fillHeight: true
|
||||
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
|
||||
contentHeight: descText.height
|
||||
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();
|
||||
});
|
||||
Text {
|
||||
id: descText
|
||||
width: parent.width
|
||||
text: selectedServer?.description ?? ""
|
||||
wrapMode: Text.WrapAnywhere
|
||||
font.pixelSize: 18
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
TextField {
|
||||
id: usernameEdit
|
||||
maximumLength: 32
|
||||
Layout.fillWidth: true
|
||||
placeholderText: "用户名"
|
||||
text: selectedServer?.username ?? ""
|
||||
}
|
||||
TextField {
|
||||
id: passwordEdit
|
||||
maximumLength: 32
|
||||
Layout.fillWidth: true
|
||||
placeholderText: "密码"
|
||||
passwordCharacter: "*"
|
||||
echoMode: TextInput.Password
|
||||
text: selectedServer?.password ?? ""
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
onSourceComponentChanged: sourceChanged();
|
||||
}
|
||||
}
|
||||
|
||||
function addNewServer(addr, name, password) {
|
||||
if (config.savedPassword[addr]) {
|
||||
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
|
||||
highlight: Rectangle {
|
||||
color: "#AA9ABFEF"; radius: 5
|
||||
// border.color: "black"; border.width: 2
|
||||
}
|
||||
currentIndex: -1
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
config.savedPassword[addr] = undefined;
|
||||
config.saveConf();
|
||||
|
||||
serverModel.remove(serverList.currentIndex, 1);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateServerDetail(addr, data) {
|
||||
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;
|
||||
}
|
||||
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, 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.notify.FreeKill"
|
||||
android:installLocation="preferExternal"
|
||||
android:versionCode="418"
|
||||
android:versionName="0.4.18">
|
||||
android:versionCode="419"
|
||||
android:versionName="0.4.19">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
|
|
@ -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!",
|
||||
|
|
BIN
image/misc/favorite.png
Normal file
BIN
image/misc/favorite.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
BIN
image/misc/network_local.png
Normal file
BIN
image/misc/network_local.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
image/misc/server_icon.png
Normal file
BIN
image/misc/server_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
|
@ -21,7 +21,7 @@
|
|||
|
||||
<message>
|
||||
<source>@VersionMismatch</source>
|
||||
<translation><font color="red" size="4"><b>Mismatch version: server is at v%1</b></font></translation>
|
||||
<translation><font color="red" size="4"><b>!! v%1</b></font></translation>
|
||||
</message>
|
||||
|
||||
<message>
|
||||
|
|
|
@ -242,7 +242,7 @@
|
|||
|
||||
<message>
|
||||
<source>@VersionMismatch</source>
|
||||
<translation><font color="red" size="4"><b>版本不同:服务器为v%1</b></font></translation>
|
||||
<translation><font color="red" size="4"><b>!! v%1</b></font></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Server not up</source>
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue
Block a user