Mas cosas
This commit is contained in:
parent
e2cf465862
commit
569e165690
7
client/package-lock.json
generated
7
client/package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"@kangc/v-md-editor": "^2.3.17",
|
"@kangc/v-md-editor": "^2.3.17",
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.5.1",
|
||||||
"babel-plugin-prismjs": "^2.1.0",
|
"babel-plugin-prismjs": "^2.1.0",
|
||||||
|
"dice-notation-js": "^1.0.3",
|
||||||
"ef-infinite-canvas": "^0.6.6",
|
"ef-infinite-canvas": "^0.6.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"jquery": "^3.7.1",
|
"jquery": "^3.7.1",
|
||||||
@ -5102,6 +5103,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/dice-notation-js": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dice-notation-js/-/dice-notation-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-K02a/w3kjRp4QPYE3+qlXnQRVw9n00IIJHYtrxAryIIC112SP36YKo2Z9CR/f+ZKzj+YKJmCeTKnMIc4+crG5g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/dir-glob": {
|
"node_modules/dir-glob": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"@kangc/v-md-editor": "^2.3.17",
|
"@kangc/v-md-editor": "^2.3.17",
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.5.1",
|
||||||
"babel-plugin-prismjs": "^2.1.0",
|
"babel-plugin-prismjs": "^2.1.0",
|
||||||
|
"dice-notation-js": "^1.0.3",
|
||||||
"ef-infinite-canvas": "^0.6.6",
|
"ef-infinite-canvas": "^0.6.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"jquery": "^3.7.1",
|
"jquery": "^3.7.1",
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||||
|
<title>perspective-dice-six-svg</title>
|
||||||
|
<style>
|
||||||
|
.s0 { fill: #000000 }
|
||||||
|
</style>
|
||||||
|
<path id="Layer" fill-rule="evenodd" class="s0" d="m272.8 46.9l152.8 88.4c9.6 5.5 9.6 14.3 0 19.8l-152.8 88.4c-9.5 5.5-24.7 5.5-34.2 0l-152.8-88.4c-9.6-5.5-9.6-14.3 0-19.8l152.8-88.4c4.7-2.8 10.9-4.1 17.1-4.1 6.2 0 12.4 1.3 17.1 4.1zm-44.8 58.3q-4.8 1.9-9.1 4.5-13.4 8-10.3 19.4 3 11.2 21.7 22.9 18.3 11.5 34.9 13.8 16.5 2.2 28.5-5 10.9-6.5 10-14.9-0.8-8.5-13-16.1-11-6.9-23.6-7.6-12.5-0.8-22 4.8-3.7 2.3-5.7 5-1.9 2.7-2.1 5.8-8.9-6.3-9.8-11.7-0.9-5.4 6.2-9.7 3.3-1.9 7.9-3.3 4.5-1.4 10.7-2.4l-14-8.7q-5.5 1.3-10.3 3.2zm34.2 29.1q0.4 0 0.7 0 0.3 0.1 0.6 0.1 0.4 0.1 0.7 0.1 5.4 0.8 12 4.9 6.7 4.2 7.9 7.5 1.2 3.3-3 5.9-4.1 2.5-9.5 1.7-5.4-0.9-12.1-5-6.6-4.2-7.8-7.5-1.3-3.3 2.9-5.8 3.1-1.9 7-1.9 0.3 0 0.6 0zm183.9 49.8v157.7c0 11.1-7.6 24.2-17.2 29.7l-146.9 84.9c-9.6 5.5-17.2 1.1-17.2-9.9v-157.7c0-11.1 7.6-24.2 17.2-29.7l146.9-84.9c2.7-1.5 5-2.3 7-2.4 4.9-0.2 7.7 4.3 10.2 12.3zm-363-9.9l146.9 84.9c9.6 5.5 17.2 18.6 17.2 29.7v157.7c0 11-7.6 15.4-17.2 9.9l-146.9-84.9c-9.6-5.5-17.2-18.6-17.2-29.7v-157.7c0.2-6.5 4-11.8 10.2-11.8 2.1 0 4.4 0.6 7 1.9zm45.4 136.4q4.6 0.4 8.5 1.6 1 0.3 2 0.7 0.9 0.3 1.9 0.8 0.9 0.4 1.8 0.9 0.9 0.4 1.8 1 5.9 3.5 9.3 9.1 3.5 5.7 3.5 12 0 6.2-3.5 7.8-3.4 1.6-9.3-2-4.1-2.4-8.7-7.1-4.6-4.6-9.8-11.4v16.1q5.2 5.7 10.4 10.2 5.3 4.5 10.7 7.7 12.4 7.5 19.4 4.4 7-3.1 7-15.9 0-13-6.4-24.1-6.4-11.1-18-18-2-1.3-3.9-2-0.4-0.2-0.9-0.4-0.5-0.2-0.9-0.3-0.5-0.2-1-0.3-0.4-0.2-0.9-0.3v-12.3l27.5 16.5v-15l-40.5-24.3zm236.2-32.8l-22.7 61.4v17.7l25.2-15.1v14.6l13.8-8.3v-14.6l8.1-4.8v-15l-8.1 4.8v-50.5zm2.5 49.1l-16.1 9.6 16.1-43.2z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
BIN
client/public/img/d20.png
Normal file
BIN
client/public/img/d20.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
client/public/img/dd-dice-512.webp
Normal file
BIN
client/public/img/dd-dice-512.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@ -22,7 +22,7 @@
|
|||||||
--c-black-muter: #585858;
|
--c-black-muter: #585858;
|
||||||
|
|
||||||
|
|
||||||
--c-black-blurred: #222222cc;
|
--c-black-blurred: #222222;
|
||||||
|
|
||||||
--c-indigo: #2c3e50;
|
--c-indigo: #2c3e50;
|
||||||
|
|
||||||
@ -96,6 +96,9 @@
|
|||||||
--chat-background: var(--c-blacker);
|
--chat-background: var(--c-blacker);
|
||||||
--text-disabled: #7e7e7e;
|
--text-disabled: #7e7e7e;
|
||||||
|
|
||||||
|
--color-chat-other: #1d1d1d;
|
||||||
|
--color-roll-dice-chat: #665750;
|
||||||
|
|
||||||
--color-hover: var()
|
--color-hover: var()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,13 @@ a {
|
|||||||
background-color: var(--c-button-green-hover);
|
background-color: var(--c-button-green-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-red {
|
||||||
|
background-color: var(--c-button-red);
|
||||||
|
}
|
||||||
|
.btn-red:hover {
|
||||||
|
background-color: var(--c-button-red-hover);
|
||||||
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
@ -4,6 +4,7 @@ import { io } from "socket.io-client";
|
|||||||
import Api from '@/services/Api'
|
import Api from '@/services/Api'
|
||||||
import { backendUrl } from './BackendURL';
|
import { backendUrl } from './BackendURL';
|
||||||
import { GetUser } from './User';
|
import { GetUser } from './User';
|
||||||
|
import { ExitGame } from './Game';
|
||||||
|
|
||||||
let emitter;
|
let emitter;
|
||||||
|
|
||||||
@ -25,7 +26,24 @@ let GetPlayerList = () => { return players; };
|
|||||||
let GetCampaign = () => { return currentCampaign; };
|
let GetCampaign = () => { return currentCampaign; };
|
||||||
let GetClient = () => { return currentPlayer; };
|
let GetClient = () => { return currentPlayer; };
|
||||||
|
|
||||||
|
let chatMessageId = 0;
|
||||||
|
const chat = ref([
|
||||||
|
/* {
|
||||||
|
id: 1,
|
||||||
|
author: "66ae8aea3e78bb669e25010d",
|
||||||
|
chunks: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
type: "text",
|
||||||
|
content: "Hola test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} */
|
||||||
|
]);
|
||||||
|
let GetChatRef = () => chat;
|
||||||
|
|
||||||
socket.on('update-players', data => {
|
socket.on('update-players', data => {
|
||||||
|
console.log(data);
|
||||||
players.value = [];
|
players.value = [];
|
||||||
Object.keys(data).forEach((key) => {
|
Object.keys(data).forEach((key) => {
|
||||||
players.value.push(data[key]);
|
players.value.push(data[key]);
|
||||||
@ -33,22 +51,60 @@ socket.on('update-players', data => {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
function DisplayCampaign(data){
|
socket.on('message', (data) => {
|
||||||
|
// Add new chat message, ?
|
||||||
|
if(chat.value.length > 0) if(chat.value[chat.value.length - 1].author == data.author){
|
||||||
|
chat.value[chat.value.length - 1].chunkSize += 1;
|
||||||
|
chat.value[chat.value.length - 1].chunks.push({
|
||||||
|
id: chat.value[chat.value.length - 1].chunkSize,
|
||||||
|
type: data.type ? data.type : 'text',
|
||||||
|
content: data.content
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chatMessageId += 1;
|
||||||
|
chat.value.push({
|
||||||
|
id: chatMessageId,
|
||||||
|
author: data.author,
|
||||||
|
chunkSize: 1,
|
||||||
|
chunks: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
type: data.type ? data.type : 'text',
|
||||||
|
content: data.content
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function SendMessage(data){
|
||||||
|
socket.emit('message', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DisplayCampaign(data = currentCampaign){
|
||||||
ClearAll();
|
ClearAll();
|
||||||
CreateWindow('campaign_preview', {campaign: data});
|
CreateWindow('campaign_preview', {campaign: data});
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConnectToCampaign(campaign){
|
function ConnectToCampaign(campaign){
|
||||||
currentCampaign = campaign;
|
currentCampaign = campaign;
|
||||||
|
chat.value = [];
|
||||||
|
|
||||||
socket.emit('enter', GetUser(), currentCampaign._id);
|
socket.emit('enter', GetUser(), currentCampaign._id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Disconnect(){
|
function Disconnect(){
|
||||||
socket.emit('exit');
|
socket.emit('exit');
|
||||||
|
ExitGame();
|
||||||
|
|
||||||
currentCampaign = null;
|
currentCampaign = null;
|
||||||
|
currentPlayer = null;
|
||||||
|
chat.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function GetPlayer(player_campaign){
|
function GetPlayer(player_campaign){
|
||||||
|
console.log(players.value);
|
||||||
let index = players.value.findIndex((p) => {return p._id == player_campaign});
|
let index = players.value.findIndex((p) => {return p._id == player_campaign});
|
||||||
if(index != -1) return players.value[index];
|
if(index != -1) return players.value[index];
|
||||||
}
|
}
|
||||||
@ -66,4 +122,7 @@ export {
|
|||||||
GetClient,
|
GetClient,
|
||||||
GetPlayerList,
|
GetPlayerList,
|
||||||
GetPlayer,
|
GetPlayer,
|
||||||
|
|
||||||
|
GetChatRef,
|
||||||
|
SendMessage
|
||||||
};
|
};
|
@ -12,7 +12,9 @@ const windows = {
|
|||||||
campaign_list: ref([]),
|
campaign_list: ref([]),
|
||||||
new_campaign: ref([]),
|
new_campaign: ref([]),
|
||||||
join_campaign: ref([]),
|
join_campaign: ref([]),
|
||||||
campaign_preview: ref([])
|
campaign_preview: ref([]),
|
||||||
|
chat: ref([]),
|
||||||
|
dice_menu: ref([]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const defValues = {
|
const defValues = {
|
||||||
@ -66,6 +68,16 @@ const defValues = {
|
|||||||
ClearWindow('campaign_preview');
|
ClearWindow('campaign_preview');
|
||||||
CreateWindow('campaign_list');
|
CreateWindow('campaign_list');
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'chat': {
|
||||||
|
id: 'chat',
|
||||||
|
title: 'Chat',
|
||||||
|
close: true
|
||||||
|
},
|
||||||
|
'dice_menu': {
|
||||||
|
id: 'dice_menu',
|
||||||
|
title: 'Dice roll',
|
||||||
|
close: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,26 @@ import { InGameRef } from '../../services/Game';
|
|||||||
import IconButton from '../partials/game/IconButton.vue';
|
import IconButton from '../partials/game/IconButton.vue';
|
||||||
import { AddSound } from '../../services/Sound';
|
import { AddSound } from '../../services/Sound';
|
||||||
import TileMap from './TileMap.vue';
|
import TileMap from './TileMap.vue';
|
||||||
|
import { DisplayCampaign, GetCampaign } from '../../services/Dragonroll';
|
||||||
|
import { ClearAll, CreateWindow } from '../../services/Windows';
|
||||||
|
|
||||||
const game = ref(null);
|
const game = ref(null);
|
||||||
const in_game = InGameRef();
|
const in_game = InGameRef();
|
||||||
|
|
||||||
|
function OpenCampaignPreview(){
|
||||||
|
CreateWindow('campaign_preview', {campaign: GetCampaign(), style: 'compact', hide_start: true, back: undefined, close: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
function OpenChat(){
|
||||||
|
CreateWindow('chat');
|
||||||
|
}
|
||||||
|
|
||||||
|
function OpenDiceMenu(){
|
||||||
|
CreateWindow('dice_menu');
|
||||||
|
}
|
||||||
|
|
||||||
watch(game, () => {
|
watch(game, () => {
|
||||||
if(game){
|
if(game.value && in_game.value){
|
||||||
AddSound(game.value);
|
AddSound(game.value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -22,12 +36,14 @@ watch(game, () => {
|
|||||||
<!-- Aquests dos son absolute -->
|
<!-- Aquests dos son absolute -->
|
||||||
|
|
||||||
<div class="vertical-button">
|
<div class="vertical-button">
|
||||||
<IconButton icon="icons/iconoir/regular/menu.svg"></IconButton>
|
<IconButton icon="icons/iconoir/regular/menu.svg" :action="OpenCampaignPreview"></IconButton>
|
||||||
<IconButton icon="icons/iconoir/regular/cursor-pointer.svg"></IconButton>
|
<IconButton icon="icons/iconoir/regular/cursor-pointer.svg"></IconButton>
|
||||||
<IconButton icon="icons/game-icons/000000/delapouite/rolling-dice-cup.svg"></IconButton>
|
<IconButton icon="icons/game-icons/000000/delapouite/rolling-dice-cup.svg" :action="OpenDiceMenu"></IconButton>
|
||||||
</div>
|
</div>
|
||||||
<div class="horizontal-button">
|
<div class="horizontal-button">
|
||||||
|
<IconButton icon="icons/iconoir/regular/group.svg"></IconButton>
|
||||||
|
<IconButton icon="icons/iconoir/regular/bookmark-book.svg"></IconButton>
|
||||||
|
<IconButton icon="icons/iconoir/regular/chat-bubble.svg" :action="OpenChat"></IconButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tilemap -->
|
<!-- Tilemap -->
|
||||||
@ -44,5 +60,18 @@ watch(game, () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -115,12 +115,16 @@ onMounted(() => {
|
|||||||
offsetY = oldOffsetY + ((event.clientY - startY) * (1 / scale));
|
offsetY = oldOffsetY + ((event.clientY - startY) * (1 / scale));
|
||||||
|
|
||||||
draw();
|
draw();
|
||||||
console.log("x: " + offsetX + ", y: " + offsetY);
|
// console.log("x: " + offsetX + ", y: " + offsetY);
|
||||||
});
|
});
|
||||||
|
|
||||||
tilemap.addEventListener("mouseup", () => mouseDown = false);
|
tilemap.addEventListener("mouseup", () => mouseDown = false);
|
||||||
|
|
||||||
addEventListener("resize", draw)
|
addEventListener("resize", draw)
|
||||||
|
|
||||||
|
offsetX = window.innerWidth / 2;
|
||||||
|
offsetY = window.innerHeight / 2;
|
||||||
|
|
||||||
draw();
|
draw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ import CampaignListWindow from '../windows/campaigns/CampaignListWindow.vue'
|
|||||||
import NewCampaignWindow from '../windows/campaigns/NewCampaignWindow.vue'
|
import NewCampaignWindow from '../windows/campaigns/NewCampaignWindow.vue'
|
||||||
import JoinCampaignWindow from '../windows/campaigns/JoinCampaignWindow.vue'
|
import JoinCampaignWindow from '../windows/campaigns/JoinCampaignWindow.vue'
|
||||||
import CampaignPreviewWindow from '@/views/windows/campaigns/CampaignPreviewWindow.vue'
|
import CampaignPreviewWindow from '@/views/windows/campaigns/CampaignPreviewWindow.vue'
|
||||||
|
import ChatWindow from '../windows/game/ChatWindow.vue'
|
||||||
|
import DiceWindow from '../windows/game/DiceWindow.vue'
|
||||||
|
|
||||||
// Gestionem ventanas
|
// Gestionem ventanas
|
||||||
const reload = ReloadRef();
|
const reload = ReloadRef();
|
||||||
@ -32,6 +34,8 @@ const campaign_list = windows.campaign_list;
|
|||||||
const new_campaign = windows.new_campaign;
|
const new_campaign = windows.new_campaign;
|
||||||
const join_campaign = windows.join_campaign;
|
const join_campaign = windows.join_campaign;
|
||||||
const campaign_preview = windows.campaign_preview;
|
const campaign_preview = windows.campaign_preview;
|
||||||
|
const chat = windows.chat;
|
||||||
|
const dice_menu = windows.dice_menu;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -48,6 +52,8 @@ const campaign_preview = windows.campaign_preview;
|
|||||||
<NewCampaignWindow v-for="win in new_campaign" :key="win.id" :data="win"></NewCampaignWindow>
|
<NewCampaignWindow v-for="win in new_campaign" :key="win.id" :data="win"></NewCampaignWindow>
|
||||||
<JoinCampaignWindow v-for="win in join_campaign" :key="win.id" :data="win"></JoinCampaignWindow>
|
<JoinCampaignWindow v-for="win in join_campaign" :key="win.id" :data="win"></JoinCampaignWindow>
|
||||||
<CampaignPreviewWindow v-for="win in campaign_preview" :key="win.id" :data="win"></CampaignPreviewWindow>
|
<CampaignPreviewWindow v-for="win in campaign_preview" :key="win.id" :data="win"></CampaignPreviewWindow>
|
||||||
|
<ChatWindow v-for="win in chat" :key="win.id" :data="win"></ChatWindow>
|
||||||
|
<DiceWindow v-for="win in dice_menu" :key="win.id" :data="win"></DiceWindow>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -57,7 +63,7 @@ const campaign_preview = windows.campaign_preview;
|
|||||||
.window-wrapper {
|
.window-wrapper {
|
||||||
background-color: var(--window-background);
|
background-color: var(--window-background);
|
||||||
|
|
||||||
backdrop-filter: blur(10px);
|
/* backdrop-filter: blur(10px); */
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
||||||
|
|
||||||
|
146
client/src/views/partials/ChatComponent.vue
Normal file
146
client/src/views/partials/ChatComponent.vue
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<script setup>
|
||||||
|
import IconButton from '@/views/partials/game/IconButton.vue';
|
||||||
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import MessageComponent from './MessageComponent.vue';
|
||||||
|
import { GetChatRef, GetClient, SendMessage } from '../../services/Dragonroll';
|
||||||
|
|
||||||
|
const textInput = ref(null);
|
||||||
|
const chat = GetChatRef();
|
||||||
|
const messageContainer = ref(null);
|
||||||
|
|
||||||
|
function Send(message){
|
||||||
|
SendMessage({
|
||||||
|
content: {
|
||||||
|
text: message
|
||||||
|
},
|
||||||
|
author: GetClient()._id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
textInput.value.addEventListener('input', (event) => {
|
||||||
|
// textInput.value.style.height = "1px";
|
||||||
|
textInput.value.style.height = (textInput.value.scrollHeight)+"px";
|
||||||
|
})
|
||||||
|
textInput.value.addEventListener("keypress", (event) => {
|
||||||
|
if(event.shiftKey) return;
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
Send(textInput.value.value);
|
||||||
|
textInput.value.value = "";
|
||||||
|
|
||||||
|
|
||||||
|
textInput.value.style.height = "1px";
|
||||||
|
textInput.value.style.height = (textInput.value.scrollHeight)+"px";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(chat, () => {
|
||||||
|
if(chat.value.length > 0) if(chat.value[chat.value.length - 1].author == GetClient()._id){
|
||||||
|
setTimeout(() => {
|
||||||
|
messageContainer.value.scrollTop = messageContainer.value.scrollHeight;
|
||||||
|
console.log(messageContainer.value.scrollHeight)
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}, {deep: true})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
<div class="chat-container">
|
||||||
|
<div class="message-container" ref="messageContainer">
|
||||||
|
<MessageComponent v-for="message in chat" :key="message._id" :message="message"></MessageComponent>
|
||||||
|
</div>
|
||||||
|
<div class="chat-input-container">
|
||||||
|
<textarea ref="textInput" class="chat-input"></textarea>
|
||||||
|
<div class="chat-input-actions">
|
||||||
|
<div class="chat-input-actions-left">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="chat-input-actions-right">
|
||||||
|
<IconButton icon="icons/iconoir/regular/send.svg"></IconButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
display: flex;
|
||||||
|
height: 720px;
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family: MrEavesRemake;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-container {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 580px;
|
||||||
|
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input-container {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input {
|
||||||
|
background-color: var(--color-background-softer);
|
||||||
|
border: none;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--color-text);
|
||||||
|
transition: 300ms background-color;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
min-height: 30px;
|
||||||
|
height: 41px;
|
||||||
|
max-height: 100px;
|
||||||
|
resize: none;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
background-color: var(--color-background-softest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-input-actions-left {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.chat-input-actions-right {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
61
client/src/views/partials/MessageChunk.vue
Normal file
61
client/src/views/partials/MessageChunk.vue
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
const text = ref("");
|
||||||
|
const roll = ref("");
|
||||||
|
|
||||||
|
const props = defineProps(['data']);
|
||||||
|
const data = props.data;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if(data.type == "dice-roll"){
|
||||||
|
text.value = data.content.throw;
|
||||||
|
roll.value = data.content.roll;
|
||||||
|
} else {
|
||||||
|
text.value = data.content.text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="msg-chunk">
|
||||||
|
<span v-if="data.type == 'text'">{{ text }}</span>
|
||||||
|
<div v-if="data.type == 'dice-roll'" class="dice-roll-container">
|
||||||
|
<span class="roll-title">Rolled {{ text }}</span>
|
||||||
|
<span class="roll-result">{{ roll }}</span>
|
||||||
|
<img class="roll-bg" src="/img/d20.png">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.dice-roll-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
width: 300px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-result {
|
||||||
|
font-size: 48px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: MrEavesRemake;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: -75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-bg {
|
||||||
|
filter: invert(0.9);
|
||||||
|
opacity: 0.1;
|
||||||
|
width: 75px;
|
||||||
|
position: relative;
|
||||||
|
left: 112px;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
</style>
|
65
client/src/views/partials/MessageComponent.vue
Normal file
65
client/src/views/partials/MessageComponent.vue
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<script setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
import MessageChunk from './MessageChunk.vue';
|
||||||
|
import { GetPlayer } from '../../services/Dragonroll';
|
||||||
|
import { backendUrl } from '../../services/BackendURL';
|
||||||
|
|
||||||
|
const props = defineProps(['message']);
|
||||||
|
const message = props.message;
|
||||||
|
|
||||||
|
const avatar = ref(null);
|
||||||
|
const title = ref("");
|
||||||
|
const chunks = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
let sender = GetPlayer(message.author);
|
||||||
|
if(sender.user.image) avatar.value.src = backendUrl + "public/" + sender.user.image;
|
||||||
|
title.value = sender.user.username;
|
||||||
|
chunks.value = message.chunks;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="msg-parent-container rcv">
|
||||||
|
<img class="user-icon" src="img/def-avatar.jpg" ref="avatar" draggable="false">
|
||||||
|
<div class="content-container">
|
||||||
|
<div class="msg-title">
|
||||||
|
{{ title }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<MessageChunk v-for="chunk in chunks" :id="chunk.id" :data="chunk"></MessageChunk>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.msg-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-parent-container {
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--color-chat-other);
|
||||||
|
display: flex;
|
||||||
|
margin-top: 2px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-container {
|
||||||
|
max-width: 75%;
|
||||||
|
padding: 7px 15px;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-icon {
|
||||||
|
margin-top: 9px;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -1,13 +1,16 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const props = defineProps(['icon']);
|
const props = defineProps(['icon', 'action','size']);
|
||||||
let icon = props.icon;
|
let icon = props.icon;
|
||||||
|
let action = props.action;
|
||||||
|
|
||||||
|
let size = props.size;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="icon-button sound-click">
|
<div class="icon-button sound-click" :class="size" v-on:click.prevent="action">
|
||||||
<img class="icon" :src="icon">
|
<img class="icon" draggable="false" :src="icon" :class="size">
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -16,6 +19,12 @@ let icon = props.icon;
|
|||||||
.icon-button {
|
.icon-button {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
|
|
||||||
|
&.big {
|
||||||
|
height: 42px;
|
||||||
|
width: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-background-soft);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -34,4 +43,9 @@ let icon = props.icon;
|
|||||||
height: 24px;
|
height: 24px;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.big {
|
||||||
|
height: 38px;
|
||||||
|
width: 38px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -4,23 +4,39 @@ import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Win
|
|||||||
|
|
||||||
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||||
import PlayerList from '../../partials/PlayerList.vue';
|
import PlayerList from '../../partials/PlayerList.vue';
|
||||||
import { DisplayToast, GetCampaign, GetClient } from '../../../services/Dragonroll';
|
import { Disconnect, DisplayToast, GetCampaign, GetClient } from '../../../services/Dragonroll';
|
||||||
import CampaignBookList from '../../partials/books/CampaignBookList.vue';
|
import CampaignBookList from '../../partials/books/CampaignBookList.vue';
|
||||||
import { ClearWindow } from '../../../services/Windows';
|
import { ClearAll, ClearWindow, CreateWindow } from '../../../services/Windows';
|
||||||
import { LaunchGame } from '../../../services/Game';
|
import { LaunchGame } from '../../../services/Game';
|
||||||
|
import { AddSound } from '../../../services/Sound';
|
||||||
|
import ChatComponent from '../../partials/ChatComponent.vue';
|
||||||
|
|
||||||
const handle = ref(null);
|
const handle = ref(null);
|
||||||
|
|
||||||
const props = defineProps(['data']);
|
const props = defineProps(['data']);
|
||||||
const data = props.data;
|
const data = props.data;
|
||||||
|
|
||||||
|
const hide_start = ref(false);
|
||||||
|
const hide_chat = ref(false);
|
||||||
|
|
||||||
|
const container = ref(null);
|
||||||
|
|
||||||
let id = data.id;
|
let id = data.id;
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
SetupHandle(id, handle);
|
SetupHandle(id, handle);
|
||||||
|
|
||||||
|
if(data.style == 'compact') {
|
||||||
|
SetSize(id, {x: 800, y: 750});
|
||||||
|
hide_chat.value = true;
|
||||||
|
} else {
|
||||||
SetSize(id, {x: 1200, y: 750});
|
SetSize(id, {x: 1200, y: 750});
|
||||||
|
}
|
||||||
|
|
||||||
ResetPosition(id, "center");
|
ResetPosition(id, "center");
|
||||||
|
|
||||||
console.log(data);
|
hide_start.value = data.hide_start;
|
||||||
|
|
||||||
|
AddSound(container.value)
|
||||||
});
|
});
|
||||||
|
|
||||||
function CopyCode(){
|
function CopyCode(){
|
||||||
@ -33,6 +49,12 @@ function Launch(){
|
|||||||
LaunchGame();
|
LaunchGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Exit(){
|
||||||
|
Disconnect();
|
||||||
|
ClearAll();
|
||||||
|
CreateWindow('campaign_list');
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@ -43,7 +65,7 @@ function Launch(){
|
|||||||
<!-- Body
|
<!-- Body
|
||||||
<h1>{{ data.campaign.name }}</h1> -->
|
<h1>{{ data.campaign.name }}</h1> -->
|
||||||
|
|
||||||
<div class="campaign-preview-container">
|
<div class="campaign-preview-container" :class="hide_chat ? 'campaign-preview-compact' : ''" ref="container">
|
||||||
<div class="campaign-preview-column left">
|
<div class="campaign-preview-column left">
|
||||||
<h2>Players</h2>
|
<h2>Players</h2>
|
||||||
<PlayerList :campaign="data.campaign"></PlayerList>
|
<PlayerList :campaign="data.campaign"></PlayerList>
|
||||||
@ -61,11 +83,12 @@ function Launch(){
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="buttons-row">
|
<div class="buttons-row">
|
||||||
<button class="btn-primary button-row sound-click btn-green" v-on:click.prevent="Launch">Launch game</button>
|
<button class="btn-primary button-row sound-click btn-green" v-if="!hide_start" v-on:click.prevent="Launch">Launch game</button>
|
||||||
|
<button class="btn-primary button-row sound-click btn-red" v-if="hide_start" v-on:click.prevent="Exit">Exit game</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="campaign-preview-column right">
|
<div v-if="!hide_chat" class="campaign-preview-column right">
|
||||||
<h2>Chat</h2>
|
<ChatComponent></ChatComponent>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -115,6 +138,10 @@ function Launch(){
|
|||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 3fr 5fr 4fr;
|
grid-template-columns: 3fr 5fr 4fr;
|
||||||
|
|
||||||
|
&.campaign-preview-compact {
|
||||||
|
grid-template-columns: 2fr 3fr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.campaign-preview-column {
|
.campaign-preview-column {
|
||||||
|
38
client/src/views/windows/game/ChatWindow.vue
Normal file
38
client/src/views/windows/game/ChatWindow.vue
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<script setup>
|
||||||
|
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||||
|
|
||||||
|
import { onMounted, onUpdated, ref } from 'vue';
|
||||||
|
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
|
||||||
|
import ChatComponent from '../../partials/ChatComponent.vue';
|
||||||
|
|
||||||
|
const props = defineProps(['data']);
|
||||||
|
const data = props.data;
|
||||||
|
|
||||||
|
const handle = ref(null);
|
||||||
|
|
||||||
|
let id = data.id;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
SetupHandle(id, handle);
|
||||||
|
SetSize(id, {x: 400, y: 750});
|
||||||
|
ResetPosition(id, "center");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||||
|
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||||
|
|
||||||
|
<ChatComponent></ChatComponent>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.window-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
140
client/src/views/windows/game/DiceWindow.vue
Normal file
140
client/src/views/windows/game/DiceWindow.vue
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<script setup>
|
||||||
|
import WindowHandle from '@/views/partials/WindowHandle.vue';
|
||||||
|
|
||||||
|
import { onMounted, onUpdated, ref } from 'vue';
|
||||||
|
import { SetupHandle, SetSize, SetPosition, ResetPosition } from '@/services/Windows';
|
||||||
|
import IconButton from '@/views/partials/game/IconButton.vue'
|
||||||
|
|
||||||
|
import Dice from 'dice-notation-js'
|
||||||
|
import { GetClient, SendMessage } from '../../../services/Dragonroll';
|
||||||
|
|
||||||
|
const props = defineProps(['data']);
|
||||||
|
const data = props.data;
|
||||||
|
|
||||||
|
const handle = ref(null);
|
||||||
|
|
||||||
|
const diceResult = ref("");
|
||||||
|
const diceField = ref(null);
|
||||||
|
|
||||||
|
let id = data.id;
|
||||||
|
|
||||||
|
let ThrowD4 = () => { ThrowDice("d4") };
|
||||||
|
let ThrowD6 = () => { ThrowDice("d6") };
|
||||||
|
let ThrowD8 = () => { ThrowDice("d8") };
|
||||||
|
let ThrowD10 = () => { ThrowDice("d10") };
|
||||||
|
let ThrowD12 = () => { ThrowDice("d12") };
|
||||||
|
let ThrowD20 = () => { ThrowDice("d20") };
|
||||||
|
|
||||||
|
function comp (s, m, n, f, a) {
|
||||||
|
m = parseInt( m );
|
||||||
|
if( isNaN( m ) ) m = 1;
|
||||||
|
n = parseInt( n );
|
||||||
|
if( isNaN( n ) ) n = 1;
|
||||||
|
f = parseInt( f );
|
||||||
|
a = typeof(a) == 'string' ? parseInt( a.replace(/\s/g, '') ) : 0;
|
||||||
|
if( isNaN( a ) ) a = 0;
|
||||||
|
var r = 0;
|
||||||
|
for( var i=0; i<n; i++ )
|
||||||
|
r += Math.floor( Math.random() * f ) + 1;
|
||||||
|
return r * m + a;
|
||||||
|
};
|
||||||
|
function parse( de ) {
|
||||||
|
return comp.apply( this, de.match(/(?:(\d+)\s*\*\s*)?(\d*)d(\d+)(?:\s*([\+\-]\s*\d+))?/i) );
|
||||||
|
}
|
||||||
|
|
||||||
|
function ThrowDice(expr){
|
||||||
|
// let result = Dice.detailed(expr);
|
||||||
|
diceField.value.value = expr;
|
||||||
|
let result = parse(expr);
|
||||||
|
|
||||||
|
let audios = ['/sounds/roll1.wav', '/sounds/roll2.wav']
|
||||||
|
const audio = new Audio(audios[Math.floor(Math.random() * audios.length)]);
|
||||||
|
audio.type = "audio/wav"
|
||||||
|
audio.play();
|
||||||
|
|
||||||
|
console.log(result)
|
||||||
|
diceResult.value = result;
|
||||||
|
|
||||||
|
SendMessage({
|
||||||
|
content: {
|
||||||
|
roll: result,
|
||||||
|
throw: expr
|
||||||
|
},
|
||||||
|
author: GetClient()._id,
|
||||||
|
type: 'dice-roll'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function ThrowCustomDice(){
|
||||||
|
ThrowDice(diceField.value.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
SetupHandle(id, handle);
|
||||||
|
SetSize(id, {x: 300, y: 210});
|
||||||
|
ResetPosition(id, "center");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="window-wrapper" :id="'window-wrapper-' + id">
|
||||||
|
<WindowHandle :window="id" ref="handle"></WindowHandle>
|
||||||
|
|
||||||
|
<div class="horizontal-dice">
|
||||||
|
<IconButton icon="icons/game-icons/000000/skoll/d4.svg" :action="ThrowD4" size="big"></IconButton>
|
||||||
|
<IconButton icon="icons/game-icons/000000/delapouite/perspective-dice-six-svg.svg" :action="ThrowD6" size="big"></IconButton>
|
||||||
|
<IconButton icon="icons/game-icons/000000/delapouite/dice-eight-faces-eight.svg" :action="ThrowD8" size="big"></IconButton>
|
||||||
|
<IconButton icon="icons/game-icons/000000/skoll/d10.svg" :action="ThrowD10" size="big"></IconButton>
|
||||||
|
<IconButton icon="icons/game-icons/000000/skoll/d12.svg" :action="ThrowD12" size="big"></IconButton>
|
||||||
|
<IconButton icon="icons/game-icons/000000/delapouite/dice-twenty-faces-twenty.svg" :action="ThrowD20" size="big"></IconButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="custom-dice">
|
||||||
|
<input type="text" ref="diceField">
|
||||||
|
<IconButton icon="icons/game-icons/000000/delapouite/rolling-dices.svg" size="big" :action="ThrowCustomDice"></IconButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="roll-result">{{ diceResult }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.window-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.horizontal-dice {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-dice {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text] {
|
||||||
|
height: 32px;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-right: 6px;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roll-result {
|
||||||
|
font-size: 48px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: MrEavesRemake;
|
||||||
|
}
|
||||||
|
</style>
|
@ -33,7 +33,8 @@ module.exports = io => {
|
|||||||
socket.campaign = campaignId;
|
socket.campaign = campaignId;
|
||||||
|
|
||||||
if(!sessions[campaignId]) sessions[campaignId] = {
|
if(!sessions[campaignId]) sessions[campaignId] = {
|
||||||
players: await GetOfflinePlayers(campaignId)
|
players: await GetOfflinePlayers(campaignId),
|
||||||
|
chat: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -55,5 +56,9 @@ module.exports = io => {
|
|||||||
|
|
||||||
console.log(socket.user.username + " ha salido!")
|
console.log(socket.user.username + " ha salido!")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('message', (data) => {
|
||||||
|
io.to(socket.campaign).emit('message', data);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user