Add ownership token tot tutorial

This commit is contained in:
Ryan Huffman 2016-09-15 13:02:33 -07:00
parent 2bf13b9cf6
commit a05f681704
2 changed files with 292 additions and 93 deletions

188
tutorial/ownershipToken.js Normal file
View file

@ -0,0 +1,188 @@
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {},
fBound = function() {
return fToBind.apply(this instanceof fNOP
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
fBound.prototype = new fNOP();
return fBound;
};
}
function getOption(options, key, defaultValue) {
if (options.hasOwnProperty(key)) {
return options[key];
}
return defaultValue;
}
var TOKEN_NAME_PREFIX = "ownership_token-";
function getOwnershipTokenID(parentEntityID) {
var childEntityIDs = Entities.getChildrenIDs(parentEntityID);
var ownerID = null;
var ownerName = '';
for (var i = 0; i < childEntityIDs.length; ++i) {
var childID = childEntityIDs[i];
var properties = Entities.getEntityProperties(childID, ['name', 'userData', 'lifetime', 'age']);
var childName = properties.name;
//debug("Owner lifetime: ", properties.lifetime, properties.age);
if (properties.age > 0.5 && childName.indexOf(TOKEN_NAME_PREFIX) == 0) {
if (ownerID === null || childName < ownerName) {
ownerID = childID;
ownerName = childName;
}
}
}
return ownerID;
}
function createOwnershipToken(name, parentEntityID) {
return Entities.addEntity({
type: "Box",
name: TOKEN_NAME_PREFIX + name,
visible: false,
parentID: parentEntityID,
locationPosition: { x: 0, y: 0, z: 0 },
dimensions: { x: 100, y: 100, z: 100 },
collisionless: true,
lifetime: 5
});
}
var DEBUG = true;
function debug() {
if (DEBUG) {
var args = Array.prototype.slice.call(arguments);
print.apply(this, args);
}
}
var TOKEN_STATE_DESTROYED = -1;
var TOKEN_STATE_UNOWNED = 0;
var TOKEN_STATE_REQUESTING_OWNERSHIP = 1;
var TOKEN_STATE_OWNED = 2;
OwnershipToken = function(name, parentEntityID, options) {
this.name = MyAvatar.sessionUUID + "-" + Math.floor(Math.random() * 10000000);
this.name = Math.floor(Math.random() * 10000000);
this.parentEntityID = parentEntityID;
// How often to check whether the token is available if we don't currently own it
this.checkEverySeconds = getOption(options, 'checkEverySeconds', 1000);
this.updateTokenLifetimeEvery = getOption(options, 'updateTokenLifetimeEvery', 2000);
//this.onRequestingOwnership = getOption(options, 'onRequestingOwnership', function() { });
this.onGainedOwnership = getOption(options, 'onGainedOwnership', function() { });
this.onLostOwnership = getOption(options, 'onLostOwnership', function() { });
this.ownershipTokenID = null;
this.setState(TOKEN_STATE_UNOWNED);
};
OwnershipToken.prototype = {
destroy: function() {
debug(this.name, "Destroying token");
this.setState(TOKEN_STATE_DESTROYED);
},
setState: function(newState) {
if (this.state == newState) {
debug(this.name, "Warning: Trying to set state to the current state");
return;
}
if (this.updateLifetimeID) {
Script.clearInterval(this.updateLifetimeID);
this.updateLifetimeID = null;
}
if (this.checkOwnershipAvailableID) {
Script.clearInterval(this.checkOwnershipAvailableID);
this.checkOwnershipAvailableID = null;
}
if (this.state == TOKEN_STATE_OWNED) {
this.onLostOwnership(this);
}
if (newState == TOKEN_STATE_UNOWNED) {
this.checkOwnershipAvailableID = Script.setInterval(
this.tryRequestingOwnership.bind(this), this.checkEverySeconds);
} else if (newState == TOKEN_STATE_REQUESTING_OWNERSHIP) {
} else if (newState == TOKEN_STATE_OWNED) {
this.onGainedOwnership(this);
this.updateLifetimeID = Script.setInterval(
this.updateTokenLifetime.bind(this), this.updateTokenLifetimeEvery);
} else if (newState == TOKEN_STATE_DESTROYED) {
Entities.deleteEntity(this.ownershipTokenID);
}
debug(this.name, "Info: Switching to state:", newState);
this.state = newState;
},
updateTokenLifetime: function() {
if (this.state != TOKEN_STATE_OWNED) {
debug(this.name, "Error: Trying to update token while it is unowned");
return;
}
debug(this.name, "Updating entity lifetime");
var age = Entities.getEntityProperties(this.ownershipTokenID, 'age').age;
Entities.editEntity(this.ownershipTokenID, {
lifetime: age + 5
});
},
tryRequestingOwnership: function() {
if (this.state == TOKEN_STATE_REQUESTING_OWNERSHIP || this.state == TOKEN_STATE_OWNED) {
debug(this.name, "We already have or are requesting ownership");
return;
}
var ownerID = getOwnershipTokenID(this.parentEntityID);
if (ownerID !== null) {
// Already owned, return
debug(this.name, "Token already owned by another client, return");
return;
}
this.ownershipTokenID = createOwnershipToken(this.name, this.parentEntityID);
this.setState(TOKEN_STATE_REQUESTING_OWNERSHIP);
function checkOwnershipRequest() {
var ownerID = getOwnershipTokenID(this.parentEntityID);
if (ownerID == this.ownershipTokenID) {
debug(this.name, "Info: Obtained ownership");
this.setState(TOKEN_STATE_OWNED);
} else {
if (ownerID === null) {
debug(this.name, "Warning: Checked ownership request and no tokens existed");
}
debug(this.name, "Info: Lost ownership request")
this.ownershipTokenID = null;
this.setState(TOKEN_STATE_UNOWNED);
}
}
Script.setTimeout(checkOwnershipRequest.bind(this), 2000);
},
};

