Reconnect fix (#357)
Some checks failed
Check Whitespace and New Line / check (push) Has been cancelled
Deploy Sphinx documentation to Pages / pages (push) Has been cancelled

修复一系列炸服
修复大厅太辣眼睛的bug
This commit is contained in:
notify 2024-06-11 14:19:39 +08:00 committed by GitHub
parent d94b483f66
commit d11bf58cb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 137 additions and 81 deletions

View File

@ -1,9 +1,11 @@
# ChangeLog # ChangeLog
## v0.4.16 ## v0.4.16 & v0.4.17
在引入freekill-core之后的第一次版本更新甚至无法保证这次更新是否正常 在引入freekill-core之后的第一次版本更新甚至无法保证这次更新是否正常
UI是半成品0.4.17修复各种爆炸以及半成品UI稍微人性化一点
1. 改进processPrompt支持双将和暗将 1. 改进processPrompt支持双将和暗将
2. 副将长名旋转 2. 副将长名旋转
3. 国战体力上限优化,包括一览和选将框 3. 国战体力上限优化,包括一览和选将框

View File

@ -6,7 +6,7 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(FreeKill VERSION 0.4.16) project(FreeKill VERSION 0.4.17)
add_definitions(-DFK_VERSION=\"${CMAKE_PROJECT_VERSION}\") add_definitions(-DFK_VERSION=\"${CMAKE_PROJECT_VERSION}\")
find_package(Qt6 REQUIRED COMPONENTS find_package(Qt6 REQUIRED COMPONENTS

View File

@ -107,6 +107,7 @@ Item {
} }
Text { Text {
id: faqTxt
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.rightMargin: 8 anchors.rightMargin: 8
@ -123,6 +124,24 @@ Item {
} }
} }
} }
Text {
anchors.right: faqTxt.left
anchors.bottom: parent.bottom
anchors.rightMargin: 8
anchors.bottomMargin: 8
text: qsTr("ResFix")
color: "blue"
font.pixelSize: 24
font.underline: true
visible: OS === "Android"
TapHandler {
onTapped: {
Backend.askFixResource();
}
}
}
} }
} }

View File

