mirror of
https://github.com/overte-org/overte.git
synced 2025-04-12 09:42:11 +02:00
188 lines
6.3 KiB
JavaScript
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");
|