View file

@ -30,6 +30,7 @@ Script.include("entityData.js");
Script.include("viveHandsv2.js");
Script.include("lighter/createButaneLighter.js");
Script.include('ownershipToken.js');
var BASKET_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Trach-Can-3.fbx";
var BASKET_COLLIDER_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Trash-Can-4.obj";
@ -146,19 +147,19 @@ function spawnWithTag(entityData, transform, tag) {
}
function deleteEntitiesWithTag(tag) {
print("searching for...:", tag);
print("searching for...:", tag);
var entityIDs = findEntitiesWithTag(tag);
for (var i = 0; i < entityIDs.length; ++i) {
print("Deleteing:", entityIDs[i]);
//print("Deleteing:", entityIDs[i]);
Entities.deleteEntity(entityIDs[i]);
}
}
function editEntitiesWithTag(tag, propertiesOrFn) {
print("Editing:", tag);
//print("Editing:", tag);
var entityIDs = findEntitiesWithTag(tag);
print("Editing...", entityIDs);
//print("Editing...", entityIDs);
for (var i = 0; i < entityIDs.length; ++i) {
print("Editing...", entityIDs[i]);
//print("Editing...", entityIDs[i]);
if (isFunction(propertiesOrFn)) {
Entities.editEntity(entityIDs[i], propertiesOrFn(entityIDs[i]));
} else {
@ -318,11 +319,11 @@ stepOrient.prototype = {
}
};
this.overlay = new StayInFrontOverlay("model", {
url: "http://hifi-content.s3.amazonaws.com/alan/dev/Prompt-Cards/welcome.fbx?11",
ignoreRayIntersection: true,
visible: false
}, 1.5, { x: 0, y: 0.3, z: 0 });
// this.overlay = new StayInFrontOverlay("model", {
// url: "http://hifi-content.s3.amazonaws.com/alan/dev/Prompt-Cards/welcome.fbx?11",
// ignoreRayIntersection: true,
// visible: false
// }, 1.5, { x: 0, y: 0.3, z: 0 });
// Spawn content set
//spawnWithTag(HandsAboveHeadData, defaultTransform, tag);
@ -952,105 +953,115 @@ function hideEntitiesWithTag(tag) {
});
}
var STEPS;
var currentStepNum = -1;
var currentStep = null;
function startTutorial() {
currentStepNum = -1;
currentStep = null;
STEPS = [
new stepDisableControllers("step0"),
new stepOrient("orient"),
//new stepWelcome("welcome"),
new stepRaiseAboveHead("raiseHands"),
new stepNearGrab("nearGrab"),
new stepFarGrab("farGrab"),
new stepEquip("equip"),
new stepTurnAround("turnAround"),
new stepTeleport("teleport"),
new stepFinish("finish"),
];
for (var i = 0; i < STEPS.length; ++i) {
STEPS[i].cleanup();
}
location = "/tutorial_begin";
//location = "/tutorial";
MyAvatar.shouldRenderLocally = false;
startNextStep();
}
TutorialManager = function() {
var STEPS;
function startNextStep() {
if (currentStep) {
currentStep.cleanup();
}
var currentStepNum = -1;
var currentStep = null;
++currentStepNum;
if (currentStepNum >= STEPS.length) {
// Done
print("DONE WITH TUTORIAL");
this.startTutorial = function() {
currentStepNum = -1;
currentStep = null;
STEPS = [
new stepDisableControllers("step0"),
new stepOrient("orient"),
//new stepWelcome("welcome"),
new stepRaiseAboveHead("raiseHands"),
new stepNearGrab("nearGrab"),
new stepFarGrab("farGrab"),
new stepEquip("equip"),
new stepTurnAround("turnAround"),
new stepTeleport("teleport"),
new stepFinish("finish"),
];
for (var i = 0; i < STEPS.length; ++i) {
STEPS[i].cleanup();
}
location = "/tutorial_begin";
//location = "/tutorial";
MyAvatar.shouldRenderLocally = false;
this.startNextStep();
}
this.startNextStep = function() {
if (currentStep) {
currentStep.cleanup();
}
++currentStepNum;
if (currentStepNum >= STEPS.length) {
// Done
print("DONE WITH TUTORIAL");
currentStepNum = -1;
currentStep = null;
return false;
} else {
print("Starting step", currentStepNum);
currentStep = STEPS[currentStepNum];
currentStep.start(this.startNextStep);
return true;
}
}.bind(this);
this.restartStep = function() {
if (currentStep) {
currentStep.cleanup();
currentStep.start(this.startNextStep);
}
}
this.stopTutorial = function() {
if (currentStep) {
currentStep.cleanup();
}
currentStepNum = -1;
currentStep = null;
return false;
} else {
print("Starting step", currentStepNum);
currentStep = STEPS[currentStepNum];
currentStep.start(startNextStep);
return true;
}
}
function restartStep() {
if (currentStep) {
currentStep.cleanup();
currentStep.start(startNextStep);
}
}
function skipTutorial() {
}
function stopTutorial() {
if (currentStep) {
currentStep.cleanup();
}
currentStepNum = -1;
currentStep = null;
}
startTutorial();
Script.scriptEnding.connect(function() {
Controller.enableMapping('handControllerPointer-click');
});
Controller.disableMapping('handControllerPointer-click');
//mapping.from([Controller.Standard.RY]).to(noop);
//{ "from": "Vive.LeftApplicationMenu", "to": "Standard.LeftSecondaryThumb" },
//mapping.from([Controller.Standard.RY]).when("Controller.Application.Grounded").to(noop);
//mapping.from([Controller.Standard.RY]).when(Controller.Application.Grounded).to(noop);
// var entityID = '{be3d10a3-262a-4827-b30c-ec025c4325dc}';
// var token = new OwnershipToken(Math.random() * 100000, entityID, {
// onGainedOwnership: function(token) {
// //Script.setTimeout(function() { token.destroy() }, 15000);
// Controller.keyReleaseEvent.connect(keyReleaseHandler);
// startTutorial();
// },
// onLostOwnership: function(token) {
// Controller.keyReleaseEvent.disconnect(keyReleaseHandler);
// stopTutorial();
// }
// });
Script.scriptEnding.connect(stopTutorial);
Controller.keyReleaseEvent.connect(function (event) {
print(event.text);
if (event.text == ",") {
if (!startNextStep()) {
startTutorial();
}
} else if (event.text == "F11") {
restartStep();
} else if (event.text == "F10") {
MyAvatar.shouldRenderLocally = !MyAvatar.shouldRenderLocally;
} else if (event.text == "r") {
stopTutorial();
startTutorial();
}
//tutorialManager = new TutorialManager();
//tutorialManager.startTutorial();
//Controller.keyReleaseEvent.connect(keyReleaseHandler);
Script.scriptEnding.connect(function() {
//token.destroy();
//stopTutorial();
});
// function keyReleaseHandler(event) {
// print(event.text);
// if (event.text == ",") {
// if (!tutorialManager.startNextStep()) {
// tutorialManager.startTutorial();
// }
// } else if (event.text == "F11") {
// tutorialManager.restartStep();
// } else if (event.text == "F10") {
// MyAvatar.shouldRenderLocally = !MyAvatar.shouldRenderLocally;
// } else if (event.text == "r") {
// tutorialManager.stopTutorial();
// tutorialManager.startTutorial();
// }
// }
//
// Messages.sendLocalMessage('Controller-Display', JSON.stringify({
// name: "menu",
// visible: false,