From d3ee1cecc463a261dfca06f331e05e061ec9488c Mon Sep 17 00:00:00 2001 From: Evoleo Date: Wed, 4 Dec 2024 07:44:10 +0300 Subject: [PATCH] chat history fix --- Client/scripts/chatHandlers/chatHandlers.gml | 10 ++- TypescriptServer/src/cmd/handlers/chat.ts | 6 ++ TypescriptServer/src/cmd/handlers/custom.ts | 3 - TypescriptServer/src/cmd/sendStuff.ts | 3 + TypescriptServer/src/cmd/senders/chat.ts | 18 ++++- TypescriptServer/src/concepts/chat.ts | 68 +++++++++++-------- TypescriptServer/src/concepts/client.ts | 17 +++-- .../src/initializers/00_exit_handler.ts | 3 +- TypescriptServer/src/initializers/15_chats.ts | 10 +++ TypescriptServer/src/schemas/chat.ts | 18 +++++ TypescriptServer/src/util/names.ts | 2 + 11 files changed, 118 insertions(+), 40 deletions(-) create mode 100644 TypescriptServer/src/cmd/handlers/chat.ts diff --git a/Client/scripts/chatHandlers/chatHandlers.gml b/Client/scripts/chatHandlers/chatHandlers.gml index b909ce5..067bc7c 100644 --- a/Client/scripts/chatHandlers/chatHandlers.gml +++ b/Client/scripts/chatHandlers/chatHandlers.gml @@ -7,5 +7,13 @@ addHandler("chat msg", function(data) { }) addHandler("chat history", function(data) { - trace(data.messages) + trace(data.history) +}) + +addHandler("chats list", function(data) { + var ids = data.chats +}) + +addHandler("chat info", function(data) { + trace("chat info: %", data.chat) }) \ No newline at end of file diff --git a/TypescriptServer/src/cmd/handlers/chat.ts b/TypescriptServer/src/cmd/handlers/chat.ts new file mode 100644 index 0000000..eb9ae14 --- /dev/null +++ b/TypescriptServer/src/cmd/handlers/chat.ts @@ -0,0 +1,6 @@ +import addHandler from "#cmd/handlePacket"; + +// list of all the chats of this player +addHandler('chats list', (c, data) => { + c.sendChatsList(); +}); \ No newline at end of file diff --git a/TypescriptServer/src/cmd/handlers/custom.ts b/TypescriptServer/src/cmd/handlers/custom.ts index a01fa3b..4f56847 100644 --- a/TypescriptServer/src/cmd/handlers/custom.ts +++ b/TypescriptServer/src/cmd/handlers/custom.ts @@ -1,7 +1,4 @@ import { addHandler } from "#cmd/handlePacket"; -import { PlayerInputs } from "#entities/player"; -import Point from "#types/point"; -import { clamp } from "#util/maths"; addHandler('player controls', (c, data) => { if (!c.entity) return; diff --git a/TypescriptServer/src/cmd/sendStuff.ts b/TypescriptServer/src/cmd/sendStuff.ts index da0d032..07bb60c 100644 --- a/TypescriptServer/src/cmd/sendStuff.ts +++ b/TypescriptServer/src/cmd/sendStuff.ts @@ -13,6 +13,7 @@ import Party from '#matchmaking/party'; import IClient from '#types/client_properties'; import Match from '#matchmaking/match'; import { ISession } from '#schemas/session'; +import Chat from '#concepts/chat'; // sender functions can be later called using some_client.sendThing() @@ -39,6 +40,8 @@ export abstract class SendStuff implements IClient { abstract halfpack: Buffer; abstract entity: PlayerEntity; + abstract chats: Chat[]; + abstract bindTCP(socket: net.Socket): void; abstract bindWS(socket: WebSocket): void; diff --git a/TypescriptServer/src/cmd/senders/chat.ts b/TypescriptServer/src/cmd/senders/chat.ts index a8167c1..b13e266 100644 --- a/TypescriptServer/src/cmd/senders/chat.ts +++ b/TypescriptServer/src/cmd/senders/chat.ts @@ -1,17 +1,29 @@ import SendStuff from "#cmd/sendStuff"; -import { IMessage } from "#schemas/chat"; +import Chat from "#concepts/chat"; +import { IMessage, messageSerialize } from "#schemas/chat"; declare module '#cmd/sendStuff' { interface SendStuff { sendChatMessage(chat_id:string, message:IMessage):void sendChatHistory(chat_id:string, messages:IMessage[]):void + sendChatInfo(chat:Chat):void + sendChatsList():void } } SendStuff.prototype.sendChatMessage = function(chat_id:string, message:IMessage) { - this.send({ cmd: 'chat msg', chat_id, message }); + this.send({ cmd: 'chat msg', chat_id, message: messageSerialize(message) }); } SendStuff.prototype.sendChatHistory = function(chat_id:string, messages:IMessage[]) { - this.send({ cmd: 'chat history', chat_id, history: messages }); + // this.send({ cmd: 'chat history', chat_id, history: messages.map(m => ({ content: m.content, name: m.name, profile_id: null })) }); + this.send({ cmd: 'chat history', chat_id, history: messages.map(messageSerialize) }) +} + +SendStuff.prototype.sendChatInfo = function(chat:Chat) { + this.send({ cmd: 'chat info', chat: chat.serialize() }); +} + +SendStuff.prototype.sendChatsList = function() { + this.send({ cmd: 'chats list', chats: this.chats.map(chat => chat.chat_id) }); } \ No newline at end of file diff --git a/TypescriptServer/src/concepts/chat.ts b/TypescriptServer/src/concepts/chat.ts index 52c0faf..bcfbe5b 100644 --- a/TypescriptServer/src/concepts/chat.ts +++ b/TypescriptServer/src/concepts/chat.ts @@ -13,15 +13,18 @@ export function chatFind(chat_id:string) { return global.chats[chat_id]; } -export function chatCreate(members:IProfile[] = []) { +export function chatCreate(members:IProfile[] = [], isPrivate = false) { let chat_id:string = getRandomId(global.chats); if (chat_id === null) return null; let chatlog = new ChatLog(); chatlog._id = chat_id; + chatlog.private = isPrivate; + let chat = new Chat(chatlog); + for(let member of members) { chat.addMember(member, null, true); } @@ -32,6 +35,12 @@ export function chatCreate(members:IProfile[] = []) { return chat; } +export interface SerializedChat { + chat_id: string, + online_members: string[], + members: string[] +} + export class Chat { chatlog: IChatLog; @@ -100,6 +109,8 @@ export class Chat { if (!client.chats.includes(this)) client.chats.push(this); + + client.sendChatHistory(this.chat_id, this.messages); } disconnectMember(client: Client) { @@ -112,38 +123,41 @@ export class Chat { client.chats.splice(idx, 1); } - writeMessage(client: Client, content: string) { - const message:IMessage = { - profile_id: client.profile.id, - name: client.name, - content - }; + writeMessage(content: string, author: Client|string = 'SYSTEM') { + let name:string, profile_id:string; + + // author is not logged in/anonymous + if (typeof author === 'string') { + name = author; + profile_id = null; + } + else { + name = author.name; + profile_id = author.profile?.id ?? null; + } + + const message = { + name, + content, + profile_id + } + this.messages.push(message); this.save(); // broadcast to all online users this.online_members.forEach( - member => member.sendChatMessage(this.chat_id, message) + client => client.sendChatMessage(this.chat_id, message) ); } + + serialize():SerializedChat { + return { + chat_id: this.chat_id, + members: this.members.map(profile_id => profile_id.toString()), + online_members: this.online_members.map(client => client.name) + } + } } -export default Chat; - -// export class GlobalChat extends Chat { -// constructor() { -// // super(global.clients); -// } -// } - -// export class DirectChat extends Chat { -// constructor(client1:Client, client2:Client) { -// // super([client1, client2]); -// } -// } - -// export class GroupChat extends Chat { -// constructor(members: Client[]) { -// // super(members); -// } -// } \ No newline at end of file +export default Chat; \ No newline at end of file diff --git a/TypescriptServer/src/concepts/client.ts b/TypescriptServer/src/concepts/client.ts index cc9ec5c..ace4e4a 100644 --- a/TypescriptServer/src/concepts/client.ts +++ b/TypescriptServer/src/concepts/client.ts @@ -62,7 +62,7 @@ export default class Client extends SendStuff implements IClient { /** @type {Match} */ match: Match = null; - /** @type {Chat[]} */ + /** @type {string[]} */ chats: Chat[] = []; @@ -662,14 +662,23 @@ export default class Client extends SendStuff implements IClient { } } + chatLeave(chat_id: string) { + if (!this.profile) + return; + + let chat = chatFind(chat_id); + if (chat) { + chat.kickMember(this.profile); + } + } + chatConnectAll() { if (!this.profile) return; this.profile.chats.forEach(chat_id => { - let chat = global.chats[chat_id.toString()]; - chat.connectMember(this); - + let chat = chatFind(chat_id); + chat?.connectMember(this); }); } diff --git a/TypescriptServer/src/initializers/00_exit_handler.ts b/TypescriptServer/src/initializers/00_exit_handler.ts index 6cb0a37..cd71f56 100644 --- a/TypescriptServer/src/initializers/00_exit_handler.ts +++ b/TypescriptServer/src/initializers/00_exit_handler.ts @@ -18,8 +18,7 @@ async function onProcessExit(exitCode:number = undefined) { trace('Exiting the process...'); - if (this.noexit === undefined) - process.exit(); + process.exit(); } // do something when app is closing diff --git a/TypescriptServer/src/initializers/15_chats.ts b/TypescriptServer/src/initializers/15_chats.ts index 71977a5..f8ef0dc 100644 --- a/TypescriptServer/src/initializers/15_chats.ts +++ b/TypescriptServer/src/initializers/15_chats.ts @@ -1,6 +1,7 @@ import Chat, { chatCreate } from "#concepts/chat"; import ChatLog from "#schemas/chat"; +// create instances of every chat from the DB const chatLogs = await ChatLog.find({}); chatLogs.forEach(chatlog => { let chat = new Chat(chatlog); @@ -8,4 +9,13 @@ chatLogs.forEach(chatlog => { }); +// create a new id=0 "global" chat if it doesn't exist already +if (global.chats['0'] === undefined) { + let chatlog = new ChatLog(); + chatlog._id = '0'; + + let chat = new Chat(chatlog); + global.chats['0'] = chat; +} + // chatCreate([]); \ No newline at end of file diff --git a/TypescriptServer/src/schemas/chat.ts b/TypescriptServer/src/schemas/chat.ts index 7f3191c..6cc5cc8 100644 --- a/TypescriptServer/src/schemas/chat.ts +++ b/TypescriptServer/src/schemas/chat.ts @@ -10,6 +10,21 @@ export interface IMessage { content: string; } +export interface SerializedMessage { + profile_id?: string; + name: string; + content: string; +} + +// for some reason trying to msgpack.encode message with ObjectId leads to a circular reference (???) +export function messageSerialize(msg:IMessage):SerializedMessage { + return { + name: msg.name, + content: msg.content, + profile_id: msg.profile_id?.toString() + } +} + const messageSchema = new Schema({ profile_id: { type: Schema.Types.ObjectId, ref: 'Profile', required: false }, name: String, @@ -19,6 +34,7 @@ const messageSchema = new Schema({ export interface IChatLog extends Document { _id: string, type: ChatType, + private: boolean, messages: IMessage[], members: ObjectId[] } @@ -27,6 +43,8 @@ export interface IChatLog extends Document { const chatSchema = new Schema({ _id: { type: String, unique: true, index: true }, + private: { type: Boolean, default: false }, + type: { type: String, default: 'group' }, messages: [messageSchema], members: [ { type: Schema.Types.ObjectId, ref: 'Profile' } diff --git a/TypescriptServer/src/util/names.ts b/TypescriptServer/src/util/names.ts index fc031b3..d44c0f7 100644 --- a/TypescriptServer/src/util/names.ts +++ b/TypescriptServer/src/util/names.ts @@ -11,6 +11,8 @@ export class Names { if (name.startsWith('guest')) { return false; } + if (name === 'system') + return false; return true; }