Progress on thang property serialization
There is a bug where thang properties aren’t updated when simulating forward
This commit is contained in:
parent
c9ea301b29
commit
717651d6ff
3 changed files with 95 additions and 36 deletions
app
|
@ -86,24 +86,83 @@ var GoalManager = self.require('lib/world/GoalManager');
|
||||||
self.getCurrentFrame = function getCurrentFrame(args) { return self.world.frames.length; };
|
self.getCurrentFrame = function getCurrentFrame(args) { return self.world.frames.length; };
|
||||||
|
|
||||||
//optimize this later
|
//optimize this later
|
||||||
self.currentUserCodeMap = {};
|
self.currentUserCodeMapCopy = {};
|
||||||
self.currentWorldFrame = 0;
|
self.currentWorldFrame = 0;
|
||||||
|
|
||||||
self.runWorldUntilFrame = function runWorldUntilFrame(args) {
|
self.maxSerializationDepth = 3;
|
||||||
console.log("Running world until frame " + args.frame);
|
self.serializeProperty = function serializeProperty(prop, depth) {
|
||||||
|
var typeOfProperty = typeof(prop);
|
||||||
|
if (["undefined","boolean","number","string","xml"].indexOf(typeOfProperty) > -1 || prop === null || prop instanceof Date || prop instanceof String)
|
||||||
|
return prop;
|
||||||
|
else if (typeOfProperty === "function") return "<function>";
|
||||||
|
else if (prop instanceof Array)
|
||||||
|
{
|
||||||
|
if (depth >= self.maxSerializationDepth) return Object.keys(prop);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var newProps = [];
|
||||||
|
for(var i= 0, arrayLength=prop.length; i < arrayLength; i++)
|
||||||
|
newProps[i] = self.serializeProperty(prop[i],depth + 1);
|
||||||
|
return newProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (prop.hasOwnProperty("id"))
|
||||||
|
{
|
||||||
|
return prop.id;
|
||||||
|
}
|
||||||
|
else if (prop.hasOwnProperty('serialize'))
|
||||||
|
{
|
||||||
|
return prop.serialize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newObject = {};
|
||||||
|
for (var key in prop)
|
||||||
|
{
|
||||||
|
if (prop.hasOwnProperty(key))
|
||||||
|
{
|
||||||
|
if (depth >= self.maxSerializationDepth)
|
||||||
|
{
|
||||||
|
newObject[key] = "DEPTH EXCEEDED";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newObject[key] = self.serializeProperty(prop[key], depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newObject;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.retrieveThangPropertyFromFrame = function retrieveThangPropertyFromFrame(args) {
|
||||||
|
var thangID = args.thangID;
|
||||||
|
var prop = args.prop;
|
||||||
|
var retrieveProperty = function retrieveProperty()
|
||||||
|
{
|
||||||
|
var unserializedProperty = self.world.thangMap[thangID][prop];
|
||||||
|
self.postMessage({type: 'debug-value-return', serialized: self.serializeProperty(unserializedProperty,0)});
|
||||||
|
};
|
||||||
|
self.setupWorldToRunUntilFrame(args);
|
||||||
|
self.world.loadFramesUntilFrame(args.frame, retrieveProperty, self.onWorldError, self.onWorldLoadProgress);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setupWorldToRunUntilFrame = function setupWorldToRunUntilFrame(args) {
|
||||||
self.postedErrors = {};
|
self.postedErrors = {};
|
||||||
self.t0 = new Date();
|
self.t0 = new Date();
|
||||||
self.firstWorld = args.firstWorld;
|
self.firstWorld = args.firstWorld;
|
||||||
self.postedErrors = false;
|
self.postedErrors = false;
|
||||||
self.logsLogged = 0;
|
self.logsLogged = 0;
|
||||||
|
|
||||||
var userCodeMapHasChanged = _.isEqual(self.currentUserCodeMap, args.userCodeMap);
|
var stringifiedUserCodeMap = JSON.stringify(args.userCodeMap);
|
||||||
self.currentUserCodeMap = args.userCodeMap;
|
var userCodeMapHasChanged = ! _.isEqual(self.currentUserCodeMapCopy, stringifiedUserCodeMap);
|
||||||
console.log("User codemap has changed: " + userCodeMapHasChanged);
|
self.currentUserCodeMapCopy = stringifiedUserCodeMap;
|
||||||
if (!self.world || userCodeMapHasChanged || args.frame < self.currentWorldFrame)
|
if (!self.world || userCodeMapHasChanged || args.frame < self.currentWorldFrame)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self.world = new World(args.worldName, self.currentUserCodeMap);
|
self.world = new World(args.worldName, args.userCodeMap);
|
||||||
if(args.level)
|
if(args.level)
|
||||||
self.world.loadFromLevel(args.level, true);
|
self.world.loadFromLevel(args.level, true);
|
||||||
self.goalManager = new GoalManager(self.world);
|
self.goalManager = new GoalManager(self.world);
|
||||||
|
@ -118,37 +177,18 @@ self.runWorldUntilFrame = function runWorldUntilFrame(args) {
|
||||||
}
|
}
|
||||||
Math.random = self.world.rand.randf; // so user code is predictable
|
Math.random = self.world.rand.randf; // so user code is predictable
|
||||||
}
|
}
|
||||||
|
|
||||||
self.world.totalFrames = args.frame; //hack to work around error checking
|
self.world.totalFrames = args.frame; //hack to work around error checking
|
||||||
|
|
||||||
self.world.loadFramesUntilFrame(args.frame, self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress);
|
|
||||||
self.currentWorldFrame = args.frame;
|
self.currentWorldFrame = args.frame;
|
||||||
|
};
|
||||||
|
self.runWorldUntilFrame = function runWorldUntilFrame(args) {
|
||||||
|
self.setupWorldToRunUntilFrame(args);
|
||||||
|
self.world.loadFramesUntilFrame(args.frame, self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onWorldLoaded = function onWorldLoaded() {
|
self.onWorldLoaded = function onWorldLoaded() {
|
||||||
var t1 = new Date();
|
console.log("World loaded!");
|
||||||
var diff = t1 - self.t0;
|
|
||||||
var transferableSupported = self.transferableSupported();
|
|
||||||
try {
|
|
||||||
var serialized = self.world.serialize();
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
console.log("World serialization error:", error.toString() + "\n" + error.stack || error.stackTrace);
|
|
||||||
}
|
|
||||||
var t2 = new Date();
|
|
||||||
//console.log("About to transfer", serialized.serializedWorld.trackedPropertiesPerThangValues, serialized.transferableObjects);
|
|
||||||
try {
|
|
||||||
if(transferableSupported)
|
|
||||||
self.postMessage({type: 'new-debug-world', serialized: serialized.serializedWorld, goalStates: self.goalManager.getGoalStates()}, serialized.transferableObjects);
|
|
||||||
else
|
|
||||||
self.postMessage({type: 'new-debug-world', serialized: serialized.serializedWorld, goalStates: self.goalManager.getGoalStates()});
|
|
||||||
}
|
|
||||||
catch(error) {
|
|
||||||
console.log("World delivery error:", error.toString() + "\n" + error.stack || error.stackTrace);
|
|
||||||
}
|
|
||||||
var t3 = new Date();
|
|
||||||
console.log("And it was so: (" + (diff / self.world.totalFrames).toFixed(3) + "ms per frame,", self.world.totalFrames, "frames)\nSimulation :", diff + "ms \nSerialization:", (t2 - t1) + "ms\nDelivery :", (t3 - t2) + "ms");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onWorldError = function onWorldError(error) {
|
self.onWorldError = function onWorldError(error) {
|
||||||
|
|
|
@ -75,7 +75,9 @@ module.exports = class God
|
||||||
console.log "New Debug world!"
|
console.log "New Debug world!"
|
||||||
when 'console-log'
|
when 'console-log'
|
||||||
console.log "|" + @id + "'s " + @id + "|", event.data.args...
|
console.log "|" + @id + "'s " + @id + "|", event.data.args...
|
||||||
|
when 'debug-value-return'
|
||||||
|
console.log event.data.serialized
|
||||||
|
|
||||||
getAngel: ->
|
getAngel: ->
|
||||||
freeAngel = null
|
freeAngel = null
|
||||||
for angel in @angels
|
for angel in @angels
|
||||||
|
@ -137,6 +139,20 @@ module.exports = class God
|
||||||
firstWorld: @firstWorld
|
firstWorld: @firstWorld
|
||||||
goals: @goalManager?.getGoals()
|
goals: @goalManager?.getGoals()
|
||||||
frame: frame
|
frame: frame
|
||||||
|
|
||||||
|
retrieveThangPropertyFromFrame: (thang, prop, frame) ->
|
||||||
|
@debugWorker.postMessage
|
||||||
|
func: 'retrieveThangPropertyFromFrame'
|
||||||
|
args:
|
||||||
|
worldName: @level.name
|
||||||
|
userCodeMap: @currentUserCodeMap
|
||||||
|
level: @level
|
||||||
|
firstWorld: @firstWorld
|
||||||
|
goals: @goalManager?.getGoals()
|
||||||
|
frame: frame
|
||||||
|
thangID: thang
|
||||||
|
prop: prop
|
||||||
|
|
||||||
|
|
||||||
getDebugWorldCurrentFrame: ->
|
getDebugWorldCurrentFrame: ->
|
||||||
@debugWorker.postMessage
|
@debugWorker.postMessage
|
||||||
|
|
|
@ -8,6 +8,11 @@ WorldScriptNote = require './world_script_note'
|
||||||
{now, consolidateThangs, typedArraySupport} = require './world_utils'
|
{now, consolidateThangs, typedArraySupport} = require './world_utils'
|
||||||
Component = require 'lib/world/component'
|
Component = require 'lib/world/component'
|
||||||
System = require 'lib/world/system'
|
System = require 'lib/world/system'
|
||||||
|
#adding this for the debug worker
|
||||||
|
serializedClasses =
|
||||||
|
Thang: require "lib/world/thang"
|
||||||
|
Vector: require "lib/world/vector"
|
||||||
|
Rectangle: require "lib/world/rectangle"
|
||||||
|
|
||||||
PROGRESS_UPDATE_INTERVAL = 200
|
PROGRESS_UPDATE_INTERVAL = 200
|
||||||
DESERIALIZATION_INTERVAL = 20
|
DESERIALIZATION_INTERVAL = 20
|
||||||
|
@ -40,7 +45,6 @@ module.exports = class World
|
||||||
else if frameIndex
|
else if frameIndex
|
||||||
frame = frames[frameIndex - 1].getNextFrame()
|
frame = frames[frameIndex - 1].getNextFrame()
|
||||||
frames.push frame
|
frames.push frame
|
||||||
console.log "Pushed frame #{frameIndex}"
|
|
||||||
else
|
else
|
||||||
frame = frames[0]
|
frame = frames[0]
|
||||||
@age = frameIndex * @dt
|
@age = frameIndex * @dt
|
||||||
|
@ -278,7 +282,6 @@ module.exports = class World
|
||||||
|
|
||||||
serialize: ->
|
serialize: ->
|
||||||
# Code hotspot; optimize it
|
# Code hotspot; optimize it
|
||||||
console.log("Frames length: #{@frames.length}, total frames: #{@totalFrames}")
|
|
||||||
if @frames.length < @totalFrames then throw new Error("World Should Be Over Before Serialization")
|
if @frames.length < @totalFrames then throw new Error("World Should Be Over Before Serialization")
|
||||||
[transferableObjects, nontransferableObjects] = [0, 0]
|
[transferableObjects, nontransferableObjects] = [0, 0]
|
||||||
o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}, trackedProperties: {}}
|
||||||
|
|
Reference in a new issue