Files
MaterialDeck/MaterialDeck.js
CDeenen ead6db5a48 v0.8.4
2020-11-11 04:10:36 +01:00

347 lines
10 KiB
JavaScript

import {registerSettings} from "./src/settings.js";
import {StreamDeck} from "./src/streamDeck.js";
import {TokenControl} from "./src/token.js";
import {Move} from "./src/move.js";
import {MacroControl} from "./src/macro.js";
import {CombatTracker} from "./src/combattracker.js";
import {PlaylistControl} from "./src/playlist.js";
import {SoundboardControl} from "./src/soundboard.js";
import {OtherControls} from "./src/othercontrols.js";
export var streamDeck;
export var tokenControl;
var move;
export var macroControl;
var combatTracker;
var playlistControl;
var soundboard;
var otherControls;
export const moduleName = "MaterialDeck";
export var selectedTokenId;
let ready = false;
//CONFIG.debug.hooks = true;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Global variables
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var enableModule;
//Websocket variables
let ip = "localhost"; //Ip address of the websocket server
let port = "3003"; //Port of the websocket server
var ws; //Websocket variable
let wsOpen = false; //Bool for checking if websocket has ever been opened => changes the warning message if there's no connection
let wsInterval; //Interval timer to detect disconnections
let WSconnected = false;
/*
* Analyzes the message received
*
* @param {*} msg Message received
*/
async function analyzeWSmessage(msg,passthrough = false){
if (enableModule == false) return;
const data = JSON.parse(msg);
if (data == undefined || data.payload == undefined) return;
//console.log(data);
const action = data.action;
const event = data.event;
const context = data.context;
const coordinates = data.payload.coordinates;
if (coordinates == undefined) coordinates = 0;
const settings = data.payload.settings;
if (data.data == 'init'){
}
if (event == 'willAppear' || event == 'didReceiveSettings'){
streamDeck.setScreen(action);
streamDeck.setContext(action,context,coordinates,settings);
if (action == 'token'){
if (selectedTokenId != undefined)
tokenControl.update(selectedTokenId);
}
else if (action == 'macro')
macroControl.update(settings,context);
else if (action == 'combattracker')
combatTracker.update(settings,context);
else if (action == 'playlist')
playlistControl.update(settings,context);
else if (action == 'soundboard')
soundboard.update(settings,context);
else if (action == 'other')
otherControls.update(settings,context);
}
else if (event == 'willDisappear'){
streamDeck.clearContext(action,coordinates);
}
else if (event == 'keyDown'){
if (action == 'token')
tokenControl.keyPress(settings);
else if (action == 'move')
move.keyPress(settings);
else if (action == 'macro')
macroControl.keyPress(settings);
else if (action == 'combattracker')
combatTracker.keyPress(settings,context);
else if (action == 'playlist')
playlistControl.keyPress(settings,context);
else if (action == 'soundboard'){
soundboard.keyPressDown(settings);
}
}
else if (event == 'keyUp'){
if (action == 'soundboard'){
soundboard.keyPressUp(settings);
}
else if (action == 'other')
otherControls.keyPress(settings);
}
};
/**
* Start a new websocket
* Start a 10s interval, if no connection is made, run resetWS()
* If connection is made, set interval to 1.5s to check for disconnects
* If message is received, reset the interval, and send the message to analyzeWSmessage()
*/
function startWebsocket() {
//ip = localhost;
ws = new WebSocket('ws://'+ip+':'+port+'/1');
ws.onmessage = function(msg){
//console.log(msg);
analyzeWSmessage(msg.data);
clearInterval(wsInterval);
wsInterval = setInterval(resetWS, 5000);
}
ws.onopen = function() {
WSconnected = true;
ui.notifications.info("Material Deck Connected: "+ip+':'+port);
wsOpen = true;
let msg = {
type: "Foundry"
}
ws.send(JSON.stringify(msg));
clearInterval(wsInterval);
wsInterval = setInterval(resetWS, 5000);
}
clearInterval(wsInterval);
wsInterval = setInterval(resetWS, 10000);
}
/**
* Try to reset the websocket if a connection is lost
*/
function resetWS(){
if (wsOpen) ui.notifications.warn("Material Deck: "+game.i18n.localize("MaterialDeck.Notifications.Disconnected"));
else ui.notifications.warn("Material Deck: "+game.i18n.localize("MaterialDeck.Notifications.ConnectFail"));
WSconnected = false;
startWebsocket();
}
export function sendWS(txt){
if (WSconnected)
ws.send(txt);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Hooks
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Ready hook
* Attempt to open the websocket
*/
Hooks.once('ready', ()=>{
enableModule = (game.settings.get(moduleName,'Enable')) ? true : false;
if (enableModule == false) return;
game.socket.on(`module.MaterialDeck`, (payload) =>{
//console.log(payload);
if (payload.msgType != "playSound") return;
playTrack(payload.trackNr,payload.play,payload.repeat,payload.volume);
});
if (game.user.isGM == false) {
ready = true;
return;
}
startWebsocket();
streamDeck = new StreamDeck();
tokenControl = new TokenControl();
move = new Move();
macroControl = new MacroControl();
combatTracker = new CombatTracker();
playlistControl = new PlaylistControl();
soundboard = new SoundboardControl();
otherControls = new OtherControls();
let soundBoardSettings = game.settings.get(moduleName,'soundboardSettings');
let macroSettings = game.settings.get(moduleName, 'macroSettings');
let array = [];
for (let i=0; i<64; i++) array[i] = "";
let arrayVolume = [];
for (let i=0; i<64; i++) arrayVolume[i] = "50";
let arrayZero = [];
for (let i=0; i<64; i++) arrayZero[i] = "0";
if (macroSettings.color == undefined){
game.settings.set(moduleName,'macroSettings',{
macros: array,
color: arrayZero
});
}
if (soundBoardSettings.colorOff == undefined){
game.settings.set(moduleName,'soundboardSettings',{
playlist: "",
sounds: array,
colorOn: arrayZero,
colorOff: arrayZero,
mode: arrayZero,
toggle: arrayZero,
volume: arrayVolume
});
}
});
export function playTrack(soundNr,play,repeat,volume){
if (play){
let trackId = game.settings.get(moduleName,'soundboardSettings').sounds[soundNr];
let playlistId = game.settings.get(moduleName,'soundboardSettings').playlist;
let sounds = game.playlists.entities.find(p => p._id == playlistId).data.sounds;
let sound = sounds.find(p => p._id == trackId);
if (sound == undefined){
activeSounds[soundNr] = false;
return;
}
volume *= game.settings.get("core", "globalInterfaceVolume");
let src = sound.path;
let howl = new Howl({src, volume, loop: repeat, onend: (id)=>{
if (repeat == false){
activeSounds[soundNr] = false;
}
},
onstop: (id)=>{
activeSounds[soundNr] = false;
}});
howl.play();
activeSounds[soundNr] = howl;
}
else {
activeSounds[soundNr].stop();
}
}
Hooks.on('updateToken',(scene,token)=>{
if (enableModule == false || ready == false) return;
let tokenId = token._id;
if (tokenId == selectedTokenId)
tokenControl.update(selectedTokenId);
});
Hooks.on('controlToken',(token,controlled)=>{
if (enableModule == false || ready == false) return;
if (controlled) {
selectedTokenId = token.data._id;
}
else {
selectedTokenId = undefined;
}
tokenControl.update(selectedTokenId);
});
Hooks.on('renderHotbar', (hotbar)=>{
if (enableModule == false || ready == false) return;
macroControl.hotbar(hotbar.macros);
});
Hooks.on('renderCombatTracker',()=>{
if (enableModule == false || ready == false) return;
combatTracker.updateAll();
});
Hooks.on('renderPlaylistDirectory', (playlistDirectory)=>{
if (enableModule == false || ready == false) return;
playlistControl.updateAll();
});
Hooks.on('closeplaylistConfigForm', (form)=>{
if (enableModule == false || ready == false) return;
if (form.template == "./modules/MaterialDeck/templates/playlistConfig.html")
playlistControl.updateAll();
});
Hooks.on('pauseGame',()=>{
if (enableModule == false || ready == false) return;
otherControls.updateAll();
});
Hooks.on('renderSidebarTab',()=>{
if (enableModule == false || ready == false) return;
otherControls.updateAll();
});
Hooks.on('updateScene',()=>{
if (enableModule == false || ready == false) return;
otherControls.updateAll();
});
Hooks.on('renderSceneControls',()=>{
if (enableModule == false || ready == false) return;
otherControls.updateAll();
});
Hooks.once('init', ()=>{
//CONFIG.debug.hooks = true;
registerSettings(); //in ./src/settings.js
});
Hooks.once('canvasReady',()=>{
ready = true;
});
export function getFromJSONArray(data,i){
if (i>9) return 'nul';
let val;
if (i == 0) val = data.a;
else if (i == 1) val = data.a;
else if (i == 2) val = data.c;
else if (i == 3) val = data.d;
else if (i == 4) val = data.e;
else if (i == 5) val = data.f;
else if (i == 6) val = data.g;
else if (i == 7) val = data.h;
else if (i == 8) val = data.i;
return val;
}
export function setToJSONArray(data,i,val){
if (i>9) return 'nul';
if (i == 0) data.a = val;
else if (i == 1) data.b = val;
else if (i == 2) data.c = val;
else if (i == 3) data.d = val;
else if (i == 4) data.e = val;
else if (i == 5) data.f = val;
else if (i == 6) data.g = val;
else if (i == 7) data.h = val;
else if (i == 8) data.i = val;
}