Observer chat (#125)
新增旁观者聊天栏兼公告栏 增加服务端广播消息功能 修复单机启动失败时被心跳包卡死机的情况 修复发配音时undefined 聊天信息服务端回显
This commit is contained in:
parent
ba8aae852d
commit
0e51614588
|
@ -121,7 +121,7 @@ callbacks["UpdatePlayerNum"] = (j) => {
|
||||||
|
|
||||||
callbacks["Chat"] = function(jsonData) {
|
callbacks["Chat"] = function(jsonData) {
|
||||||
// jsonData: { string userName, string general, string time, string msg }
|
// jsonData: { string userName, string general, string time, string msg }
|
||||||
let current = mainStack.currentItem; // lobby(TODO) or room
|
let current = mainStack.currentItem; // lobby or room
|
||||||
let data = JSON.parse(jsonData);
|
let data = JSON.parse(jsonData);
|
||||||
let pid = data.sender;
|
let pid = data.sender;
|
||||||
let userName = data.userName;
|
let userName = data.userName;
|
||||||
|
@ -134,3 +134,8 @@ callbacks["Chat"] = function(jsonData) {
|
||||||
else
|
else
|
||||||
current.addToChat(pid, data, `[${time}] ${userName}(${general}): ${msg}`);
|
current.addToChat(pid, data, `[${time}] ${userName}(${general}): ${msg}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callbacks["ServerMessage"] = function(jsonData) {
|
||||||
|
let current = mainStack.currentItem; // lobby or room
|
||||||
|
current.sendDanmaku('<font color="gold"><b>[Server] </b></font>' + jsonData);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
width: 900
|
||||||
|
height: 20
|
||||||
|
visible: false
|
||||||
|
property bool newTxtAvailable: true
|
||||||
|
property var stashedTxt: []
|
||||||
|
property int currentRunning: 0
|
||||||
|
|
||||||
|
onNewTxtAvailableChanged: {
|
||||||
|
if (!newTxtAvailable || stashedTxt.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let t = stashedTxt.splice(0, 1)[0];
|
||||||
|
let obj = txtComponent.createObject(root, { text: t });
|
||||||
|
obj.finished.connect(() => obj.destroy());
|
||||||
|
obj.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentRunningChanged: {
|
||||||
|
visible = !!currentRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "black"
|
||||||
|
opacity: 0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: txtComponent
|
||||||
|
Text {
|
||||||
|
id: txt
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 18
|
||||||
|
font.family: fontLibian.name
|
||||||
|
textFormat: TextEdit.RichText
|
||||||
|
y: -1
|
||||||
|
property bool changedAvail: false
|
||||||
|
signal finished()
|
||||||
|
|
||||||
|
onXChanged: {
|
||||||
|
if (root.width - x - 40 > width && !changedAvail) {
|
||||||
|
root.newTxtAvailable = true;
|
||||||
|
changedAvail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyAnimation on x {
|
||||||
|
id: txtAnim
|
||||||
|
running: false
|
||||||
|
from: root.width
|
||||||
|
to: -txt.width
|
||||||
|
duration: (root.width + txt.width) * 5
|
||||||
|
|
||||||
|
onFinished: {
|
||||||
|
root.currentRunning--;
|
||||||
|
txt.finished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
root.newTxtAvailable = false;
|
||||||
|
root.currentRunning++;
|
||||||
|
txtAnim.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendLog(txt) {
|
||||||
|
root.stashedTxt.push(txt);
|
||||||
|
if (root.newTxtAvailable) {
|
||||||
|
root.newTxtAvailable = false;
|
||||||
|
root.newTxtAvailable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -234,10 +234,19 @@ Item {
|
||||||
radius: 4
|
radius: 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Danmaku {
|
||||||
|
id: danmaku
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
function addToChat(pid, raw, msg) {
|
function addToChat(pid, raw, msg) {
|
||||||
if (raw.type !== 1) return;
|
if (raw.type !== 1) return;
|
||||||
lobbyChat.append(msg);
|
lobbyChat.append(msg);
|
||||||
toast.show("<b>" + raw.userName + "</b>: " + raw.msg);
|
danmaku.sendLog("<b>" + raw.userName + "</b>: " + raw.msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendDanmaku(msg) {
|
||||||
|
danmaku.sendLog(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|
|
@ -625,6 +625,11 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Danmaku {
|
||||||
|
id: danmaku
|
||||||
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
Shortcut {
|
Shortcut {
|
||||||
sequence: "T"
|
sequence: "T"
|
||||||
onActivated: {
|
onActivated: {
|
||||||
|
@ -677,12 +682,16 @@ Item {
|
||||||
if (raw.type === 1) return;
|
if (raw.type === 1) return;
|
||||||
|
|
||||||
if (raw.msg.startsWith("$")) {
|
if (raw.msg.startsWith("$")) {
|
||||||
if (specialChat(pid, data, raw.msg.slice(1))) return;
|
if (specialChat(pid, raw, raw.msg.slice(1))) return;
|
||||||
}
|
}
|
||||||
chat.append(msg);
|
chat.append(msg);
|
||||||
let photo = Logic.getPhotoOrSelf(pid);
|
let photo = Logic.getPhotoOrSelf(pid);
|
||||||
if (photo === undefined)
|
if (photo === undefined) {
|
||||||
|
let user = raw.userName;
|
||||||
|
let m = raw.msg;
|
||||||
|
danmaku.sendLog(`${user}: ${m}`);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
photo.chat(raw.msg);
|
photo.chat(raw.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,8 +729,10 @@ Item {
|
||||||
chat.append(`[${time}] ${userName}(${general}): ${m}`);
|
chat.append(`[${time}] ${userName}(${general}): ${m}`);
|
||||||
|
|
||||||
let photo = Logic.getPhotoOrSelf(pid);
|
let photo = Logic.getPhotoOrSelf(pid);
|
||||||
if (photo === undefined)
|
if (photo === undefined) {
|
||||||
|
danmaku.sendLog(`${userName}: ${m}`);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
photo.chat(m);
|
photo.chat(m);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -743,8 +754,10 @@ Item {
|
||||||
chat.append(`[${time}] ${userName}(${general}): ${m}`);
|
chat.append(`[${time}] ${userName}(${general}): ${m}`);
|
||||||
|
|
||||||
let photo = Logic.getPhotoOrSelf(pid);
|
let photo = Logic.getPhotoOrSelf(pid);
|
||||||
if (photo === undefined)
|
if (photo === undefined) {
|
||||||
|
danmaku.sendLog(`${userName}: ${m}`);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
photo.chat(m);
|
photo.chat(m);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -757,6 +770,10 @@ Item {
|
||||||
log.append(msg);
|
log.append(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendDanmaku(msg) {
|
||||||
|
danmaku.sendLog(msg);
|
||||||
|
}
|
||||||
|
|
||||||
function showDistance(show) {
|
function showDistance(show) {
|
||||||
for (let i = 0; i < photoModel.count; i++) {
|
for (let i = 0; i < photoModel.count; i++) {
|
||||||
let item = photos.itemAt(i);
|
let item = photos.itemAt(i);
|
||||||
|
|
|
@ -295,6 +295,9 @@ void Room::chat(ServerPlayer *sender, const QString &jsonData) {
|
||||||
doBroadcastNotify(players, "Chat", json);
|
doBroadcastNotify(players, "Chat", json);
|
||||||
doBroadcastNotify(observers, "Chat", json);
|
doBroadcastNotify(observers, "Chat", json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qInfo("[Chat] %s: %s", sender->getScreenName().toUtf8().constData(),
|
||||||
|
doc["msg"].toString().toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Room::gameOver() {
|
void Room::gameOver() {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
#include <qjsonarray.h>
|
#include <qjsonarray.h>
|
||||||
|
#include <qobject.h>
|
||||||
|
|
||||||
#include "client_socket.h"
|
#include "client_socket.h"
|
||||||
#include "packman.h"
|
#include "packman.h"
|
||||||
|
@ -49,7 +50,12 @@ Server::Server(QObject *parent) : QObject(parent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QThread::sleep(20);
|
for (int i = 0; i < 10; i++) {
|
||||||
|
if (!this->isListening) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QThread::sleep(2);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (auto p, this->players.values()) {
|
foreach (auto p, this->players.values()) {
|
||||||
if (p->getState() == Player::Online && !p->alive) {
|
if (p->getState() == Player::Online && !p->alive) {
|
||||||
|
@ -58,6 +64,7 @@ Server::Server(QObject *parent) : QObject(parent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
heartbeatThread->setParent(this);
|
||||||
heartbeatThread->setObjectName("Heartbeat");
|
heartbeatThread->setObjectName("Heartbeat");
|
||||||
heartbeatThread->start();
|
heartbeatThread->start();
|
||||||
}
|
}
|
||||||
|
@ -70,7 +77,9 @@ Server::~Server() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::listen(const QHostAddress &address, ushort port) {
|
bool Server::listen(const QHostAddress &address, ushort port) {
|
||||||
return server->listen(address, port);
|
bool ret = server->listen(address, port);
|
||||||
|
isListening = ret;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::createRoom(ServerPlayer *owner, const QString &name, int capacity,
|
void Server::createRoom(ServerPlayer *owner, const QString &name, int capacity,
|
||||||
|
@ -139,6 +148,12 @@ void Server::updateRoomList() {
|
||||||
|
|
||||||
sqlite3 *Server::getDatabase() { return db; }
|
sqlite3 *Server::getDatabase() { return db; }
|
||||||
|
|
||||||
|
void Server::broadcast(const QString &command, const QString &jsonData) {
|
||||||
|
foreach (ServerPlayer *p, players.values()) {
|
||||||
|
p->doNotify(command, jsonData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Server::processNewConnection(ClientSocket *client) {
|
void Server::processNewConnection(ClientSocket *client) {
|
||||||
qInfo() << client->peerAddress() << "connected";
|
qInfo() << client->peerAddress() << "connected";
|
||||||
// version check, file check, ban IP, reconnect, etc
|
// version check, file check, ban IP, reconnect, etc
|
||||||
|
|
|
@ -33,6 +33,8 @@ public:
|
||||||
|
|
||||||
sqlite3 *getDatabase();
|
sqlite3 *getDatabase();
|
||||||
|
|
||||||
|
void broadcast(const QString &command, const QString &jsonData);
|
||||||
|
bool isListening;
|
||||||
signals:
|
signals:
|
||||||
void roomCreated(Room *room);
|
void roomCreated(Room *room);
|
||||||
void playerAdded(ServerPlayer *player);
|
void playerAdded(ServerPlayer *player);
|
||||||
|
|
|
@ -30,6 +30,7 @@ void Shell::helpCommand(QStringList &) {
|
||||||
qInfo("%s: Disable a package.", "disable");
|
qInfo("%s: Disable a package.", "disable");
|
||||||
qInfo("%s: Upgrade a package.", "upgrade");
|
qInfo("%s: Upgrade a package.", "upgrade");
|
||||||
qInfo("%s: Kick a player by his id.", "kick");
|
qInfo("%s: Kick a player by his id.", "kick");
|
||||||
|
qInfo("%s: Broadcast message.", "msg");
|
||||||
qInfo("For more commands, check the documentation.");
|
qInfo("For more commands, check the documentation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,10 +134,19 @@ void Shell::kickCommand(QStringList &list) {
|
||||||
auto p = ServerInstance->findPlayer(id);
|
auto p = ServerInstance->findPlayer(id);
|
||||||
if (p) {
|
if (p) {
|
||||||
p->kicked();
|
p->kicked();
|
||||||
qInfo("Success");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shell::msgCommand(QStringList &list) {
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
qWarning("The 'msg' command needs message body.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto msg = list.join(' ');
|
||||||
|
ServerInstance->broadcast("ServerMessage", msg);
|
||||||
|
}
|
||||||
|
|
||||||
Shell::Shell() {
|
Shell::Shell() {
|
||||||
setObjectName("Shell");
|
setObjectName("Shell");
|
||||||
signal(SIGINT, sigintHandler);
|
signal(SIGINT, sigintHandler);
|
||||||
|
@ -154,6 +164,7 @@ Shell::Shell() {
|
||||||
handlers["enable"] = &Shell::enableCommand;
|
handlers["enable"] = &Shell::enableCommand;
|
||||||
handlers["disable"] = &Shell::disableCommand;
|
handlers["disable"] = &Shell::disableCommand;
|
||||||
handlers["kick"] = &Shell::kickCommand;
|
handlers["kick"] = &Shell::kickCommand;
|
||||||
|
handlers["msg"] = &Shell::msgCommand;
|
||||||
}
|
}
|
||||||
handler_map = handlers;
|
handler_map = handlers;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ private:
|
||||||
void enableCommand(QStringList &);
|
void enableCommand(QStringList &);
|
||||||
void disableCommand(QStringList &);
|
void disableCommand(QStringList &);
|
||||||
void kickCommand(QStringList &);
|
void kickCommand(QStringList &);
|
||||||
|
void msgCommand(QStringList &);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue