2017-06-13 14:09:18 +02:00
|
|
|
/**
|
2017-06-26 18:20:34 +02:00
|
|
|
* Storage System takes care loading and linking components and dependencies
|
2017-06-28 17:09:06 +02:00
|
|
|
* @param graphics
|
2017-06-30 14:20:22 +02:00
|
|
|
* @param physics
|
2017-06-13 14:09:18 +02:00
|
|
|
* @param apiSystem GameLib.API.System
|
|
|
|
* @param apiUrl
|
|
|
|
* @param token
|
2017-06-26 18:20:34 +02:00
|
|
|
* @param apiUploadUrl
|
|
|
|
* @param onImageLoaded
|
|
|
|
* @param onImageProgress
|
|
|
|
* @param onImageError
|
2017-06-27 13:27:27 +02:00
|
|
|
* @param onComponentLoaded
|
|
|
|
* @param onComponentProgress
|
|
|
|
* @param onComponentError
|
2017-06-13 14:09:18 +02:00
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
GameLib.System.Storage = function(
|
2017-06-28 17:09:06 +02:00
|
|
|
graphics,
|
2017-06-30 14:20:22 +02:00
|
|
|
physics,
|
2017-06-13 14:09:18 +02:00
|
|
|
apiSystem,
|
|
|
|
apiUrl,
|
2017-06-26 18:20:34 +02:00
|
|
|
token,
|
|
|
|
apiUploadUrl,
|
|
|
|
onImageLoaded,
|
|
|
|
onImageProgress,
|
2017-06-27 13:27:27 +02:00
|
|
|
onImageError,
|
|
|
|
onComponentLoaded,
|
|
|
|
onComponentProgress,
|
|
|
|
onComponentError
|
2017-06-13 14:09:18 +02:00
|
|
|
) {
|
2017-06-28 17:09:06 +02:00
|
|
|
this.graphics = graphics;
|
|
|
|
this.graphics.isNotThreeThrow();
|
|
|
|
|
2017-06-30 14:20:22 +02:00
|
|
|
this.physics = physics;
|
|
|
|
this.physics.isNotCannonThrow();
|
|
|
|
|
2017-06-26 18:20:34 +02:00
|
|
|
GameLib.System.call(
|
|
|
|
this,
|
|
|
|
apiSystem
|
|
|
|
);
|
2017-06-13 14:09:18 +02:00
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(apiUrl)) {
|
|
|
|
console.warn('Need an API URL for a storage system');
|
2017-06-26 18:20:34 +02:00
|
|
|
apiUrl = '';
|
2017-06-13 14:09:18 +02:00
|
|
|
}
|
|
|
|
this.apiUrl = apiUrl;
|
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(token)) {
|
|
|
|
token = null;
|
|
|
|
}
|
|
|
|
this.token = token;
|
|
|
|
|
2017-06-26 18:20:34 +02:00
|
|
|
if (GameLib.Utils.UndefinedOrNull(apiUploadUrl)) {
|
|
|
|
console.warn('Need an API Upload URL for a storage system');
|
|
|
|
apiUploadUrl = '';
|
|
|
|
}
|
|
|
|
this.apiUploadUrl = apiUploadUrl;
|
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(onImageLoaded)) {
|
|
|
|
onImageLoaded = null;
|
|
|
|
}
|
|
|
|
this.onImageLoaded = onImageLoaded;
|
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(onImageProgress)) {
|
|
|
|
onImageProgress = null;
|
|
|
|
}
|
|
|
|
this.onImageProgress = onImageProgress;
|
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(onImageError)) {
|
|
|
|
onImageError = null;
|
|
|
|
}
|
|
|
|
this.onImageError = onImageError;
|
|
|
|
|
2017-06-27 13:27:27 +02:00
|
|
|
if (GameLib.Utils.UndefinedOrNull(onComponentLoaded)) {
|
|
|
|
onComponentLoaded = null;
|
|
|
|
}
|
|
|
|
this.onComponentLoaded = onComponentLoaded;
|
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(onComponentProgress)) {
|
|
|
|
onComponentProgress = null;
|
|
|
|
}
|
|
|
|
this.onComponentProgress = onComponentProgress;
|
|
|
|
|
|
|
|
if (GameLib.Utils.UndefinedOrNull(onComponentError)) {
|
|
|
|
onComponentError = null;
|
|
|
|
}
|
|
|
|
this.onComponentError = onComponentError;
|
|
|
|
|
2017-06-19 15:54:02 +02:00
|
|
|
this.loginSubscription = null;
|
2017-06-26 18:20:34 +02:00
|
|
|
this.saveSubscription = null;
|
|
|
|
this.loadSubscription = null;
|
|
|
|
this.loadImageSubscription = null;
|
2017-06-13 14:09:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
GameLib.System.Storage.prototype = Object.create(GameLib.System.prototype);
|
|
|
|
GameLib.System.Storage.prototype.constructor = GameLib.System.Storage;
|
|
|
|
|
2017-06-19 15:54:02 +02:00
|
|
|
GameLib.System.Storage.prototype.start = function() {
|
|
|
|
|
|
|
|
this.loginSubscription = this.subscribe(
|
|
|
|
GameLib.Event.LOGGED_IN,
|
|
|
|
function(data) {
|
|
|
|
this.token = data.token;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
this.saveSubscription = this.subscribe(
|
2017-06-19 21:35:51 +02:00
|
|
|
GameLib.Event.SAVE_COMPONENT,
|
2017-06-19 15:54:02 +02:00
|
|
|
this.save
|
|
|
|
);
|
|
|
|
|
|
|
|
this.loadSubscription = this.subscribe(
|
2017-06-19 21:35:51 +02:00
|
|
|
GameLib.Event.LOAD_COMPONENT,
|
2017-06-19 15:54:02 +02:00
|
|
|
this.load
|
2017-06-26 18:20:34 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
this.loadImageSubscription = this.subscribe(
|
|
|
|
GameLib.Event.LOAD_IMAGE,
|
|
|
|
this.loadImage
|
|
|
|
);
|
2017-06-19 15:54:02 +02:00
|
|
|
};
|
2017-06-13 14:09:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 'Saves' data to baseURL
|
|
|
|
*/
|
|
|
|
GameLib.System.Storage.prototype.save = function(data) {
|
|
|
|
|
|
|
|
if (typeof XMLHttpRequest === 'undefined') {
|
|
|
|
console.log('Implement server side save here');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
|
|
|
|
xhr.open(
|
|
|
|
'POST',
|
|
|
|
this.apiUrl + '/component/create'
|
|
|
|
);
|
|
|
|
|
|
|
|
xhr.setRequestHeader("Accept", "application/json");
|
|
|
|
xhr.setRequestHeader("Content-Type", "application/json");
|
|
|
|
|
|
|
|
xhr.onreadystatechange = function () {
|
|
|
|
if (this.readyState === 4) {
|
|
|
|
try {
|
|
|
|
var response = JSON.parse(this.responseText)
|
|
|
|
} catch (error) {
|
|
|
|
GameLib.Event.Emit(
|
2017-06-19 21:35:51 +02:00
|
|
|
GameLib.Event.SAVE_COMPONENT_ERROR,
|
2017-06-13 14:09:18 +02:00
|
|
|
{
|
|
|
|
message: this.responseText
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (response.result === 'success') {
|
|
|
|
GameLib.Event.Emit(
|
2017-06-19 21:35:51 +02:00
|
|
|
GameLib.Event.COMPONENT_SAVED,
|
2017-06-13 14:09:18 +02:00
|
|
|
{
|
|
|
|
message: response.message || 'Successfully saved the component'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
GameLib.Event.Emit(
|
2017-06-19 21:35:51 +02:00
|
|
|
GameLib.Event.SAVE_COMPONENT_ERROR,
|
2017-06-13 14:09:18 +02:00
|
|
|
{
|
|
|
|
message: response.message || 'The server responded but failed to save the component'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
xhr.send(JSON.stringify({
|
|
|
|
component : data,
|
|
|
|
session : this.token
|
|
|
|
}));
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
GameLib.System.Storage.prototype.loadComponent = function(toProcess, includeDependencies) {
|
2017-06-13 14:09:18 +02:00
|
|
|
|
2017-06-27 13:27:27 +02:00
|
|
|
var loaded = [];
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var loading = [];
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
toProcess.map(function(id) {
|
|
|
|
if (loading.indexOf(id) === -1) {
|
|
|
|
loading.push(id);
|
|
|
|
}
|
|
|
|
});
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-30 12:06:55 +02:00
|
|
|
return function download(id, parentEntity) {
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var onComponentLoaded = this.onComponentLoaded;
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var onComponentProgress = this.onComponentProgress;
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var onComponentError = this.onComponentError;
|
2017-06-27 13:27:27 +02:00
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
xhr.onload = function(__system) {
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
return function () {
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
try {
|
|
|
|
var object = JSON.parse(this.responseText);
|
|
|
|
} catch (error) {
|
2017-06-19 21:35:51 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
if (onComponentError) {
|
|
|
|
onComponentError(error);
|
2017-06-27 13:27:27 +02:00
|
|
|
}
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
GameLib.Event.Emit(
|
|
|
|
GameLib.Event.LOAD_COMPONENT_ERROR,
|
|
|
|
{
|
|
|
|
error: error
|
|
|
|
}
|
|
|
|
);
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
return;
|
2017-06-19 21:35:51 +02:00
|
|
|
}
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
if (object.result !== 'success') {
|
|
|
|
|
|
|
|
if (onComponentError) {
|
2017-06-29 15:23:50 +02:00
|
|
|
onComponentError(id, object);
|
2017-06-27 13:27:27 +02:00
|
|
|
}
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
GameLib.Event.Emit(
|
|
|
|
GameLib.Event.LOAD_COMPONENT_ERROR,
|
2017-06-29 15:23:50 +02:00
|
|
|
{error : object}
|
2017-06-28 17:09:06 +02:00
|
|
|
);
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
/**
|
|
|
|
* Now we need to create the runtime component - this happens systematically.
|
|
|
|
* First, we create an API object from the Object, then a Runtime object from the API object
|
|
|
|
* Each component has a function 'FromObject' which essentially does this for you
|
|
|
|
*/
|
|
|
|
object.component.map(function (component) {
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var componentName = GameLib.Component.GetComponentName(component.componentType);
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var componentClass = eval(componentName);
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var fn = componentClass['FromObject'];
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
var runtimeComponent = null;
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
if (component.componentType === GameLib.Component.COMPONENT_ENTITY) {
|
|
|
|
runtimeComponent = fn(component, GameLib.EntityManager.Instance);
|
2017-06-30 12:06:55 +02:00
|
|
|
runtimeComponent.parentEntity = parentEntity;
|
|
|
|
parentEntity = runtimeComponent;
|
2017-06-28 17:09:06 +02:00
|
|
|
} else {
|
2017-06-30 14:20:22 +02:00
|
|
|
try {
|
|
|
|
runtimeComponent = fn(__system.graphics, component);
|
|
|
|
} catch (error) {
|
|
|
|
runtimeComponent = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!runtimeComponent) {
|
|
|
|
try {
|
|
|
|
runtimeComponent = fn(__system.physics, component);
|
|
|
|
} catch (error) {
|
|
|
|
runtimeComponent = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!runtimeComponent) {
|
|
|
|
throw new Error('Could not create a runtime component: ', component);
|
|
|
|
}
|
|
|
|
|
2017-06-30 12:06:55 +02:00
|
|
|
runtimeComponent.parentEntity = parentEntity;
|
2017-06-28 17:09:06 +02:00
|
|
|
}
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
if (runtimeComponent instanceof GameLib.D3.Image) {
|
|
|
|
GameLib.Event.Emit(
|
|
|
|
GameLib.Event.LOAD_IMAGE,
|
|
|
|
{
|
|
|
|
image : runtimeComponent
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 18:40:12 +02:00
|
|
|
loaded.push(runtimeComponent);
|
2017-06-28 17:09:06 +02:00
|
|
|
|
|
|
|
if (includeDependencies) {
|
|
|
|
/**
|
|
|
|
* Before we announce the creation of this component, we should get
|
|
|
|
* a list of all dependencies of this component, because once we announce
|
|
|
|
* the creation of this component - the linking system will attempt to resolve
|
|
|
|
* all dependencies
|
|
|
|
*/
|
|
|
|
var dependencies = runtimeComponent.getDependencies();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Now - we should systematically check if we have the dependency already
|
|
|
|
* loaded (in our runtime environment) - if we have - we just ignore loading this dependency (for now)
|
2017-06-30 09:50:29 +02:00
|
|
|
*
|
|
|
|
* We don't override runtime versions of the same component in the database because the user
|
|
|
|
* could be working with it and it should be the latest version.
|
2017-06-28 17:09:06 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
dependencies = dependencies.reduce(
|
|
|
|
function (result, dependency) {
|
|
|
|
|
2017-06-30 09:50:29 +02:00
|
|
|
if (GameLib.EntityManager.Instance.findComponentById(dependency)) {
|
|
|
|
/**
|
|
|
|
* Don't add the dependency
|
|
|
|
*/
|
|
|
|
} else {
|
2017-06-28 17:09:06 +02:00
|
|
|
result.push(dependency);
|
2017-06-27 13:27:27 +02:00
|
|
|
}
|
2017-06-28 17:09:06 +02:00
|
|
|
|
2017-06-27 13:27:27 +02:00
|
|
|
return result;
|
|
|
|
},
|
2017-06-28 17:09:06 +02:00
|
|
|
[]
|
2017-06-27 13:27:27 +02:00
|
|
|
);
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
/**
|
|
|
|
* Also check if we did not already load this component quite recently
|
|
|
|
*/
|
|
|
|
dependencies = dependencies.reduce(
|
|
|
|
function (result, dependency) {
|
|
|
|
|
|
|
|
var found = loaded.reduce(
|
2017-06-28 18:40:12 +02:00
|
|
|
function (result, component) {
|
|
|
|
if (component.id === dependency) {
|
2017-06-28 17:09:06 +02:00
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
},
|
|
|
|
false
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
result.push(dependency);
|
2017-06-27 13:27:27 +02:00
|
|
|
}
|
2017-06-28 17:09:06 +02:00
|
|
|
|
2017-06-27 13:27:27 +02:00
|
|
|
return result;
|
|
|
|
},
|
2017-06-28 17:09:06 +02:00
|
|
|
[]
|
2017-06-27 13:27:27 +02:00
|
|
|
);
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
/**
|
|
|
|
* We should now check our 'loading' list and add all dependencies which are not already in there
|
|
|
|
*/
|
|
|
|
dependencies.map(
|
|
|
|
function (dependency) {
|
|
|
|
if (loading.indexOf(dependency) === -1) {
|
|
|
|
loading.push(dependency);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
/**
|
|
|
|
* Ok - now we have a super good idea of which components still need to load -
|
|
|
|
* they live in the 'loading' list.
|
|
|
|
*
|
|
|
|
* At this point - the runtime components are created, but they are not ready
|
|
|
|
* to be used. They may have dependencies to other components, which still need
|
|
|
|
* to load, or may never be loaded.
|
|
|
|
*
|
|
|
|
* It is however safe, to announce, that we created the
|
|
|
|
* runtime version of it, however it could still have some dependencies.
|
|
|
|
*
|
|
|
|
* The Linking system will then kick in and try to resolve all dependencies
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (onComponentLoaded) {
|
|
|
|
onComponentLoaded(runtimeComponent);
|
|
|
|
}
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
GameLib.Event.Emit(
|
|
|
|
GameLib.Event.COMPONENT_CREATED,
|
|
|
|
{
|
|
|
|
component: runtimeComponent
|
2017-06-27 13:27:27 +02:00
|
|
|
}
|
2017-06-28 17:09:06 +02:00
|
|
|
);
|
|
|
|
|
2017-06-28 18:40:12 +02:00
|
|
|
var toProcess = GameLib.Utils.Difference(loaded.map(function(component){return component.id}), loading);
|
2017-06-28 17:09:06 +02:00
|
|
|
|
|
|
|
if (toProcess.length === 0) {
|
|
|
|
GameLib.Event.Emit(
|
|
|
|
GameLib.Event.COMPONENT_DOWNLOAD_COMPLETE,
|
|
|
|
{
|
|
|
|
loaded: loaded
|
|
|
|
}
|
|
|
|
)
|
|
|
|
} else {
|
2017-06-30 12:06:55 +02:00
|
|
|
download.bind(__system)(toProcess.pop(), parentEntity);
|
2017-06-13 14:09:18 +02:00
|
|
|
}
|
2017-06-28 17:09:06 +02:00
|
|
|
});
|
|
|
|
};
|
|
|
|
}(this);
|
2017-06-27 13:27:27 +02:00
|
|
|
|
|
|
|
xhr.onprogress = function(__id) {
|
|
|
|
return function (progressEvent) {
|
|
|
|
|
|
|
|
var progress = 0;
|
|
|
|
|
|
|
|
if (progressEvent.total !== 0) {
|
|
|
|
progress = Number(progressEvent.loaded / progressEvent.total);
|
|
|
|
progress *= 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (onComponentProgress) {
|
|
|
|
onComponentProgress(__id, progress)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}(id);
|
|
|
|
|
|
|
|
xhr.onerror = function(__id) {
|
|
|
|
return function (error) {
|
|
|
|
console.warn('component load failed for component ID ' + __id);
|
|
|
|
if (onComponentError) {
|
|
|
|
onComponentError(__id, error)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}(id);
|
|
|
|
|
|
|
|
xhr.open(
|
|
|
|
'GET',
|
|
|
|
this.apiUrl + '/component/load/' + id
|
|
|
|
);
|
|
|
|
|
|
|
|
xhr.send();
|
2017-06-28 17:09:06 +02:00
|
|
|
}.bind(this);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 'Loads' data from a url
|
|
|
|
*/
|
|
|
|
GameLib.System.Storage.prototype.load = function(data) {
|
|
|
|
|
|
|
|
if (typeof XMLHttpRequest === 'undefined') {
|
|
|
|
console.log('Implement server side load here');
|
|
|
|
return;
|
2017-06-27 13:27:27 +02:00
|
|
|
}
|
|
|
|
|
2017-06-28 17:09:06 +02:00
|
|
|
if (data.ids && data.ids.length > 0) {
|
2017-06-30 12:06:55 +02:00
|
|
|
this.loadComponent(data.ids, data.includeDependencies)(data.ids[0], null);
|
2017-06-28 17:09:06 +02:00
|
|
|
} else {
|
|
|
|
console.log('No components selected');
|
|
|
|
}
|
2017-06-27 13:27:27 +02:00
|
|
|
|
2017-06-19 15:54:02 +02:00
|
|
|
};
|
|
|
|
|
2017-06-26 18:20:34 +02:00
|
|
|
GameLib.System.Storage.prototype.loadImage = function(data) {
|
|
|
|
|
|
|
|
console.log('loading image : ' + data.image.name);
|
|
|
|
|
|
|
|
var onLoaded = this.onImageLoaded;
|
|
|
|
|
2017-06-27 13:27:27 +02:00
|
|
|
var onProgress = this.onImageProgress;
|
2017-06-26 18:20:34 +02:00
|
|
|
|
|
|
|
var onError = this.onImageError;
|
|
|
|
|
|
|
|
var image = data.image;
|
|
|
|
|
|
|
|
var url = this.apiUploadUrl + image.path + '?ts=' + Date.now();
|
|
|
|
|
|
|
|
var preflight = new XMLHttpRequest();
|
|
|
|
|
|
|
|
preflight.withCredentials = true;
|
|
|
|
|
|
|
|
preflight.open(
|
|
|
|
'OPTIONS',
|
|
|
|
url
|
|
|
|
);
|
|
|
|
|
|
|
|
preflight.setRequestHeader('Content-Type', 'application/json');
|
|
|
|
|
|
|
|
preflight.onload = function() {
|
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
|
|
|
|
xhr.withCredentials = true;
|
|
|
|
|
|
|
|
xhr.open('GET', url);
|
|
|
|
|
|
|
|
xhr.setRequestHeader('Content-Type', image.contentType);
|
|
|
|
|
|
|
|
xhr.responseType = 'blob';
|
|
|
|
|
|
|
|
xhr.onload = function() {
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (this.response.type !== 'application/json') {
|
|
|
|
var url = window.URL.createObjectURL(this.response);
|
|
|
|
} else {
|
|
|
|
if (onError) {
|
|
|
|
onError(image, {message:'Image not found'});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
if (onError) {
|
|
|
|
onError(image, {message:'Image not found'});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var img = document.createElement('img');
|
|
|
|
|
|
|
|
img.onload = function() {
|
|
|
|
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
|
|
|
|
image.instance = img;
|
2017-06-28 17:09:06 +02:00
|
|
|
image.loaded = true;
|
2017-06-26 18:20:34 +02:00
|
|
|
image.publish(
|
|
|
|
GameLib.Event.IMAGE_INSTANCE_CREATED,
|
|
|
|
{
|
|
|
|
image: image
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
if (onLoaded) {
|
|
|
|
onLoaded(image);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
img.src = url;
|
|
|
|
};
|
|
|
|
|
|
|
|
xhr.onprogress = function(progressEvent) {
|
|
|
|
|
|
|
|
var progress = 0;
|
|
|
|
|
|
|
|
if (progressEvent.total !== 0) {
|
|
|
|
progress = Number(progressEvent.loaded / progressEvent.total);
|
|
|
|
progress *= 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (onProgress) {
|
|
|
|
onProgress(image, progress);
|
|
|
|
}
|
|
|
|
|
|
|
|
image.size = progressEvent.total;
|
|
|
|
};
|
|
|
|
|
|
|
|
xhr.onerror = function(error) {
|
|
|
|
console.warn('image load failed for image ' + image.name);
|
|
|
|
if (onError) {
|
|
|
|
onError(image, error)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
xhr.send();
|
|
|
|
};
|
|
|
|
|
|
|
|
preflight.onerror = function(error) {
|
|
|
|
console.warn('image pre-flight request failed for image ' + image.name);
|
|
|
|
if (onError) {
|
|
|
|
onError(image, error);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
preflight.send();
|
|
|
|
};
|
|
|
|
|
2017-06-19 15:54:02 +02:00
|
|
|
GameLib.System.Storage.prototype.stop = function() {
|
|
|
|
this.loginSubscription.remove();
|
|
|
|
this.loadSubscription.remove();
|
|
|
|
this.saveSubscription.remove();
|
2017-06-26 18:20:34 +02:00
|
|
|
this.loadImageSubscription.remove();
|
2017-06-19 15:54:02 +02:00
|
|
|
};
|
|
|
|
|