extended animation support, add /anim command (TODO: animation list, command help)
This commit is contained in:
parent
5550303284
commit
59efab9300
10 changed files with 155 additions and 18 deletions
|
@ -378,6 +378,12 @@ export class Agent {
|
||||||
if (index !== -1) this.playAnimation(index, finishCallback);
|
if (index !== -1) this.playAnimation(index, finishCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playAnimationByNamePromise(name: string): Promise<void> {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
this.playAnimationByName(name, () => res());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setUsername(username: string, color: string) {
|
setUsername(username: string, color: string) {
|
||||||
if (this.usernameBalloonState !== null) {
|
if (this.usernameBalloonState !== null) {
|
||||||
this.usernameBalloonState.finish();
|
this.usernameBalloonState.finish();
|
||||||
|
@ -420,13 +426,10 @@ export class Agent {
|
||||||
this.y = randint(0, document.documentElement.clientHeight - this.data.characterInfo.charHeight);
|
this.y = randint(0, document.documentElement.clientHeight - this.data.characterInfo.charHeight);
|
||||||
this.setLoc();
|
this.setLoc();
|
||||||
this.cnv.style.display = 'block';
|
this.cnv.style.display = 'block';
|
||||||
this.playAnimationByName('Show', () => {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hide(remove: boolean = false) {
|
hide(remove: boolean = false) {
|
||||||
this.playAnimationByName('Hide', () => {
|
|
||||||
if (remove) this.remove();
|
if (remove) this.remove();
|
||||||
else this.cnv.style.display = 'none';
|
else this.cnv.style.display = 'none';
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ export enum MSAgentProtocolMessageType {
|
||||||
KeepAlive = 'nop',
|
KeepAlive = 'nop',
|
||||||
Join = 'join',
|
Join = 'join',
|
||||||
Talk = 'talk',
|
Talk = 'talk',
|
||||||
|
PlayAnimation = 'anim',
|
||||||
SendImage = 'img',
|
SendImage = 'img',
|
||||||
Admin = 'admin',
|
Admin = 'admin',
|
||||||
// Server-to-client
|
// Server-to-client
|
||||||
|
@ -20,6 +21,14 @@ export interface MSAgentProtocolMessage {
|
||||||
op: MSAgentProtocolMessageType;
|
op: MSAgentProtocolMessageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AgentAnimationConfig {
|
||||||
|
join: string[];
|
||||||
|
chat: string[];
|
||||||
|
idle: string[];
|
||||||
|
rest: string[];
|
||||||
|
leave: string[];
|
||||||
|
}
|
||||||
|
|
||||||
// Client-to-server
|
// Client-to-server
|
||||||
|
|
||||||
export interface MSAgentJoinMessage extends MSAgentProtocolMessage {
|
export interface MSAgentJoinMessage extends MSAgentProtocolMessage {
|
||||||
|
@ -37,6 +46,14 @@ export interface MSAgentTalkMessage extends MSAgentProtocolMessage {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MSAgentPlayAnimationMessage extends MSAgentProtocolMessage {
|
||||||
|
op: MSAgentProtocolMessageType.PlayAnimation;
|
||||||
|
data: {
|
||||||
|
anim: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface MSAgentSendImageMessage extends MSAgentProtocolMessage {
|
export interface MSAgentSendImageMessage extends MSAgentProtocolMessage {
|
||||||
op: MSAgentProtocolMessageType.SendImage;
|
op: MSAgentProtocolMessageType.SendImage;
|
||||||
data: {
|
data: {
|
||||||
|
@ -56,6 +73,7 @@ export interface MSAgentInitMessage extends MSAgentProtocolMessage {
|
||||||
username: string;
|
username: string;
|
||||||
agent: string;
|
agent: string;
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
|
animations: AgentAnimationConfig;
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -65,6 +83,7 @@ export interface MSAgentAddUserMessage extends MSAgentProtocolMessage {
|
||||||
data: {
|
data: {
|
||||||
username: string;
|
username: string;
|
||||||
agent: string;
|
agent: string;
|
||||||
|
animations: AgentAnimationConfig;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +103,14 @@ export interface MSAgentChatMessage extends MSAgentProtocolMessage {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MSAgentAnimationMessage extends MSAgentProtocolMessage {
|
||||||
|
op: MSAgentProtocolMessageType.PlayAnimation;
|
||||||
|
data: {
|
||||||
|
username: string;
|
||||||
|
anim: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface MSAgentImageMessage extends MSAgentProtocolMessage {
|
export interface MSAgentImageMessage extends MSAgentProtocolMessage {
|
||||||
op: MSAgentProtocolMessageType.SendImage;
|
op: MSAgentProtocolMessageType.SendImage;
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -23,6 +23,7 @@ bannedWords = []
|
||||||
|
|
||||||
[chat.ratelimits]
|
[chat.ratelimits]
|
||||||
chat = {seconds = 10, limit = 8}
|
chat = {seconds = 10, limit = 8}
|
||||||
|
anim = {seconds = 10, limit = 8}
|
||||||
|
|
||||||
[motd]
|
[motd]
|
||||||
version = 1
|
version = 1
|
||||||
|
@ -58,71 +59,89 @@ expirySeconds = 60
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Clippy"
|
friendlyName = "Clippy"
|
||||||
filename = "CLIPPIT.ACS"
|
filename = "CLIPPIT.ACS"
|
||||||
|
animations = { join = ["Greeting"], chat = ["Explain"], idle = [], leave = ["GoodBye"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Courtney"
|
friendlyName = "Courtney"
|
||||||
filename = "courtney.acs"
|
filename = "courtney.acs"
|
||||||
|
animations = { join = ["Show", "Greet"], chat = ["GetAttentionMinor"], idle = [], leave = ["Disappear"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Dot"
|
friendlyName = "Dot"
|
||||||
filename = "DOT.ACS"
|
filename = "DOT.ACS"
|
||||||
|
animations = { join = ["Greeting", "Show"], chat = ["Alert", "Show"], idle = [], leave = ["Goodbye"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Earl"
|
friendlyName = "Earl"
|
||||||
filename = "earl.acs"
|
filename = "earl.acs"
|
||||||
|
animations = { join = ["Show", "Greet"], chat = ["LookUp"], idle = [], leave = ["Disappear"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "F1"
|
friendlyName = "F1"
|
||||||
filename = "F1.ACS"
|
filename = "F1.ACS"
|
||||||
|
animations = { join = ["Show"], chat = ["Explain"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Genie"
|
friendlyName = "Genie"
|
||||||
filename = "Genie.acs"
|
filename = "Genie.acs"
|
||||||
|
animations = { join = ["Show"], chat = ["Suggest", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "James"
|
friendlyName = "James"
|
||||||
filename = "James.acs"
|
filename = "James.acs"
|
||||||
|
animations = { join = ["Show"], chat = ["Suggest", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Links"
|
friendlyName = "Links"
|
||||||
filename = "Links.ACS"
|
filename = "Links.ACS"
|
||||||
|
animations = { join = ["Greeting"], chat = ["GetAttention"], idle = [], leave = ["GoodBye"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Merlin"
|
friendlyName = "Merlin"
|
||||||
filename = "merlin.acs"
|
filename = "merlin.acs"
|
||||||
|
animations = { join = ["Show"], chat = ["Explain", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Mother Nature"
|
friendlyName = "Mother Nature"
|
||||||
filename = "Mother_NATURE.ACS"
|
filename = "Mother_NATURE.ACS"
|
||||||
|
animations = { join = ["Greeting"], chat = ["Explain"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Office Logo"
|
friendlyName = "Office Logo"
|
||||||
filename = "Office_Logo.ACS"
|
filename = "Office_Logo.ACS"
|
||||||
|
animations = { join = ["Greeting"], chat = ["Explain"], idle = [], leave = ["Goodbye"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Peedy"
|
friendlyName = "Peedy"
|
||||||
filename = "Peedy.acs"
|
filename = "Peedy.acs"
|
||||||
|
animations = { join = ["Show", "Greet", "RestPose"], chat = ["Thinking", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
#[[agents]]
|
[[agents]]
|
||||||
#friendlyName = "Question"
|
friendlyName = "Question"
|
||||||
#filename = "question_mark.acs"
|
filename = "question_mark.acs"
|
||||||
|
animations = { join = ["Welcome"], chat = ["Shimmer"], idle = [], leave = ["Fade"], rest = ["Restpose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Robby"
|
friendlyName = "Robby"
|
||||||
filename = "Robby.acs"
|
filename = "Robby.acs"
|
||||||
|
animations = { join = ["Show", "Greet", "RestPose"], chat = ["Thinking", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Rocky"
|
friendlyName = "Rocky"
|
||||||
filename = "ROCKY.ACS"
|
filename = "ROCKY.ACS"
|
||||||
|
animations = { join = ["Show"], chat = ["Alert"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Rover"
|
friendlyName = "Rover"
|
||||||
filename = "rover.acs"
|
filename = "rover.acs"
|
||||||
|
animations = { join = ["Show", "Greet", "RestPose"], chat = ["Thinking", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Victor"
|
friendlyName = "Victor"
|
||||||
filename = "Victor.acs"
|
filename = "Victor.acs"
|
||||||
|
animations = { join = ["Show", "Greet", "RestPose"], chat = ["Thinking", "RestPose"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
||||||
|
|
||||||
[[agents]]
|
[[agents]]
|
||||||
friendlyName = "Bonzi"
|
friendlyName = "Bonzi"
|
||||||
filename = "Bonzi.acs"
|
filename = "Bonzi.acs"
|
||||||
|
animations = { join = ["Show", "Wave", "RestPose"], chat = ["Giggle"], idle = [], leave = ["Hide"], rest = ["RestPose"] }
|
|
@ -14,7 +14,8 @@ import {
|
||||||
MSAgentJoinMessage,
|
MSAgentJoinMessage,
|
||||||
MSAgentProtocolMessage,
|
MSAgentProtocolMessage,
|
||||||
MSAgentProtocolMessageType,
|
MSAgentProtocolMessageType,
|
||||||
MSAgentTalkMessage
|
MSAgentTalkMessage,
|
||||||
|
MSAgentPlayAnimationMessage
|
||||||
} from '@msagent-chat/protocol';
|
} from '@msagent-chat/protocol';
|
||||||
import { MSAgentChatRoom } from './room.js';
|
import { MSAgentChatRoom } from './room.js';
|
||||||
import * as htmlentities from 'html-entities';
|
import * as htmlentities from 'html-entities';
|
||||||
|
@ -27,6 +28,7 @@ export interface Client {
|
||||||
on(event: 'join', listener: () => void): this;
|
on(event: 'join', listener: () => void): this;
|
||||||
on(event: 'close', listener: () => void): this;
|
on(event: 'close', listener: () => void): this;
|
||||||
on(event: 'talk', listener: (msg: string) => void): this;
|
on(event: 'talk', listener: (msg: string) => void): this;
|
||||||
|
on(event: 'animation', listener: (anim: string) => void): this;
|
||||||
on(event: 'image', listener: (id: string) => void): this;
|
on(event: 'image', listener: (id: string) => void): this;
|
||||||
|
|
||||||
on(event: string, listener: Function): this;
|
on(event: string, listener: Function): this;
|
||||||
|
@ -45,6 +47,7 @@ export class Client extends EventEmitter {
|
||||||
nopLevel: number;
|
nopLevel: number;
|
||||||
|
|
||||||
chatRateLimit: RateLimiter;
|
chatRateLimit: RateLimiter;
|
||||||
|
animRateLimit: RateLimiter;
|
||||||
|
|
||||||
constructor(socket: WebSocket, room: MSAgentChatRoom, ip: string) {
|
constructor(socket: WebSocket, room: MSAgentChatRoom, ip: string) {
|
||||||
super();
|
super();
|
||||||
|
@ -58,6 +61,7 @@ export class Client extends EventEmitter {
|
||||||
this.nopLevel = 0;
|
this.nopLevel = 0;
|
||||||
|
|
||||||
this.chatRateLimit = new RateLimiter(this.room.config.ratelimits.chat);
|
this.chatRateLimit = new RateLimiter(this.room.config.ratelimits.chat);
|
||||||
|
this.animRateLimit = new RateLimiter(this.room.config.ratelimits.anim);
|
||||||
|
|
||||||
this.socket.on('message', (msg, isBinary) => {
|
this.socket.on('message', (msg, isBinary) => {
|
||||||
if (isBinary) {
|
if (isBinary) {
|
||||||
|
@ -162,6 +166,12 @@ export class Client extends EventEmitter {
|
||||||
this.emit('talk', talkMsg.data.msg);
|
this.emit('talk', talkMsg.data.msg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSAgentProtocolMessageType.PlayAnimation: {
|
||||||
|
let animMsg = msg as MSAgentPlayAnimationMessage;
|
||||||
|
if (!animMsg.data || !animMsg.data.anim || !this.animRateLimit.request()) return;
|
||||||
|
this.emit('animation', animMsg.data.anim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MSAgentProtocolMessageType.SendImage: {
|
case MSAgentProtocolMessageType.SendImage: {
|
||||||
let imgMsg = msg as MSAgentSendImageMessage;
|
let imgMsg = msg as MSAgentSendImageMessage;
|
||||||
if (!imgMsg.data || !imgMsg.data.id || !this.chatRateLimit.request()) return;
|
if (!imgMsg.data || !imgMsg.data.id || !this.chatRateLimit.request()) return;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { AgentAnimationConfig } from "@msagent-chat/protocol";
|
||||||
|
|
||||||
export interface IConfig {
|
export interface IConfig {
|
||||||
http: {
|
http: {
|
||||||
host: string;
|
host: string;
|
||||||
|
@ -31,6 +33,7 @@ export interface ChatConfig {
|
||||||
bannedWords: string[];
|
bannedWords: string[];
|
||||||
ratelimits: {
|
ratelimits: {
|
||||||
chat: RateLimitConfig;
|
chat: RateLimitConfig;
|
||||||
|
anim: RateLimitConfig;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +45,7 @@ export interface motdConfig {
|
||||||
export interface AgentConfig {
|
export interface AgentConfig {
|
||||||
friendlyName: string;
|
friendlyName: string;
|
||||||
filename: string;
|
filename: string;
|
||||||
|
animations: AgentAnimationConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RateLimitConfig {
|
export interface RateLimitConfig {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import {
|
import {
|
||||||
MSAgentAddUserMessage,
|
MSAgentAddUserMessage,
|
||||||
|
MSAgentAnimationMessage,
|
||||||
MSAgentChatMessage,
|
MSAgentChatMessage,
|
||||||
MSAgentImageMessage,
|
MSAgentImageMessage,
|
||||||
MSAgentInitMessage,
|
MSAgentInitMessage,
|
||||||
MSAgentPromoteMessage,
|
MSAgentPromoteMessage,
|
||||||
MSAgentProtocolMessage,
|
|
||||||
MSAgentProtocolMessageType,
|
MSAgentProtocolMessageType,
|
||||||
MSAgentRemoveUserMessage
|
MSAgentRemoveUserMessage
|
||||||
} from '@msagent-chat/protocol';
|
} from '@msagent-chat/protocol';
|
||||||
|
@ -52,6 +52,7 @@ export class MSAgentChatRoom {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
client.on('join', () => {
|
client.on('join', () => {
|
||||||
|
let agent = this.agents.find(a => a.filename === client.agent)!;
|
||||||
let initmsg: MSAgentInitMessage = {
|
let initmsg: MSAgentInitMessage = {
|
||||||
op: MSAgentProtocolMessageType.Init,
|
op: MSAgentProtocolMessageType.Init,
|
||||||
data: {
|
data: {
|
||||||
|
@ -64,7 +65,8 @@ export class MSAgentChatRoom {
|
||||||
return {
|
return {
|
||||||
username: c.username!,
|
username: c.username!,
|
||||||
agent: c.agent!,
|
agent: c.agent!,
|
||||||
admin: c.admin
|
admin: c.admin,
|
||||||
|
animations: this.agents.find(a => a.filename === c.agent)!.animations
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -74,7 +76,8 @@ export class MSAgentChatRoom {
|
||||||
op: MSAgentProtocolMessageType.AddUser,
|
op: MSAgentProtocolMessageType.AddUser,
|
||||||
data: {
|
data: {
|
||||||
username: client.username!,
|
username: client.username!,
|
||||||
agent: client.agent!
|
agent: client.agent!,
|
||||||
|
animations: agent.animations
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (const _client of this.getActiveClients().filter((c) => c !== client)) {
|
for (const _client of this.getActiveClients().filter((c) => c !== client)) {
|
||||||
|
@ -104,6 +107,18 @@ export class MSAgentChatRoom {
|
||||||
}
|
}
|
||||||
this.discord?.logMsg(client.username!, message);
|
this.discord?.logMsg(client.username!, message);
|
||||||
});
|
});
|
||||||
|
client.on('animation', async anim => {
|
||||||
|
let msg: MSAgentAnimationMessage = {
|
||||||
|
op: MSAgentProtocolMessageType.PlayAnimation,
|
||||||
|
data: {
|
||||||
|
username: client.username!,
|
||||||
|
anim: anim
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (const _client of this.getActiveClients()) {
|
||||||
|
_client.send(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
client.on('image', async (id) => {
|
client.on('image', async (id) => {
|
||||||
if (!this.img.has(id)) return;
|
if (!this.img.has(id)) return;
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,13 @@ import {
|
||||||
MSAgentAdminLoginResponse,
|
MSAgentAdminLoginResponse,
|
||||||
MSAgentAdminMessage,
|
MSAgentAdminMessage,
|
||||||
MSAgentAdminOperation,
|
MSAgentAdminOperation,
|
||||||
|
MSAgentAnimationMessage,
|
||||||
MSAgentChatMessage,
|
MSAgentChatMessage,
|
||||||
MSAgentErrorMessage,
|
MSAgentErrorMessage,
|
||||||
MSAgentImageMessage,
|
MSAgentImageMessage,
|
||||||
MSAgentInitMessage,
|
MSAgentInitMessage,
|
||||||
MSAgentJoinMessage,
|
MSAgentJoinMessage,
|
||||||
|
MSAgentPlayAnimationMessage,
|
||||||
MSAgentPromoteMessage,
|
MSAgentPromoteMessage,
|
||||||
MSAgentProtocolMessage,
|
MSAgentProtocolMessage,
|
||||||
MSAgentProtocolMessageType,
|
MSAgentProtocolMessageType,
|
||||||
|
@ -174,6 +176,16 @@ export class MSAgentClient {
|
||||||
this.send(talkMsg);
|
this.send(talkMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animation(anim: string) {
|
||||||
|
let msg: MSAgentPlayAnimationMessage = {
|
||||||
|
op: MSAgentProtocolMessageType.PlayAnimation,
|
||||||
|
data: {
|
||||||
|
anim
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.send(msg);
|
||||||
|
}
|
||||||
|
|
||||||
async sendImage(img: ArrayBuffer, type: string) {
|
async sendImage(img: ArrayBuffer, type: string) {
|
||||||
// Upload image
|
// Upload image
|
||||||
let res = await fetch(this.url + '/api/upload', {
|
let res = await fetch(this.url + '/api/upload', {
|
||||||
|
@ -296,8 +308,9 @@ export class MSAgentClient {
|
||||||
let agent = await agentCreateCharacterFromUrl(this.url + '/api/agents/' + _user.agent);
|
let agent = await agentCreateCharacterFromUrl(this.url + '/api/agents/' + _user.agent);
|
||||||
agent.setUsername(_user.username, _user.admin ? '#FF0000' : '#000000');
|
agent.setUsername(_user.username, _user.admin ? '#FF0000' : '#000000');
|
||||||
agent.addToDom(this.agentContainer);
|
agent.addToDom(this.agentContainer);
|
||||||
|
let user = new User(_user.username, agent, _user.animations);
|
||||||
agent.show();
|
agent.show();
|
||||||
let user = new User(_user.username, agent);
|
user.doAnim('join');
|
||||||
this.setContextMenu(user);
|
this.setContextMenu(user);
|
||||||
this.users.push(user);
|
this.users.push(user);
|
||||||
}
|
}
|
||||||
|
@ -309,8 +322,9 @@ export class MSAgentClient {
|
||||||
let agent = await agentCreateCharacterFromUrl(this.url + '/api/agents/' + addUserMsg.data.agent);
|
let agent = await agentCreateCharacterFromUrl(this.url + '/api/agents/' + addUserMsg.data.agent);
|
||||||
agent.setUsername(addUserMsg.data.username, '#000000');
|
agent.setUsername(addUserMsg.data.username, '#000000');
|
||||||
agent.addToDom(this.agentContainer);
|
agent.addToDom(this.agentContainer);
|
||||||
|
let user = new User(addUserMsg.data.username, agent, addUserMsg.data.animations);
|
||||||
agent.show();
|
agent.show();
|
||||||
let user = new User(addUserMsg.data.username, agent);
|
user.doAnim('join');
|
||||||
this.setContextMenu(user);
|
this.setContextMenu(user);
|
||||||
this.users.push(user);
|
this.users.push(user);
|
||||||
this.events.emit('adduser', user);
|
this.events.emit('adduser', user);
|
||||||
|
@ -320,7 +334,9 @@ export class MSAgentClient {
|
||||||
let remUserMsg = msg as MSAgentRemoveUserMessage;
|
let remUserMsg = msg as MSAgentRemoveUserMessage;
|
||||||
let user = this.users.find((u) => u.username === remUserMsg.data.username);
|
let user = this.users.find((u) => u.username === remUserMsg.data.username);
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
user.doAnim('leave').then(() => {
|
||||||
user.agent.hide(true);
|
user.agent.hide(true);
|
||||||
|
});
|
||||||
if (this.playingAudio.has(user!.username)) {
|
if (this.playingAudio.has(user!.username)) {
|
||||||
this.playingAudio.get(user!.username)?.pause();
|
this.playingAudio.get(user!.username)?.pause();
|
||||||
this.playingAudio.delete(user!.username);
|
this.playingAudio.delete(user!.username);
|
||||||
|
@ -337,6 +353,7 @@ export class MSAgentClient {
|
||||||
this.events.emit('chat', user, chatMsg.data.message);
|
this.events.emit('chat', user, chatMsg.data.message);
|
||||||
|
|
||||||
user?.agent.speak(chatMsg.data.message);
|
user?.agent.speak(chatMsg.data.message);
|
||||||
|
user?.doAnim('chat');
|
||||||
let msgId = ++user!.msgId;
|
let msgId = ++user!.msgId;
|
||||||
|
|
||||||
if (chatMsg.data.audio !== undefined) {
|
if (chatMsg.data.audio !== undefined) {
|
||||||
|
@ -368,6 +385,14 @@ export class MSAgentClient {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MSAgentProtocolMessageType.PlayAnimation: {
|
||||||
|
let animMsg = msg as MSAgentAnimationMessage;
|
||||||
|
let user = this.users.find((u) => u.username === animMsg.data.username);
|
||||||
|
if (!user || user.muted) return;
|
||||||
|
await user.agent.playAnimationByNamePromise(animMsg.data.anim);
|
||||||
|
await user.doAnim('rest');
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MSAgentProtocolMessageType.SendImage: {
|
case MSAgentProtocolMessageType.SendImage: {
|
||||||
let imgMsg = msg as MSAgentImageMessage;
|
let imgMsg = msg as MSAgentImageMessage;
|
||||||
let user = this.users.find((u) => u.username === imgMsg.data.username);
|
let user = this.users.find((u) => u.username === imgMsg.data.username);
|
||||||
|
|
18
webapp/src/ts/commands.ts
Normal file
18
webapp/src/ts/commands.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { MSAgentClient } from "./client.js";
|
||||||
|
|
||||||
|
export function InitCommands() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RunCommand(command: string, room: MSAgentClient) {
|
||||||
|
let arr = command.split(' ');
|
||||||
|
let cmd = arr[0];
|
||||||
|
let args = arr.slice(1);
|
||||||
|
switch (cmd) {
|
||||||
|
case '/anim': {
|
||||||
|
let anim = args.join(' ');
|
||||||
|
room.animation(anim);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { MSWindow, MSWindowStartPosition } from './MSWindow.js';
|
||||||
import { agentInit } from '@msagent-chat/msagent.js';
|
import { agentInit } from '@msagent-chat/msagent.js';
|
||||||
import { MSAgentClient } from './client.js';
|
import { MSAgentClient } from './client.js';
|
||||||
import { Config } from '../../config.js';
|
import { Config } from '../../config.js';
|
||||||
|
import { RunCommand } from './commands.js';
|
||||||
|
|
||||||
const elements = {
|
const elements = {
|
||||||
motdWindow: document.getElementById('motdWindow') as HTMLDivElement,
|
motdWindow: document.getElementById('motdWindow') as HTMLDivElement,
|
||||||
|
@ -120,7 +121,12 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
|
||||||
function talk() {
|
function talk() {
|
||||||
if (Room === null) return;
|
if (Room === null) return;
|
||||||
Room.talk(elements.chatInput.value);
|
let msg = elements.chatInput.value;
|
||||||
|
if (msg.startsWith('/')) {
|
||||||
|
RunCommand(msg, Room);
|
||||||
|
} else {
|
||||||
|
Room.talk(msg);
|
||||||
|
}
|
||||||
elements.chatInput.value = '';
|
elements.chatInput.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Agent } from '@msagent-chat/msagent.js';
|
import { Agent } from '@msagent-chat/msagent.js';
|
||||||
|
import { AgentAnimationConfig } from '@msagent-chat/protocol';
|
||||||
|
|
||||||
export class User {
|
export class User {
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -6,11 +7,20 @@ export class User {
|
||||||
muted: boolean;
|
muted: boolean;
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
msgId: number = 0;
|
msgId: number = 0;
|
||||||
|
animations: AgentAnimationConfig;
|
||||||
|
|
||||||
constructor(username: string, agent: Agent) {
|
constructor(username: string, agent: Agent, animations: AgentAnimationConfig) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
this.muted = false;
|
this.muted = false;
|
||||||
this.admin = false;
|
this.admin = false;
|
||||||
|
this.animations = animations;
|
||||||
|
}
|
||||||
|
|
||||||
|
async doAnim(action: string) {
|
||||||
|
// @ts-ignore
|
||||||
|
for (let anim of this.animations[action]) {
|
||||||
|
await this.agent.playAnimationByNamePromise(anim);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue