Add experimental multiuserroom
This commit is contained in:
@@ -708,4 +708,10 @@ export const languageEnglish = {
|
|||||||
customCSS: "Custom CSS",
|
customCSS: "Custom CSS",
|
||||||
betaMobileGUI: "Beta Mobile GUI",
|
betaMobileGUI: "Beta Mobile GUI",
|
||||||
menu: "Menu",
|
menu: "Menu",
|
||||||
|
connectionOpen: "Connection Open",
|
||||||
|
connectionOpenInfo: "Multiuser room is opened. you can share the room code to other users. others can join the room by using the code inside playground > Join Multiuser Room.",
|
||||||
|
createMultiuserRoom: "Create Multiuser Room",
|
||||||
|
connectionHost: "You are the host of the room.",
|
||||||
|
connectionGuest: "You are the guest of the room.",
|
||||||
|
otherUserRequesting: "Other user is already requesting. try again later.",
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
import { capitalize } from "src/ts/util";
|
import { capitalize } from "src/ts/util";
|
||||||
import { longpress } from "src/ts/gui/longtouch";
|
import { longpress } from "src/ts/gui/longtouch";
|
||||||
import { ColorSchemeTypeStore } from "src/ts/gui/colorscheme";
|
import { ColorSchemeTypeStore } from "src/ts/gui/colorscheme";
|
||||||
|
import { ConnectionOpenStore } from "src/ts/sync/multiuser";
|
||||||
export let message = ''
|
export let message = ''
|
||||||
export let name = ''
|
export let name = ''
|
||||||
export let largePortrait = false
|
export let largePortrait = false
|
||||||
@@ -202,20 +203,22 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button class={"ml-2 hover:text-green-500 transition-colors "+(editMode?'text-green-400':'')} on:click={() => {
|
{#if !$ConnectionOpenStore}
|
||||||
if(!editMode){
|
<button class={"ml-2 hover:text-green-500 transition-colors "+(editMode?'text-green-400':'')} on:click={() => {
|
||||||
editMode = true
|
if(!editMode){
|
||||||
}
|
editMode = true
|
||||||
else{
|
}
|
||||||
editMode = false
|
else{
|
||||||
edit()
|
editMode = false
|
||||||
}
|
edit()
|
||||||
}}>
|
}
|
||||||
<PencilIcon size={20}/>
|
}}>
|
||||||
</button>
|
<PencilIcon size={20}/>
|
||||||
<button class="ml-2 hover:text-green-500 transition-colors" on:click={(e) => rm(e, false)} use:longpress={(e) => rm(e, true)}>
|
</button>
|
||||||
<TrashIcon size={20}/>
|
<button class="ml-2 hover:text-green-500 transition-colors" on:click={(e) => rm(e, false)} use:longpress={(e) => rm(e, true)}>
|
||||||
</button>
|
<TrashIcon size={20}/>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if $DataBase.translator !== '' && !blankMessage}
|
{#if $DataBase.translator !== '' && !blankMessage}
|
||||||
<button class={"ml-2 cursor-pointer hover:text-green-500 transition-colors " + (translated ? 'text-green-400':'')} class:translating={translating} on:click={async () => {
|
<button class={"ml-2 cursor-pointer hover:text-green-500 transition-colors " + (translated ? 'text-green-400':'')} class:translating={translating} on:click={async () => {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
import { postChatFile } from 'src/ts/process/files/multisend';
|
import { postChatFile } from 'src/ts/process/files/multisend';
|
||||||
import { getInlayImage } from 'src/ts/process/files/image';
|
import { getInlayImage } from 'src/ts/process/files/image';
|
||||||
import PlaygroundMenu from '../Playground/PlaygroundMenu.svelte';
|
import PlaygroundMenu from '../Playground/PlaygroundMenu.svelte';
|
||||||
|
import { ConnectionOpenStore } from 'src/ts/sync/multiuser';
|
||||||
|
|
||||||
let messageInput:string = ''
|
let messageInput:string = ''
|
||||||
let messageInputTranslate:string = ''
|
let messageInputTranslate:string = ''
|
||||||
@@ -81,7 +82,8 @@
|
|||||||
if($DataBase.useSayNothing){
|
if($DataBase.useSayNothing){
|
||||||
cha.push({
|
cha.push({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
data: '*says nothing*'
|
data: '*says nothing*',
|
||||||
|
name: $ConnectionOpenStore ? $CurrentUsername : null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,14 +100,16 @@
|
|||||||
cha.push({
|
cha.push({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
data: await processScript(char,messageInput,'editinput'),
|
data: await processScript(char,messageInput,'editinput'),
|
||||||
time: Date.now()
|
time: Date.now(),
|
||||||
|
name: $ConnectionOpenStore ? $CurrentUsername : null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
cha.push({
|
cha.push({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
data: messageInput,
|
data: messageInput,
|
||||||
time: Date.now()
|
time: Date.now(),
|
||||||
|
name: $ConnectionOpenStore ? $CurrentUsername : null
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -583,9 +587,9 @@
|
|||||||
<Chat
|
<Chat
|
||||||
character={$CurrentSimpleCharacter}
|
character={$CurrentSimpleCharacter}
|
||||||
idx={chat.index}
|
idx={chat.index}
|
||||||
name={$CurrentUsername}
|
name={chat.name ?? $CurrentUsername}
|
||||||
message={chat.data}
|
message={chat.data}
|
||||||
img={getCharImage($CurrentUserIcon, 'css')}
|
img={$ConnectionOpenStore ? '' : getCharImage($CurrentUserIcon, 'css')}
|
||||||
isLastMemory={$CurrentChat.lastMemory === (chat.chatId ?? 'none') && $CurrentShowMemoryLimit}
|
isLastMemory={$CurrentChat.lastMemory === (chat.chatId ?? 'none') && $CurrentShowMemoryLimit}
|
||||||
largePortrait={$UserIconProtrait}
|
largePortrait={$UserIconProtrait}
|
||||||
MessageGenerationInfo={chat.generationInfo}
|
MessageGenerationInfo={chat.generationInfo}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
import TextAreaInput from "../UI/GUI/TextAreaInput.svelte";
|
import TextAreaInput from "../UI/GUI/TextAreaInput.svelte";
|
||||||
import ModuleChatMenu from "../Setting/Pages/Module/ModuleChatMenu.svelte";
|
import ModuleChatMenu from "../Setting/Pages/Module/ModuleChatMenu.svelte";
|
||||||
import { ColorSchemeTypeStore } from "src/ts/gui/colorscheme";
|
import { ColorSchemeTypeStore } from "src/ts/gui/colorscheme";
|
||||||
|
import Help from "./Help.svelte";
|
||||||
let btn
|
let btn
|
||||||
let input = ''
|
let input = ''
|
||||||
let cardExportType = 'realm'
|
let cardExportType = 'realm'
|
||||||
@@ -399,6 +400,21 @@
|
|||||||
<ChevronRightIcon />
|
<ChevronRightIcon />
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
{#if $DataBase.useExperimental}
|
||||||
|
<button class="border-darkborderc border py-2 px-8 flex rounded-md hover:ring-2 items-center mt-2" on:click={() => {
|
||||||
|
alertStore.set({
|
||||||
|
type: 'none',
|
||||||
|
msg: '2'
|
||||||
|
})
|
||||||
|
}}>
|
||||||
|
<div class="flex flex-col justify-start items-start">
|
||||||
|
<span>{language.createMultiuserRoom} <Help key="experimental"/></span>
|
||||||
|
</div>
|
||||||
|
<div class="ml-9 float-right flex-1 flex justify-end">
|
||||||
|
<ChevronRightIcon />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
<button class="border-darkborderc border py-2 px-8 flex rounded-md hover:ring-2 items-center mt-2" on:click={() => {
|
<button class="border-darkborderc border py-2 px-8 flex rounded-md hover:ring-2 items-center mt-2" on:click={() => {
|
||||||
alertStore.set({
|
alertStore.set({
|
||||||
type: 'none',
|
type: 'none',
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
import PlaygroundImageGen from "./PlaygroundImageGen.svelte";
|
import PlaygroundImageGen from "./PlaygroundImageGen.svelte";
|
||||||
import PlaygroundParser from "./PlaygroundParser.svelte";
|
import PlaygroundParser from "./PlaygroundParser.svelte";
|
||||||
import ToolConvertion from "./ToolConvertion.svelte";
|
import ToolConvertion from "./ToolConvertion.svelte";
|
||||||
|
import { joinMultiuserRoom } from "src/ts/sync/multiuser";
|
||||||
|
|
||||||
let easterEggTouch = 0
|
let easterEggTouch = 0
|
||||||
|
|
||||||
@@ -89,6 +90,11 @@
|
|||||||
}}>
|
}}>
|
||||||
<h1 class="text-2xl font-bold text-start">{language.promptConvertion}</h1>
|
<h1 class="text-2xl font-bold text-start">{language.promptConvertion}</h1>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="bg-darkbg rounded-md p-6 flex flex-col transition-shadow hover:ring-1" on:click={() => {
|
||||||
|
joinMultiuserRoom()
|
||||||
|
}}>
|
||||||
|
<h1 class="text-2xl font-bold text-start">{language.joinMultiUserRoom}</h1>
|
||||||
|
</button>
|
||||||
<button class="bg-darkbg rounded-md p-6 flex flex-col transition-shadow hover:ring-1" on:click={() => {
|
<button class="bg-darkbg rounded-md p-6 flex flex-col transition-shadow hover:ring-1" on:click={() => {
|
||||||
easterEggTouch += 1
|
easterEggTouch += 1
|
||||||
}}>
|
}}>
|
||||||
|
|||||||
@@ -127,6 +127,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case 2:{
|
||||||
|
chara.chatPage = i
|
||||||
|
createMultiuserRoom()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<MenuIcon size={18}/>
|
<MenuIcon size={18}/>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
import Button from "../UI/GUI/Button.svelte";
|
import Button from "../UI/GUI/Button.svelte";
|
||||||
import { alertAddCharacter, alertInput, alertSelect } from "src/ts/alert";
|
import { alertAddCharacter, alertInput, alertSelect } from "src/ts/alert";
|
||||||
import SideChatList from "./SideChatList.svelte";
|
import SideChatList from "./SideChatList.svelte";
|
||||||
import { joinMultiuserRoom } from "src/ts/sync/multiuser";
|
import { ConnectionIsHost, ConnectionOpenStore, joinMultiuserRoom, RoomIdStore } from "src/ts/sync/multiuser";
|
||||||
import { sideBarSize } from "src/ts/gui/guisize";
|
import { sideBarSize } from "src/ts/gui/guisize";
|
||||||
import DevTool from "./DevTool.svelte";
|
import DevTool from "./DevTool.svelte";
|
||||||
let sideBarMode = 0;
|
let sideBarMode = 0;
|
||||||
@@ -659,6 +659,22 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else if $CurrentCharacter?.chaId === '§playground'}
|
{:else if $CurrentCharacter?.chaId === '§playground'}
|
||||||
<SideChatList bind:chara={ $CurrentCharacter} />
|
<SideChatList bind:chara={ $CurrentCharacter} />
|
||||||
|
{:else if $ConnectionOpenStore}
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<h1 class="text-xl">{language.connectionOpen}</h1>
|
||||||
|
<span class="text-textcolor2 mb-4">{language.connectionOpenInfo}</span>
|
||||||
|
<div class="flex">
|
||||||
|
<span>ID: </span>
|
||||||
|
<span class="text-blue-600">{$RoomIdStore}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{#if $ConnectionIsHost}
|
||||||
|
<span class="text-emerald-600">{language.connectionHost}</span>
|
||||||
|
{:else}
|
||||||
|
<span class="text-gray-500">{language.connectionGuest}</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="w-full h-8 min-h-8 border-l border-b border-r border-selected relative bottom-6 rounded-b-md flex">
|
<div class="w-full h-8 min-h-8 border-l border-b border-r border-selected relative bottom-6 rounded-b-md flex">
|
||||||
<button on:click={() => {
|
<button on:click={() => {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { additionalInformations } from "./embedding/addinfo";
|
|||||||
import { cipherChat, decipherChat } from "./cipherChat";
|
import { cipherChat, decipherChat } from "./cipherChat";
|
||||||
import { getInlayImage, supportsInlayImage } from "./files/image";
|
import { getInlayImage, supportsInlayImage } from "./files/image";
|
||||||
import { getGenerationModelString } from "./models/modelString";
|
import { getGenerationModelString } from "./models/modelString";
|
||||||
import { sendPeerChar } from "../sync/multiuser";
|
import { connectionOpen, peerRevertChat, peerSafeCheck, peerSync } from "../sync/multiuser";
|
||||||
import { runInlayScreen } from "./inlayScreen";
|
import { runInlayScreen } from "./inlayScreen";
|
||||||
import { runCharacterJS } from "../plugins/embedscript";
|
import { runCharacterJS } from "../plugins/embedscript";
|
||||||
import { addRerolls } from "./prereroll";
|
import { addRerolls } from "./prereroll";
|
||||||
@@ -108,6 +108,19 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
|||||||
}
|
}
|
||||||
doingChat.set(true)
|
doingChat.set(true)
|
||||||
|
|
||||||
|
if(connectionOpen){
|
||||||
|
chatProcessStage.set(4)
|
||||||
|
const peerSafe = await peerSafeCheck()
|
||||||
|
if(!peerSafe){
|
||||||
|
peerRevertChat()
|
||||||
|
doingChat.set(false)
|
||||||
|
alertError(language.otherUserRequesting)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
await peerSync()
|
||||||
|
chatProcessStage.set(0)
|
||||||
|
}
|
||||||
|
|
||||||
let db = get(DataBase)
|
let db = get(DataBase)
|
||||||
let selectedChar = get(selectedCharID)
|
let selectedChar = get(selectedCharID)
|
||||||
const nowChatroom = db.characters[selectedChar]
|
const nowChatroom = db.characters[selectedChar]
|
||||||
@@ -1307,7 +1320,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
|||||||
|
|
||||||
chatProcessStage.set(4)
|
chatProcessStage.set(4)
|
||||||
|
|
||||||
sendPeerChar()
|
peerSync()
|
||||||
|
|
||||||
if(req.special){
|
if(req.special){
|
||||||
if(req.special.emotion){
|
if(req.special.emotion){
|
||||||
|
|||||||
@@ -1062,6 +1062,8 @@ export interface Message{
|
|||||||
chatId?:string
|
chatId?:string
|
||||||
time?: number
|
time?: number
|
||||||
generationInfo?: MessageGenerationInfo
|
generationInfo?: MessageGenerationInfo
|
||||||
|
name?:string
|
||||||
|
otherUser?:boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageGenerationInfo{
|
export interface MessageGenerationInfo{
|
||||||
|
|||||||
@@ -1,23 +1,65 @@
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import { alertError, alertInput, alertNormal, alertWait } from '../alert';
|
import { alertError, alertInput, alertNormal, alertStore, alertWait } from '../alert';
|
||||||
import { get } from 'svelte/store';
|
import { get, writable } from 'svelte/store';
|
||||||
import { DataBase, setDatabase, type character, saveImage } from '../storage/database';
|
import { DataBase, setDatabase, type character, saveImage, type Chat } from '../storage/database';
|
||||||
import { selectedCharID } from '../stores';
|
import { CurrentChat, selectedCharID } from '../stores';
|
||||||
import { findCharacterIndexbyId, sleep } from '../util';
|
import { findCharacterIndexbyId, sleep } from '../util';
|
||||||
import type { DataConnection, Peer } from 'peerjs';
|
import type { DataConnection, Peer } from 'peerjs';
|
||||||
import { readImage } from '../storage/globalApi';
|
import { readImage } from '../storage/globalApi';
|
||||||
|
import { doingChat } from '../process';
|
||||||
|
|
||||||
async function importPeerJS(){
|
async function importPeerJS(){
|
||||||
return await import('peerjs');
|
return await import('peerjs');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ReciveFirst{
|
||||||
|
type: 'receive-char',
|
||||||
|
data: character
|
||||||
|
}
|
||||||
|
interface RequestFirst{
|
||||||
|
type: 'request-char'
|
||||||
|
}
|
||||||
|
interface ReciveAsset{
|
||||||
|
type: 'receive-asset',
|
||||||
|
id: string,
|
||||||
|
data: Uint8Array
|
||||||
|
}
|
||||||
|
interface RequestSync{
|
||||||
|
type: 'request-chat-sync',
|
||||||
|
id: string,
|
||||||
|
data: Chat
|
||||||
|
}
|
||||||
|
interface ReciveSync{
|
||||||
|
type: 'receive-chat',
|
||||||
|
data: Chat
|
||||||
|
}
|
||||||
|
interface RequestChatSafe{
|
||||||
|
type: 'request-chat-safe',
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
interface ResponseChatSafe{
|
||||||
|
type: 'response-chat-safe'
|
||||||
|
data: boolean,
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
interface RequestChat{
|
||||||
|
type: 'request-chat'
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReciveData = ReciveFirst|RequestFirst|ReciveAsset|RequestSync|ReciveSync|RequestChatSafe|ResponseChatSafe|RequestChat
|
||||||
|
|
||||||
let conn:DataConnection
|
let conn:DataConnection
|
||||||
let peer:Peer
|
let peer:Peer
|
||||||
let connections:DataConnection[] = []
|
let connections:DataConnection[] = []
|
||||||
let connectionOpen = false
|
export let connectionOpen = false
|
||||||
|
let requestChatSafeQueue = new Map<string, {remaining:number,safe:boolean,conn?:DataConnection}>()
|
||||||
|
export let ConnectionOpenStore = writable(false)
|
||||||
|
export let ConnectionIsHost = writable(false)
|
||||||
|
export let RoomIdStore = writable('')
|
||||||
|
|
||||||
export async function createMultiuserRoom(){
|
export async function createMultiuserRoom(){
|
||||||
//create a room with webrtc
|
//create a room with webrtc
|
||||||
|
ConnectionIsHost.set(true)
|
||||||
alertWait("Loading...")
|
alertWait("Loading...")
|
||||||
|
|
||||||
const peerJS = await importPeerJS();
|
const peerJS = await importPeerJS();
|
||||||
@@ -93,7 +135,96 @@ export async function createMultiuserRoom(){
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
char.chats[char.chatPage] = recivedChar.chats[0]
|
char.chats[char.chatPage] = recivedChar.chats[0]
|
||||||
sendPeerChar()
|
}
|
||||||
|
if(data.type === 'request-chat-sync'){
|
||||||
|
const db = get(DataBase)
|
||||||
|
const selectedCharId = get(selectedCharID)
|
||||||
|
const char = db.characters[selectedCharId]
|
||||||
|
char.chats[char.chatPage] = data.data
|
||||||
|
db.characters[selectedCharId] = char
|
||||||
|
latestSyncChat = data.data
|
||||||
|
setDatabase(db)
|
||||||
|
|
||||||
|
for(const connection of connections){
|
||||||
|
if(connection.connectionId === conn.connectionId){
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const rs:ReciveSync = {
|
||||||
|
type: 'receive-chat',
|
||||||
|
data: data.data
|
||||||
|
}
|
||||||
|
connection.send(rs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(data.type === 'request-chat'){
|
||||||
|
const db = get(DataBase)
|
||||||
|
const selectedCharId = get(selectedCharID)
|
||||||
|
const char = db.characters[selectedCharId]
|
||||||
|
const chat = char.chats[char.chatPage]
|
||||||
|
const rs:ReciveSync = {
|
||||||
|
type: 'receive-chat',
|
||||||
|
data: chat
|
||||||
|
}
|
||||||
|
conn.send(rs)
|
||||||
|
}
|
||||||
|
if(data.type === 'request-chat-safe'){
|
||||||
|
const queue = {
|
||||||
|
remaining: connections.length,
|
||||||
|
safe: true,
|
||||||
|
conn: conn
|
||||||
|
}
|
||||||
|
requestChatSafeQueue.set(data.id, queue)
|
||||||
|
for(const connection of connections){
|
||||||
|
if(connection.connectionId === conn.connectionId){
|
||||||
|
queue.remaining--
|
||||||
|
requestChatSafeQueue.set(data.id, queue)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const rs:RequestChatSafe = {
|
||||||
|
type: 'request-chat-safe',
|
||||||
|
id: data.id
|
||||||
|
}
|
||||||
|
connection.send(rs)
|
||||||
|
}
|
||||||
|
if(queue.remaining === 0){
|
||||||
|
if(waitingMultiuserId === data.id){
|
||||||
|
waitingMultiuserId = ''
|
||||||
|
waitingMultiuserSafe = queue.safe
|
||||||
|
}
|
||||||
|
else if(queue.conn){
|
||||||
|
const rs:ResponseChatSafe = {
|
||||||
|
type: 'response-chat-safe',
|
||||||
|
data: queue.safe,
|
||||||
|
id: data.id
|
||||||
|
}
|
||||||
|
queue.conn.send(rs)
|
||||||
|
requestChatSafeQueue.delete(data.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(data.type === 'response-chat-safe'){
|
||||||
|
const queue = requestChatSafeQueue.get(data.id)
|
||||||
|
if(queue){
|
||||||
|
queue.remaining--
|
||||||
|
if(!data.data){
|
||||||
|
queue.safe = false
|
||||||
|
}
|
||||||
|
if(queue.remaining === 0){
|
||||||
|
if(waitingMultiuserId === data.id){
|
||||||
|
waitingMultiuserId = ''
|
||||||
|
waitingMultiuserSafe = queue.safe
|
||||||
|
}
|
||||||
|
else if(queue.conn){
|
||||||
|
const rs:ResponseChatSafe = {
|
||||||
|
type: 'response-chat-safe',
|
||||||
|
data: queue.safe,
|
||||||
|
id: data.id
|
||||||
|
}
|
||||||
|
queue.conn.send(rs)
|
||||||
|
requestChatSafeQueue.delete(data.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -111,28 +242,23 @@ export async function createMultiuserRoom(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
connectionOpen = true
|
connectionOpen = true
|
||||||
alertNormal("Room ID: " + roomId)
|
ConnectionOpenStore.set(true)
|
||||||
|
RoomIdStore.set(roomId)
|
||||||
|
alertStore.set({
|
||||||
|
type: 'none',
|
||||||
|
msg: ''
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReciveFirst{
|
let waitingMultiuserId = ''
|
||||||
type: 'receive-char',
|
let waitingMultiuserSafe = false
|
||||||
data: character
|
let latestSyncChat:Chat|null = null
|
||||||
}
|
|
||||||
interface RequestFirst{
|
|
||||||
type: 'request-char'
|
|
||||||
}
|
|
||||||
interface ReciveAsset{
|
|
||||||
type: 'receive-asset',
|
|
||||||
id: string,
|
|
||||||
data: Uint8Array
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReciveData = ReciveFirst|RequestFirst|ReciveAsset
|
|
||||||
|
|
||||||
export async function joinMultiuserRoom(){
|
export async function joinMultiuserRoom(){
|
||||||
|
|
||||||
//join a room with webrtc
|
//join a room with webrtc
|
||||||
|
ConnectionIsHost.set(false)
|
||||||
alertWait("Loading...")
|
alertWait("Loading...")
|
||||||
const peerJS = await importPeerJS();
|
const peerJS = await importPeerJS();
|
||||||
peer = new peerJS.Peer(
|
peer = new peerJS.Peer(
|
||||||
@@ -145,6 +271,7 @@ export async function joinMultiuserRoom(){
|
|||||||
|
|
||||||
let open = false
|
let open = false
|
||||||
conn = peer.connect(roomId);
|
conn = peer.connect(roomId);
|
||||||
|
RoomIdStore.set(roomId)
|
||||||
|
|
||||||
conn.on('open', function() {
|
conn.on('open', function() {
|
||||||
alertWait("Waiting for host to accept connection")
|
alertWait("Waiting for host to accept connection")
|
||||||
@@ -179,6 +306,32 @@ export async function joinMultiuserRoom(){
|
|||||||
}
|
}
|
||||||
case 'receive-asset':{
|
case 'receive-asset':{
|
||||||
saveImage(data.data, data.id)
|
saveImage(data.data, data.id)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'receive-chat':{
|
||||||
|
const db = get(DataBase)
|
||||||
|
const selectedCharId = get(selectedCharID)
|
||||||
|
const char = structuredClone(db.characters[selectedCharId])
|
||||||
|
char.chats[char.chatPage] = data.data
|
||||||
|
db.characters[selectedCharId] = char
|
||||||
|
latestSyncChat = data.data
|
||||||
|
setDatabase(db)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'request-chat-safe':{
|
||||||
|
const rs:ResponseChatSafe = {
|
||||||
|
type: 'response-chat-safe',
|
||||||
|
data: !get(doingChat) || data.id === waitingMultiuserId,
|
||||||
|
id: data.id
|
||||||
|
}
|
||||||
|
conn.send(rs)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'response-chat-safe':{
|
||||||
|
if(data.id === waitingMultiuserId){
|
||||||
|
waitingMultiuserId = ''
|
||||||
|
waitingMultiuserSafe = data.data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -186,6 +339,7 @@ export async function joinMultiuserRoom(){
|
|||||||
conn.on('close', function() {
|
conn.on('close', function() {
|
||||||
alertError("Connection closed")
|
alertError("Connection closed")
|
||||||
connectionOpen = false
|
connectionOpen = false
|
||||||
|
ConnectionOpenStore.set(false)
|
||||||
selectedCharID.set(-1)
|
selectedCharID.set(-1)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -199,29 +353,78 @@ export async function joinMultiuserRoom(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
connectionOpen = true
|
connectionOpen = true
|
||||||
|
ConnectionOpenStore.set(true)
|
||||||
alertNormal("Connected")
|
alertNormal("Connected")
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function sendPeerChar(){
|
export async function peerSync(){
|
||||||
if(!connectionOpen){
|
if(!connectionOpen){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
await sleep(1)
|
||||||
|
const chat = get(CurrentChat)
|
||||||
|
latestSyncChat = chat
|
||||||
if(!conn){
|
if(!conn){
|
||||||
// host user
|
// host user
|
||||||
for(const connection of connections){
|
for(const connection of connections){
|
||||||
connection.send({
|
connection.send({
|
||||||
type: 'receive-char',
|
type: 'receive-chat',
|
||||||
data: get(DataBase).characters[get(selectedCharID)]
|
data: chat
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
conn.send({
|
conn.send({
|
||||||
type: 'receive-char',
|
type: 'request-chat-sync',
|
||||||
data: get(DataBase).characters[get(selectedCharID)]
|
data: chat
|
||||||
});
|
} as RequestSync)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function peerSafeCheck() {
|
||||||
|
if(!connectionOpen){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
await sleep(500)
|
||||||
|
if(!conn){
|
||||||
|
waitingMultiuserId = v4()
|
||||||
|
requestChatSafeQueue.set(waitingMultiuserId, {
|
||||||
|
remaining: connections.length,
|
||||||
|
safe: true,
|
||||||
|
})
|
||||||
|
for(const connection of connections){
|
||||||
|
const rs:RequestChatSafe = {
|
||||||
|
type: 'request-chat-safe',
|
||||||
|
id: waitingMultiuserId
|
||||||
|
}
|
||||||
|
connection.send(rs)
|
||||||
|
}
|
||||||
|
while(waitingMultiuserId !== ''){
|
||||||
|
await sleep(100)
|
||||||
|
}
|
||||||
|
return waitingMultiuserSafe
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
waitingMultiuserId = v4()
|
||||||
|
const rs:RequestChatSafe = {
|
||||||
|
type: 'request-chat-safe',
|
||||||
|
id: waitingMultiuserId
|
||||||
|
}
|
||||||
|
conn.send(rs)
|
||||||
|
while(waitingMultiuserId !== ''){
|
||||||
|
await sleep(100)
|
||||||
|
}
|
||||||
|
return waitingMultiuserSafe
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function peerRevertChat() {
|
||||||
|
if(!connectionOpen || !latestSyncChat){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
CurrentChat.set(latestSyncChat)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user