overte/tutorial/ownershipToken.js
2016-10-27 14:58:20 -07:00

188 lines
6.3 KiB
JavaScript

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;
if (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.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.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) {
debug(this.name, "Clearing update lifetime interval");
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, returning. Owner: " + owenerID + ", Us: " + this.name);
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);
},
};
debug("Returning from ownershipToken");