166 lines · 5.6 KB · JavaScript
RawDownload
"use strict";/*jslint vars: true, plusplus: true*//*global Agent, Avatar, Script, Entities, Vec3, Quat, print*/////  crowd-agent.js//  scripts/developer/tests/performance/////  Created by Howard Stearns on 9/29/16.//  Copyright 2016 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html////  Add this to domain-settings scripts url with n instances. It will lie dormant until//  a script like summon.js calls up to n avatars to be around you. var MESSAGE_CHANNEL = "io.highfidelity.summon-crowd"; print('crowd-agent version 5'); /* Observations:- File urls for AC scripts silently fail. Use a local server (e.g., python SimpleHTTPServer) for development.- URLs are cached regardless of server headers. Must use cache-defeating query parameters.- JSON.stringify(Avatar) silently fails (even when Agent.isAvatar)- If you run from a dev build directory, you must link assignment-client/<target>/resources to ../../interface/<target>/resources*/ function messageSend(message) {    Messages.sendMessage(MESSAGE_CHANNEL, JSON.stringify(message));} function getSound(data, callback) { // callback(sound) when downloaded (which may be immediate).    var sound = SoundCache.getSound(data.url);    if (sound.downloaded) {        return callback(sound);    }    function onDownloaded() {        sound.ready.disconnect(onDownloaded);        callback(sound);    }    sound.ready.connect(onDownloaded);}function onFinishedPlaying() {    messageSend({key: 'finishedSound'});} var attachment;var stopper;function clearStopper() {    if (!stopper) {        return;    }    Script.clearTimeout(stopper);    stopper = null;}function stopAgent(parameters) {    function stop() {        clearStopper();        if (attachment) {            Avatar.detachOne(attachment.modelURL, attachment.jointName);            attachment = undefined;        }        Agent.isListeningToAudioStream = false;        Agent.isAvatar = false;        print('crowd-agent stopped', JSON.stringify(parameters), JSON.stringify(Agent));    }    // Shutting down lots of agents at once can be hard on other parts of the system. (See fogbugz 2095.)    // For now, accept a parameter to delay for the given number of milliseconds before stopping.    // (We cannot count on summoning scripts to spread out the STOP messages, because they might be doing so    // on scriptEnding, in which case they are not allowed to create new delays.)    if (parameters.delay) {        if (!stopper) { // Let the first stopper do the deed.            stopper = Script.setTimeout(stop, parameters.delay);        }    } else {        stop();    }}  var MILLISECONDS_IN_SECOND = 1000;function startAgent(parameters) { // Can also be used to update.    print('crowd-agent starting params', JSON.stringify(parameters), JSON.stringify(Agent));    clearStopper();    var wasOff = !Agent.isAvatar;    Agent.isAvatar = true;    if (parameters.displayName !== undefined) {        Avatar.displayName = parameters.displayName;    }    if (parameters.position) {        Avatar.position = parameters.position;    }    if (parameters.orientation) {        Avatar.orientation = parameters.orientation;    }    if (parameters.skeletonModelURL) {        Avatar.skeletonModelURL = parameters.skeletonModelURL;    }    if (parameters.listen != undefined) {        Agent.isListeningToAudioStream = parameters.listen; // Send silence when not chattering.    } else if (wasOff) {        Agent.isListeningToAudioStream = true;    }    if (parameters.soundData) {        getSound(parameters.soundData, function (sound) {            Script.setTimeout(onFinishedPlaying, sound.duration * MILLISECONDS_IN_SECOND);            Agent.playAvatarSound(sound);        });    }    if (parameters.animationData) {        var data = parameters.animationData;        Avatar.startAnimation(data.url, data.fps || 30, 1.0, (data.loopFlag === undefined) ? true : data.loopFlag, false, data.startFrame || 0, data.endFrame);    }    if (parameters.attachment) {        attachment = parameters.attachment;        Avatar.attach(attachment.modelURL, attachment.jointName, attachment.translation, attachment.rotation, attachment.scale, attachment.isSoft);    } else {        attachment = undefined;    }    print('crowd-agent avatars started');} function messageHandler(channel, messageString, senderID) {    if (channel !== MESSAGE_CHANNEL) {        return;    }    print('crowd-agent message', channel, messageString, senderID);    if (Agent.sessionUUID === senderID) { // ignore my own        return;    }    var message = {};    try {        message = JSON.parse(messageString);    } catch (e) {		    }    switch (message.key) {    case "HELO":        messageSend({key: 'hello'}); // Allow the coordinator to count responses and make assignments.        break;    case 'hello': // ignore responses (e.g., from other agents)    case 'finishedSound':        break;    case "SUMMON":        if (message.rcpt === Agent.sessionUUID) {            startAgent(message);        }        break;    case "STOP":        if (message.rcpt === Agent.sessionUUID) {            stopAgent(message);        }        break;    default:        print("crowd-agent received unrecognized message:", channel, messageString, senderID);    }}Messages.subscribe(MESSAGE_CHANNEL);Messages.messageReceived.connect(messageHandler); Script.scriptEnding.connect(function () {    print('crowd-agent shutting down');    Messages.messageReceived.disconnect(messageHandler);    Messages.unsubscribe(MESSAGE_CHANNEL);    print('crowd-agent unsubscribed');});