@ -22,7 +22,7 @@ Item {
radius: 8 radius: 8
height: 124 - 8 height: 124 - 8
width: 124 - 8 width: 124 - 8
color: outdated ? "#E2E2E2" : "lightgreen" color: outdated ? "#E2E2E2" : "#DDDDDDDD"
Text { Text {
id: roomNameText id: roomNameText
@ -281,7 +281,7 @@ Item {
Rectangle { Rectangle {
Layout.fillHeight: true Layout.fillHeight: true
Layout.preferredWidth: childrenRect.width + 48 Layout.preferredWidth: childrenRect.width + 72
gradient: Gradient { gradient: Gradient {
orientation: Gradient.Horizontal orientation: Gradient.Horizontal

View File

@ -3,8 +3,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.notify.FreeKill" package="org.notify.FreeKill"
android:installLocation="preferExternal" android:installLocation="preferExternal"
android:versionCode="416" android:versionCode="417"
android:versionName="0.4.16"> android:versionName="0.4.17">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

View File

@ -109,7 +109,7 @@
</message> </message>
<message> <message>
<source>packages/%1: some error occured.</source> <source>packages/%1: some error occured.</source>
<translation> %1 </translation> <translation> %1 %1</translation>
</message> </message>
</context> </context>
@ -125,7 +125,7 @@
</message> </message>
<message> <message>
<source>help: unknown password error</source> <source>help: unknown password error</source>
<translation></translation> <translation>使127.0.0.1-></translation>
</message> </message>
<message> <message>
<source>help: you have been banned!</source> <source>help: you have been banned!</source>
@ -141,7 +141,19 @@
</message> </message>
<message> <message>
<source>help: username or password error</source> <source>help: username or password error</source>
<translation></translation> <translation>127.0.0.1-></translation>
</message>
<message>
<source>help: md5 fail</source>
<translation>MD5错误且未发生拓展包变动</translation>
</message>
<message>
<source>fix resource</source>
<translation></translation>
</message>
<message>
<source>help: fix resource</source>
<translation>MD5失败</translation>
</message> </message>
</context> </context>
@ -179,6 +191,10 @@
<source>FAQ</source> <source>FAQ</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>ResFix</source>
<translation></translation>
</message>
<message> <message>
<source>$LoginFAQ</source> <source>$LoginFAQ</source>
<translation> <translation>
@ -318,6 +334,10 @@
<source>MD5 check failed!</source> <source>MD5 check failed!</source>
<translation>MD5检测失败</translation> <translation>MD5检测失败</translation>
</message> </message>
<message>
<source>md5 fail</source>
<translation></translation>
</message>
<message> <message>
<source>others logged in with this name</source> <source>others logged in with this name</source>
<translation></translation> <translation></translation>

View File

@ -24,8 +24,9 @@ bool ServerSocket::listen(const QHostAddress &address, ushort port) {
void ServerSocket::processNewConnection() { void ServerSocket::processNewConnection() {
QTcpSocket *socket = server->nextPendingConnection(); QTcpSocket *socket = server->nextPendingConnection();
ClientSocket *connection = new ClientSocket(socket); ClientSocket *connection = new ClientSocket(socket);
connect(connection, &ClientSocket::disconnected, this, // 这里怎么能一断连就自己删呢,应该让上层的来
[connection]() { connection->deleteLater(); }); //connect(connection, &ClientSocket::disconnected, this,
// [connection]() { connection->deleteLater(); });
emit new_connection(connection); emit new_connection(connection);
} }

View File

@ -169,7 +169,7 @@ QJsonObject AuthManager::checkPassword(ClientSocket *client, const QString &name
if (players.value(id)) { if (players.value(id)) {
auto player = players.value(id); auto player = players.value(id);
// 顶号机制,如果在线的话就让他变成不在线 // 顶号机制,如果在线的话就让他变成不在线
if (player->getState() == Player::Online) { if (player->getState() == Player::Online || player->getState() == Player::Robot) {
player->doNotify("ErrorDlg", "others logged in again with this name"); player->doNotify("ErrorDlg", "others logged in again with this name");
emit player->kicked(); emit player->kicked();
} }

View File

@ -240,9 +240,6 @@ void Room::removePlayer(ServerPlayer *player) {
// 然后基于跑路玩家的socket创建一个新ServerPlayer对象用来通信 // 然后基于跑路玩家的socket创建一个新ServerPlayer对象用来通信
ServerPlayer *runner = new ServerPlayer(this); ServerPlayer *runner = new ServerPlayer(this);
runner->setSocket(socket); runner->setSocket(socket);
connect(runner, &ServerPlayer::disconnected, server,
&Server::onUserDisconnected);
connect(runner, &Player::stateChanged, server, &Server::onUserStateChanged);
runner->setScreenName(player->getScreenName()); runner->setScreenName(player->getScreenName());
runner->setAvatar(player->getAvatar()); runner->setAvatar(player->getAvatar());
runner->setId(player->getId()); runner->setId(player->getId());
@ -512,7 +509,7 @@ void Room::gameOver() {
} }
} }
server->endTransaction(); server->endTransaction();
insideGameOver = true; insideGameOver = false;
} }
void Room::manuallyStart() { void Room::manuallyStart() {

View File

@ -37,15 +37,16 @@ void RoomBase::chat(ServerPlayer *sender, const QString &jsonData) {
auto type = doc["type"].toInt(); auto type = doc["type"].toInt();
doc["sender"] = sender->getId(); doc["sender"] = sender->getId();
// 屏蔽.号防止有人在HTML文本发链接而正常发链接看不出来有啥改动
auto msg = doc["msg"].toString(); auto msg = doc["msg"].toString();
msg.replace(".", "");
// 300字限制与客户端相同
msg.erase(msg.begin() + 300, msg.end());
doc["msg"] = msg;
if (!server->checkBanWord(msg)) { if (!server->checkBanWord(msg)) {
return; return;
} }
// 屏蔽.号和百分号防止有人在HTML文本发链接而正常发链接看不出来有啥改动
msg.replace(".", "");
msg.replace("%", "");
// 300字限制与客户端相同
msg.erase(msg.begin() + 300, msg.end());
doc["msg"] = msg;
if (type == 1) { if (type == 1) {
doc["userName"] = sender->getScreenName(); doc["userName"] = sender->getScreenName();
@ -57,6 +58,9 @@ void RoomBase::chat(ServerPlayer *sender, const QString &jsonData) {
doBroadcastNotify(observers, "Chat", json); doBroadcastNotify(observers, "Chat", json);
} }
qInfo("[Chat] %s: %s", sender->getScreenName().toUtf8().constData(), qInfo("[Chat/%s] %s: %s",
isLobby() ? "Lobby" : QString("#%1").arg(qobject_cast<Room *>(this)
->getId()).toUtf8().constData(),
sender->getScreenName().toUtf8().constData(),
doc["msg"].toString().toUtf8().constData()); doc["msg"].toString().toUtf8().constData());
} }

View File

@ -261,7 +261,7 @@ void Server::processNewConnection(ClientSocket *client) {
void Server::processRequest(const QByteArray &msg) { void Server::processRequest(const QByteArray &msg) {
ClientSocket *client = qobject_cast<ClientSocket *>(sender()); ClientSocket *client = qobject_cast<ClientSocket *>(sender());
client->disconnect(this, SLOT(processRequest(const QByteArray &))); disconnect(client, &ClientSocket::message_got, this, &Server::processRequest);
client->timerSignup.stop(); client->timerSignup.stop();
bool valid = true; bool valid = true;
@ -339,9 +339,6 @@ void Server::processRequest(const QByteArray &msg) {
ServerPlayer *player = new ServerPlayer(lobby()); ServerPlayer *player = new ServerPlayer(lobby());
player->setSocket(client); player->setSocket(client);
client->disconnect(this); client->disconnect(this);
connect(player, &ServerPlayer::disconnected, this,
&Server::onUserDisconnected);
connect(player, &Player::stateChanged, this, &Server::onUserStateChanged);
player->setScreenName(name); player->setScreenName(name);
player->setAvatar(obj["avatar"].toString()); player->setAvatar(obj["avatar"].toString());
player->setId(id); player->setId(id);
@ -374,56 +371,6 @@ void Server::onRoomAbandoned() {
room->getThread()->removeRoom(room); room->getThread()->removeRoom(room);
} }
void Server::onUserDisconnected() {
auto player = qobject_cast<ServerPlayer *>(sender());
qInfo() << "Player" << player->getId() << "disconnected";
if (players.count() <= 10) {
broadcast("ServerMessage", tr("%1 logged out").arg(player->getScreenName()));
}
auto _room = player->getRoom();
if (_room->isLobby()) {
player->setState(Player::Robot); // 大厅然而又不能设Offline
player->deleteLater();
} else {
auto room = qobject_cast<Room *>(_room);
if (room->isStarted()) {
if (room->getObservers().contains(player)) {
room->removeObserver(player);
player->deleteLater();
return;
}
player->setState(Player::Offline);
player->setSocket(nullptr);
// TODO: add a robot
} else {
player->setState(Player::Robot); // 大厅然而又不能设Offline
// 这里有一个多线程问题可能与Room::gameOver同时deleteLater导致出事
// FIXME: 这种解法肯定不安全
if (!room->insideGameOver)
player->deleteLater();
}
}
}
void Server::onUserStateChanged() {
ServerPlayer *player = qobject_cast<ServerPlayer *>(sender());
auto _room = player->getRoom();
if (!_room || _room->isLobby()) return;
auto room = qobject_cast<Room *>(_room);
if (room->isAbandoned()) return;
auto state = player->getState();
room->doBroadcastNotify(room->getPlayers(), "NetStateChanged",
QString("[%1,\"%2\"]").arg(player->getId()).arg(player->getStateString()));
if (state == Player::Online) {
player->resumeGameTimer();
} else {
player->pauseGameTimer();
}
}
#define SET_DEFAULT_CONFIG(k, v) do {\ #define SET_DEFAULT_CONFIG(k, v) do {\
if (config.value(k).isUndefined()) { \ if (config.value(k).isUndefined()) { \
config[k] = (v); \ config[k] = (v); \

View File

@ -66,8 +66,6 @@ public slots:
void processRequest(const QByteArray &msg); void processRequest(const QByteArray &msg);
void onRoomAbandoned(); void onRoomAbandoned();
void onUserDisconnected();
void onUserStateChanged();
private: private:
friend class Shell; friend class Shell;

View File

@ -14,6 +14,7 @@ ServerPlayer::ServerPlayer(RoomBase *room) {
this->room = room; this->room = room;
server = room->getServer(); server = room->getServer();
connect(this, &ServerPlayer::kicked, this, &ServerPlayer::kick); connect(this, &ServerPlayer::kicked, this, &ServerPlayer::kick);
connect(this, &Player::stateChanged, this, &ServerPlayer::onStateChanged);
alive = true; alive = true;
m_busy = false; m_busy = false;
@ -42,7 +43,7 @@ void ServerPlayer::setSocket(ClientSocket *socket) {
this->socket = nullptr; this->socket = nullptr;
if (socket != nullptr) { if (socket != nullptr) {
connect(socket, &ClientSocket::disconnected, this, connect(socket, &ClientSocket::disconnected, this,
&ServerPlayer::disconnected); &ServerPlayer::onDisconnected);
this->socket = socket; this->socket = socket;
} }
@ -108,6 +109,9 @@ void ServerPlayer::kick() {
setState(Player::Offline); setState(Player::Offline);
if (socket != nullptr) { if (socket != nullptr) {
socket->disconnectFromHost(); socket->disconnectFromHost();
} else {
// 还是得走一遍这个流程才行
onDisconnected();
} }
setSocket(nullptr); setSocket(nullptr);
} }
@ -115,7 +119,7 @@ void ServerPlayer::kick() {
void ServerPlayer::reconnect(ClientSocket *client) { void ServerPlayer::reconnect(ClientSocket *client) {
setSocket(client); setSocket(client);
alive = true; alive = true;
client->disconnect(this); // client->disconnect(this);
if (server->getPlayers().count() <= 10) { if (server->getPlayers().count() <= 10) {
server->broadcast("ServerMessage", tr("%1 backed").arg(getScreenName())); server->broadcast("ServerMessage", tr("%1 backed").arg(getScreenName()));
} }
@ -159,3 +163,51 @@ void ServerPlayer::resumeGameTimer() {
int ServerPlayer::getGameTime() { int ServerPlayer::getGameTime() {
return gameTime + (getState() == Player::Online ? gameTimer.elapsed() / 1000 : 0); return gameTime + (getState() == Player::Online ? gameTimer.elapsed() / 1000 : 0);
} }
void ServerPlayer::onStateChanged() {
auto _room = getRoom();
if (!_room || _room->isLobby()) return;
auto room = qobject_cast<Room *>(_room);
if (room->isAbandoned()) return;
auto state = getState();
room->doBroadcastNotify(room->getPlayers(), "NetStateChanged",
QString("[%1,\"%2\"]").arg(getId()).arg(getStateString()));
if (state == Player::Online) {
resumeGameTimer();
} else {
pauseGameTimer();
}
}
void ServerPlayer::onDisconnected() {
qInfo() << "Player" << getId() << "disconnected";
if (server->getPlayers().count() <= 10) {
server->broadcast("ServerMessage", tr("%1 logged out").arg(getScreenName()));
}
auto _room = getRoom();
if (_room->isLobby()) {
setState(Player::Robot); // 大厅然而又不能设Offline
deleteLater();
} else {
auto room = qobject_cast<Room *>(_room);
if (room->isStarted()) {
if (room->getObservers().contains(this)) {
room->removeObserver(this);
deleteLater();
return;
}
setState(Player::Offline);
setSocket(nullptr);
// TODO: add a robot
} else {
setState(Player::Robot); // 大厅然而又不能设Offline
// 这里有一个多线程问题可能与Room::gameOver同时deleteLater导致出事
// FIXME: 这种解法肯定不安全
if (!room->insideGameOver)
deleteLater();
}
}
}

View File

@ -52,9 +52,12 @@ public:
int getGameTime(); int getGameTime();
signals: signals:
void disconnected();
void kicked(); void kicked();
public slots:
void onStateChanged();
void onDisconnected();
private: private:
ClientSocket *socket; // socket for communicating with client ClientSocket *socket; // socket for communicating with client
Router *router; Router *router;

View File

@ -570,6 +570,18 @@ void QmlBackend::showDialog(const QString &type, const QString &text, const QStr
} }
} }
void QmlBackend::askFixResource() {
#if defined(Q_OS_ANDROID) || defined(Q_OS_LINUX)
auto box = new QMessageBox(QMessageBox::Question, tr("fix resource"),
tr("help: fix resource"), QMessageBox::Ok | QMessageBox::Cancel);
connect(box, &QMessageBox::accepted, box, []() {
QFile::remove("fk_ver"); qApp->exit(); });
connect(box, &QMessageBox::finished, box, &QObject::deleteLater);
box->setWindowModality(Qt::NonModal);
box->show();
#endif
}
void QmlBackend::removeRecord(const QString &fname) { void QmlBackend::removeRecord(const QString &fname) {
QFile::remove("recording/" + fname); QFile::remove("recording/" + fname);
} }

View File

@ -66,6 +66,7 @@ public:
Q_INVOKABLE void showDialog(const QString &type, const QString &text, Q_INVOKABLE void showDialog(const QString &type, const QString &text,
const QString &orig = QString()); const QString &orig = QString());
Q_INVOKABLE void askFixResource();
qreal volume() const { return m_volume; } qreal volume() const { return m_volume; }
void setVolume(qreal v) { m_volume = v; } void setVolume(qreal v) { m_volume = v; }