more careful stopping of intervals, edge case stuff

This commit is contained in:
David Kelly 2017-03-16 13:19:17 -07:00
parent 05fec328c0
commit 60000becce

View file

@ -24,7 +24,8 @@ const STATES = {
const STATE_STRINGS = ["inactive", "waiting", "friending", "makingFriends"]; const STATE_STRINGS = ["inactive", "waiting", "friending", "makingFriends"];
const WAITING_INTERVAL = 100; // ms const WAITING_INTERVAL = 100; // ms
const FRIENDING_INTERVAL = 100; // ms const FRIENDING_INTERVAL = 100; // ms
const FRIENDING_TIME = 3000; // ms const MAKING_FRIENDS_TIMEOUT = 1000; // ms
const FRIENDING_TIME = 2000; // ms
const FRIENDING_HAPTIC_STRENGTH = 0.5; const FRIENDING_HAPTIC_STRENGTH = 0.5;
const FRIENDING_SUCCESS_HAPTIC_STRENGTH = 1.0; const FRIENDING_SUCCESS_HAPTIC_STRENGTH = 1.0;
const HAPTIC_DURATION = 20; const HAPTIC_DURATION = 20;
@ -39,6 +40,7 @@ var currentHand;
var state = STATES.inactive; var state = STATES.inactive;
var friendingInterval; var friendingInterval;
var waitingInterval; var waitingInterval;
var makingFriendsTimeout;
var overlay; var overlay;
var animHandlerId; var animHandlerId;
var entityDimensionMultiplier = 1.0; var entityDimensionMultiplier = 1.0;
@ -81,6 +83,24 @@ function handToHaptic(hand) {
return -1; return -1;
} }
function stopWaiting() {
if (waitingInterval) {
waitingInterval = Script.clearInterval(waitingInterval);
}
}
function stopFriending() {
if (friendingInterval) {
friendingInterval = Script.clearInterval(friendingInterval);
}
}
function stopMakingFriends() {
if (makingFriendsTimeout) {
makingFriendsTimeout = Script.clearTimeout(makingFriendsTimeout);
}
}
// This returns the position of the palm, really. Which relies on the avatar // This returns the position of the palm, really. Which relies on the avatar
// having the expected middle1 joint. TODO: fallback for when this isn't part // having the expected middle1 joint. TODO: fallback for when this isn't part
// of the avatar? // of the avatar?
@ -184,13 +204,10 @@ function findNearestWaitingAvatar() {
// As currently implemented, we select the closest waiting avatar (if close enough) and send // As currently implemented, we select the closest waiting avatar (if close enough) and send
// them a friendRequest. If nobody is close enough we just wait for a friendRequest. If the // them a friendRequest. If nobody is close enough we send a waiting message, and wait for a
// 2 people who want to connect are both somewhat out of range when they initiate the shake, // friendRequest. If the 2 people who want to connect are both somewhat out of range when they
// then neither gets a message // initiate the shake, they will race to see who sends the friendRequest after noticing the
// and they both just stand there with their hands out. // waiting message. Either way, they will start friending eachother at that point.
// Ideally we'd either show that (so they ungrip/regrip and adjust position), or do what I
// initially did and start an interval to look for nearby avatars. The issue with the latter
// is this introduces some race condition we may need to handle (hence I didn't do it yet).
function startHandshake(fromKeyboard) { function startHandshake(fromKeyboard) {
if (fromKeyboard) { if (fromKeyboard) {
debug("adding animation"); debug("adding animation");
@ -205,6 +222,11 @@ function startHandshake(fromKeyboard) {
entityDimensionMultiplier = 1.0; entityDimensionMultiplier = 1.0;
friendingId = undefined; friendingId = undefined;
friendingHand = undefined; friendingHand = undefined;
// just in case
stopWaiting();
stopFriending();
stopMakingFriends();
var nearestAvatar = findNearestWaitingAvatar(); var nearestAvatar = findNearestWaitingAvatar();
if (nearestAvatar.avatar) { if (nearestAvatar.avatar) {
friendingId = nearestAvatar.avatar; friendingId = nearestAvatar.avatar;
@ -236,13 +258,14 @@ function endHandshake() {
state = STATES.inactive; state = STATES.inactive;
friendingId = undefined; friendingId = undefined;
friendingHand = undefined; friendingHand = undefined;
if (friendingInterval) { stopWaiting();
friendingInterval = Script.clearInterval(friendingInterval); stopFriending();
// send done to let friend know you are not making friends now stopMakingFriends();
messageSend({ // send done to let friend know you are not making friends now
key: "done" messageSend({
}); key: "done"
} });
if (animHandlerId) { if (animHandlerId) {
debug("removing animation"); debug("removing animation");
MyAvatar.removeAnimationStateHandler(animHandlerId); MyAvatar.removeAnimationStateHandler(animHandlerId);
@ -286,9 +309,7 @@ function lookForWaitingAvatar() {
// message before noticing they were in range in this loop) // message before noticing they were in range in this loop)
// just in case we reenter before stopping // just in case we reenter before stopping
if (waitingInterval) { stopWaiting();
waitingInterval = Script.clearInterval(waitingInterval);
}
debug("started looking for waiting avatars"); debug("started looking for waiting avatars");
waitingInterval = Script.setInterval(function () { waitingInterval = Script.setInterval(function () {
if (state == STATES.waiting && !friendingId) { if (state == STATES.waiting && !friendingId) {
@ -308,7 +329,7 @@ function lookForWaitingAvatar() {
} }
} else { } else {
// something happened, stop looking for avatars to friend // something happened, stop looking for avatars to friend
waitingInterval = Script.clearInterval(waitingInterval); stopWaiting();
debug("stopped looking for waiting avatars"); debug("stopped looking for waiting avatars");
} }
}, WAITING_INTERVAL); }, WAITING_INTERVAL);
@ -325,11 +346,12 @@ function makeFriends(id) {
Controller.triggerHapticPulse(FRIENDING_SUCCESS_HAPTIC_STRENGTH, HAPTIC_DURATION, handToHaptic(currentHand)); Controller.triggerHapticPulse(FRIENDING_SUCCESS_HAPTIC_STRENGTH, HAPTIC_DURATION, handToHaptic(currentHand));
state = STATES.makingFriends; state = STATES.makingFriends;
// now that we made friends, reset everything // now that we made friends, reset everything
Script.setTimeout(function () { makingFriendsTimeout = Script.setTimeout(function () {
friendingId = undefined; friendingId = undefined;
friendingHand = undefined; friendingHand = undefined;
entityDimensionMultiplier = 1.0; entityDimensionMultiplier = 1.0;
}, 1000); makingFriendsTimeout = undefined;
}, MAKING_FRIENDS_TIMEOUT);
} }
// we change states, start the friendingInterval where we check // we change states, start the friendingInterval where we check
@ -357,11 +379,11 @@ function startFriending(id, hand) {
entityDimensionMultiplier = 1.0 + 2.0 * count * FRIENDING_INTERVAL / FRIENDING_TIME; entityDimensionMultiplier = 1.0 + 2.0 * count * FRIENDING_INTERVAL / FRIENDING_TIME;
if (state != STATES.friending) { if (state != STATES.friending) {
debug("stopping friending interval, state changed"); debug("stopping friending interval, state changed");
friendingInterval = Script.clearInterval(friendingInterval); stopFriending();
} else if (!isNearby(id, hand)) { } else if (!isNearby(id, hand)) {
// gotta go back to waiting // gotta go back to waiting
debug(id, "moved, back to waiting"); debug(id, "moved, back to waiting");
friendingInterval = Script.clearInterval(friendingInterval); stopFriending();
messageSend({ messageSend({
key: "done" key: "done"
}); });
@ -369,19 +391,21 @@ function startFriending(id, hand) {
} else if (count > FRIENDING_TIME/FRIENDING_INTERVAL) { } else if (count > FRIENDING_TIME/FRIENDING_INTERVAL) {
debug("made friends with " + id); debug("made friends with " + id);
makeFriends(id); makeFriends(id);
friendingInterval = Script.clearInterval(friendingInterval); stopFriending();
} }
}, FRIENDING_INTERVAL); }, FRIENDING_INTERVAL);
} }
/* /*
A simple sequence diagram: A simple sequence diagram: NOTE that the FriendAck is somewhat
vestigial, and probably should be removed shortly.
Avatar A Avatar B Avatar A Avatar B
| | | |
| <-----(FriendRequest) -- startHandshake | <-----(waiting) ----- startHandshake
startHandshake -- (FriendAck) ---> | startHandshake -- (FriendRequest) -> |
| | | |
| <-------(friending) -- startFriending | <-------(FriendAck) --------- |
| <--------(friending) -- startFriending
startFriending -- (friending) ---> | startFriending -- (friending) ---> |
| | | |
| friends | friends
@ -402,7 +426,6 @@ function messageHandler(channel, messageString, senderID) {
} catch (e) { } catch (e) {
debug(e); debug(e);
} }
debug("recv'd message:", message);
switch (message.key) { switch (message.key) {
case "waiting": case "waiting":
// add this guy to waiting object. Any other message from this person will // add this guy to waiting object. Any other message from this person will
@ -421,9 +444,13 @@ function messageHandler(channel, messageString, senderID) {
id: senderID, id: senderID,
hand: handToString(currentHand) hand: handToString(currentHand)
}); });
} else {
if (state == STATES.waiting && friendingId == senderID) {
// the person you are trying to friend sent a request to someone else. See the
// if statement above. So, don't cry, just start the handshake over again
startHandshake();
}
} }
// TODO: check to see if the person we are trying to friend sent this to someone else,
// and try again
break; break;
case "friendAck": case "friendAck":
delete waitingList[senderID]; delete waitingList[senderID];
@ -432,6 +459,7 @@ function messageHandler(channel, messageString, senderID) {
// start friending... // start friending...
friendingId = senderID; friendingId = senderID;
friendingHand = message.hand; friendingHand = message.hand;
stopWaiting();
startFriending(senderID, message.hand); startFriending(senderID, message.hand);
} else { } else {
if (friendingId) { if (friendingId) {
@ -467,9 +495,7 @@ function messageHandler(channel, messageString, senderID) {
// if they are done, and didn't friend us, terminate our // if they are done, and didn't friend us, terminate our
// friending // friending
if (message.friendId !== MyAvatar.sessionUUID) { if (message.friendId !== MyAvatar.sessionUUID) {
if (friendingInterval) { stopFriending();
friendingInterval = Script.clearInterval(friendingInterval);
}
// now just call startHandshake. Should be ok to do so without a // now just call startHandshake. Should be ok to do so without a
// value for isKeyboard, as we should not change the animation // value for isKeyboard, as we should not change the animation
// state anyways (if any) // state anyways (if any)