From 0a083c070f9c00b719431da0f1d07e429b7b6587 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 30 Oct 2015 20:21:53 -0700 Subject: [PATCH 01/23] color busters cooperative game --- examples/color_busters/colorBusterWand.js | 226 ++++++++++++++++++ .../color_busters/createColorBusterCubes.js | 89 +++++++ .../color_busters/createColorBusterWand.js | 55 +++++ 3 files changed, 370 insertions(+) create mode 100644 examples/color_busters/colorBusterWand.js create mode 100644 examples/color_busters/createColorBusterCubes.js create mode 100644 examples/color_busters/createColorBusterWand.js diff --git a/examples/color_busters/colorBusterWand.js b/examples/color_busters/colorBusterWand.js new file mode 100644 index 0000000000..26948da91b --- /dev/null +++ b/examples/color_busters/colorBusterWand.js @@ -0,0 +1,226 @@ +(function() { + + //seconds that the combination lasts + var COMBINED_COLOR_DURATION = 10; + + var INDICATOR_OFFSET_UP = 0.5; + + var REMOVE_CUBE_SOUND_URL = ''; + var COMBINE_COLORS_SOUND_URL = ''; + + var _this; + + function ColorWand() { + _this = this; + }; + + ColorBusterWand.prototype = { + combinedColorsTimer: null, + + preload: function(entityID) { + print("preload"); + this.entityID = entityID; + this.REMOVE_CUBE_SOUND = SoundCache.getSound(REMOVE_CUBE_SOUND_URL); + this.COMBINE_COLORS_SOUND = SoundCache.getSound(COMBINE_COLORS_SOUND_URL); + + }, + + entityCollisionWithEntity: function(me, otherEntity, collision) { + + var otherProperties = Entities.getEntityProperties(otherEntity, ["name", "userData"]); + var myProperties = Entities.getEntityProperties(otherEntity, ["userData"]); + var myUserData = JSON.parse(myProperties.userData); + var otherUserData = JSON.parse(otherProperties.userData); + + if (otherProperties.name === 'Hifi-ColorBusterWand') { + if (otherUserData.hifiColorBusterWandKey.colorLocked !== true && myUserData.hifiColorBusterWandKey.colorLocked !== true) { + if (otherUserData.hifiColorBusterWandKey.originalColorName === myUserData.hifiColorBusterWandKey.originalColorName) { + return; + } else { + this.combineColorsWithOtherWand(otherUserData.hifiColorBusterWandKey.originalColorName, myUserData.hifiColorBusterWandKey.originalColorName); + } + } + } + + if (otherProperties.name === 'Hifi-ColorBusterCube') { + if (otherUserData.hifiColorBusterCubeKey.originalColorName === myUserData.hifiColorBusterWandKey.currentColor) { + removeCubeOfSameColor(otherEntity); + } + + } + }, + + combineColorsWithOtherWand: function(otherColor, myColor) { + var newColor; + + if ((otherColor === 'red' && myColor == 'yellow') || (myColor === 'red' && otherColor === 'yellow')) { + //orange + newColor = 'orange'; + } + + if ((otherColor === 'red' && myColor == 'blue') || (myColor === 'red' && otherColor === 'blue')) { + //violet + newColor = 'violet'; + } + + if ((otherColor === 'blue' && myColor == 'yellow') || (myColor === 'blue' && otherColor === 'yellow')) { + //green. + newColor = 'green'; + } + + _this.combinedColorsTimer = Script.setTimeout(function() { + _this.resetToOriginalColor(myColor); + _this.combinedColorsTimer = null; + }, COMBINED_COLOR_DURATION * 1000); + + setEntityCustomData(hifiColorWandKey, this.entityID, { + owner: MyAvatar.sessionUUID, + currentColor: newColor + originalColorName: myColor, + colorLocked: false + }); + + _this.setCurrentColor(newColor); + + }, + + setCurrentColor: function(newColor) { + + var color; + + if (newColor === 'orange') { + color = { + red: 255, + green: 165, + blue: 0 + }; + } + + if (newColor === 'violet') { + color = { + red: 128, + green: 0, + blue: 128 + }; + } + + if (newColor === 'green') { + color = { + red: 0, + green: 255, + blue: 0 + }; + } + + if (newColor === 'red') { + color = { + red: 255, + green: 0, + blue: 0 + }; + } + + if (newColor === 'yellow') { + color = { + red: 255, + green: 255, + blue: 0 + }; + } + + if (newColor === 'blue') { + color = { + red: 0, + green: 0, + blue: 255 + }; + } + + Entities.editEntity(this.colorIndicator, { + color: color + }) + }, + + resetToOriginalColor: function(myColor) { + setEntityCustomData(hifiColorWandKey, this.entityID, { + owner: MyAvatar.sessionUUID, + currentColor: myColor + originalColorName: myColor, + colorLocked: true + }); + + this.setCurrentColor(myColor); + }, + + removeCubeOfSameColor: function(cube) { + Entities.callEntityMethod(cube, 'cubeEnding'); + Entities.deleteEntity(cube); + }, + + startNearGrab: function() { + this.currentProperties = Entities.getEntityProperties(this.entityID); + this.createColorIndicator(); + }, + + continueNearGrab: function() { + this.currentProperties = Entities.getEntityProperties(this.entityID); + this.updateColorIndicatorLocation(); + }, + + releaseGrab: function() { + this.deleteEntity(this.colorIndicator); + if (this.combinedColorsTimer !== null) { + Script.clearTimeout(this.combinedColorsTimer); + } + + }, + + createColorIndicator: function() { + var properties = { + name: 'Hifi-ColorBusterIndicator', + type: 'Box', + dimensions: COLOR_INDICATOR_DIMENSIONS, + color: this.currentProperties.position, + position: this.currentProperties.position + } + + this.colorIndicator = Entities.addEntity(properties); + }, + + updateColorIndicatorLocation: function() { + + var position; + + var upVector = Quat.getUp(this.currentProperties.rotation); + var indicatorVector = Vec3.multiply(upVector, INDICATOR_OFFSET_UP); + position = Vec3.sum(this.currentProperties.position, indicatorVector); + + var properties = { + position: position, + rotation: this.currentProperties.rotation + } + + Entities.editEntity(this.colorIndicator, properties); + }, + + + playSoundAtCurrentPosition: function(removeCubeSound) { + var position = Entities.getEntityProperties(this.entityID, "position").position; + + var audioProperties = { + volume: 0.25, + position: position + }; + + if (removeCubeSound) { + Audio.playSound(this.REMOVE_CUBE_SOUND, audioProperties); + } else { + Audio.playSound(this.COMBINE_COLORS_SOUND, audioProperties); + } + }, + + + }; + + return new ColorBusterWand(); +}); \ No newline at end of file diff --git a/examples/color_busters/createColorBusterCubes.js b/examples/color_busters/createColorBusterCubes.js new file mode 100644 index 0000000000..ad7b8b5307 --- /dev/null +++ b/examples/color_busters/createColorBusterCubes.js @@ -0,0 +1,89 @@ +var CUBE_DIMENSIONS = { + x: 1, + y: 1, + z: 1 +}; + +var NUMBER_OF_CUBES_PER_SIDE: 20; + +var STARTING_CORNER_POSITION = { + x: 0, + y: 0, + z: 0 +} + +var STARTING_COLORS = [ + ['red', { + red: 255, + green: 0, + blue: 0 + }], + ['yellow', { + red: 255, + green: 255, + blue: 0 + }], + ['blue', { + red: 0, + green: 0, + blue: 255 + }], + ['orange', { + red: 255, + green: 165, + blue: 0 + }], + ['violet', { + red: 128, + green: 0, + blue: 128 + }], + ['green', { + red: 0, + green: 255, + blue: 0 + }] +] + +function chooseStartingColor() { + var startingColor = STARTING_COLORS[Math.floor(Math.random() * STARTING_COLORS.length)]; + return startingColor +} + +function createColorBusterCube(row, column, vertical) { + + var startingColor = chooseStartingColor(); + var colorBusterCubeProperties = { + name: 'Hifi-ColorBusterWand', + type: 'Model', + url: COLOR_WAND_MODEL_URL, + dimensions: COLOR_WAND_DIMENSIONS, + position: { + x: row, + y: vertical, + z: column + } + userData: JSON.stringify({ + hifiColorBusterCubeKey: { + originalColorName: startingColor[0], + + } + }) + }; + + return Entities.addEntity(colorBusterCubeProperties); +} + +function createBoard() { + var vertical; + for (vertical = 0; vertical === NUMBER_OF_CUBES_PER_SIDE) { + var row; + var column; + //create a single layer + for (row = 0; row === NUMBER_OF_CUBES_PER_SIDE; row++) { + for (column = 0; column === NUMBER_OF_CUBES_PER_SIDE; column++) { + this.createColorBusterCube(row, column, vertical) + } + } + } +} \ No newline at end of file diff --git a/examples/color_busters/createColorBusterWand.js b/examples/color_busters/createColorBusterWand.js new file mode 100644 index 0000000000..68e6ecfee5 --- /dev/null +++ b/examples/color_busters/createColorBusterWand.js @@ -0,0 +1,55 @@ +var COLOR_WAND_MODEL_URL = ''; +var COLOR_WAND_DIMENSIONS = { + x: 0, + y: 0, + z: 0 +}; +var COLOR_WAND_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var STARTING_COLORS = [ + ['red', { + red: 255, + green: 0, + blue: 0 + }], + ['yellow', { + red: 255, + green: 255, + blue: 0 + }], + ['blue', { + red: 0, + green: 0, + blue: 255 + }] +] + +function chooseStartingColor() { + var startingColor = STARTING_COLORS[Math.floor(Math.random() * STARTING_COLORS.length)]; + return startingColor +} + +function createColorBusterWand() { + + var startingColor = chooseStartingColor(); + var colorBusterWandProperties = { + name: 'Hifi-ColorBusterWand', + type: 'Model', + url: COLOR_WAND_MODEL_URL, + dimensions: COLOR_WAND_DIMENSIONS, + position: COLOR_WAND_START_POSITION, + userData: JSON.stringify({ + hifiColorBusterWandKey: { + owner: MyAvatar.sessionUUID, + currentColor: startingColor[1] + originalColorName: startingColor[0], + colorLocked: false + } + }) + }; + + Entities.addEntity(colorBusterWandProperties); +} \ No newline at end of file From 459b449a7fed46786541bebcd5691a8a3b8bbfbf Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Fri, 30 Oct 2015 20:52:19 -0700 Subject: [PATCH 02/23] rename folder --- examples/{color_busters => color_busters_game}/colorBusterWand.js | 0 .../createColorBusterCubes.js | 0 .../createColorBusterWand.js | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename examples/{color_busters => color_busters_game}/colorBusterWand.js (100%) rename examples/{color_busters => color_busters_game}/createColorBusterCubes.js (100%) rename examples/{color_busters => color_busters_game}/createColorBusterWand.js (100%) diff --git a/examples/color_busters/colorBusterWand.js b/examples/color_busters_game/colorBusterWand.js similarity index 100% rename from examples/color_busters/colorBusterWand.js rename to examples/color_busters_game/colorBusterWand.js diff --git a/examples/color_busters/createColorBusterCubes.js b/examples/color_busters_game/createColorBusterCubes.js similarity index 100% rename from examples/color_busters/createColorBusterCubes.js rename to examples/color_busters_game/createColorBusterCubes.js diff --git a/examples/color_busters/createColorBusterWand.js b/examples/color_busters_game/createColorBusterWand.js similarity index 100% rename from examples/color_busters/createColorBusterWand.js rename to examples/color_busters_game/createColorBusterWand.js From e79ebdb8aa88157fd3be5233ca7fe5a9a865661a Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Sun, 1 Nov 2015 19:47:13 -0800 Subject: [PATCH 03/23] cleanup syntax --- examples/color_busters_game/createColorBusterCubes.js | 6 +++--- examples/color_busters_game/createColorBusterWand.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/color_busters_game/createColorBusterCubes.js b/examples/color_busters_game/createColorBusterCubes.js index ad7b8b5307..2bc14e5a01 100644 --- a/examples/color_busters_game/createColorBusterCubes.js +++ b/examples/color_busters_game/createColorBusterCubes.js @@ -4,7 +4,7 @@ var CUBE_DIMENSIONS = { z: 1 }; -var NUMBER_OF_CUBES_PER_SIDE: 20; +var NUMBER_OF_CUBES_PER_SIDE= 20; var STARTING_CORNER_POSITION = { x: 0, @@ -62,7 +62,7 @@ function createColorBusterCube(row, column, vertical) { x: row, y: vertical, z: column - } + }, userData: JSON.stringify({ hifiColorBusterCubeKey: { originalColorName: startingColor[0], @@ -76,7 +76,7 @@ function createColorBusterCube(row, column, vertical) { function createBoard() { var vertical; - for (vertical = 0; vertical === NUMBER_OF_CUBES_PER_SIDE) { + for (vertical = 0; vertical === NUMBER_OF_CUBES_PER_SIDE;vertical++) { var row; var column; //create a single layer diff --git a/examples/color_busters_game/createColorBusterWand.js b/examples/color_busters_game/createColorBusterWand.js index 68e6ecfee5..4af5306177 100644 --- a/examples/color_busters_game/createColorBusterWand.js +++ b/examples/color_busters_game/createColorBusterWand.js @@ -44,7 +44,7 @@ function createColorBusterWand() { userData: JSON.stringify({ hifiColorBusterWandKey: { owner: MyAvatar.sessionUUID, - currentColor: startingColor[1] + currentColor: startingColor[1], originalColorName: startingColor[0], colorLocked: false } From 15af28337b8494b6e0f8890431c8a8b0f1c545bf Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 2 Nov 2015 16:02:30 -0800 Subject: [PATCH 04/23] add color busters game for testing --- .../createColorBusterCubes.js | 89 ------------ .../createColorBusterWand.js | 55 -------- .../games/color_busters}/colorBusterWand.js | 101 +++++++++----- .../color_busters/createColorBusterCubes.js | 130 ++++++++++++++++++ .../color_busters/createColorBusterWand.js | 99 +++++++++++++ 5 files changed, 299 insertions(+), 175 deletions(-) delete mode 100644 examples/color_busters_game/createColorBusterCubes.js delete mode 100644 examples/color_busters_game/createColorBusterWand.js rename examples/{color_busters_game => example/games/color_busters}/colorBusterWand.js (69%) create mode 100644 examples/example/games/color_busters/createColorBusterCubes.js create mode 100644 examples/example/games/color_busters/createColorBusterWand.js diff --git a/examples/color_busters_game/createColorBusterCubes.js b/examples/color_busters_game/createColorBusterCubes.js deleted file mode 100644 index 2bc14e5a01..0000000000 --- a/examples/color_busters_game/createColorBusterCubes.js +++ /dev/null @@ -1,89 +0,0 @@ -var CUBE_DIMENSIONS = { - x: 1, - y: 1, - z: 1 -}; - -var NUMBER_OF_CUBES_PER_SIDE= 20; - -var STARTING_CORNER_POSITION = { - x: 0, - y: 0, - z: 0 -} - -var STARTING_COLORS = [ - ['red', { - red: 255, - green: 0, - blue: 0 - }], - ['yellow', { - red: 255, - green: 255, - blue: 0 - }], - ['blue', { - red: 0, - green: 0, - blue: 255 - }], - ['orange', { - red: 255, - green: 165, - blue: 0 - }], - ['violet', { - red: 128, - green: 0, - blue: 128 - }], - ['green', { - red: 0, - green: 255, - blue: 0 - }] -] - -function chooseStartingColor() { - var startingColor = STARTING_COLORS[Math.floor(Math.random() * STARTING_COLORS.length)]; - return startingColor -} - -function createColorBusterCube(row, column, vertical) { - - var startingColor = chooseStartingColor(); - var colorBusterCubeProperties = { - name: 'Hifi-ColorBusterWand', - type: 'Model', - url: COLOR_WAND_MODEL_URL, - dimensions: COLOR_WAND_DIMENSIONS, - position: { - x: row, - y: vertical, - z: column - }, - userData: JSON.stringify({ - hifiColorBusterCubeKey: { - originalColorName: startingColor[0], - - } - }) - }; - - return Entities.addEntity(colorBusterCubeProperties); -} - -function createBoard() { - var vertical; - for (vertical = 0; vertical === NUMBER_OF_CUBES_PER_SIDE;vertical++) { - var row; - var column; - //create a single layer - for (row = 0; row === NUMBER_OF_CUBES_PER_SIDE; row++) { - for (column = 0; column === NUMBER_OF_CUBES_PER_SIDE; column++) { - this.createColorBusterCube(row, column, vertical) - } - } - } -} \ No newline at end of file diff --git a/examples/color_busters_game/createColorBusterWand.js b/examples/color_busters_game/createColorBusterWand.js deleted file mode 100644 index 4af5306177..0000000000 --- a/examples/color_busters_game/createColorBusterWand.js +++ /dev/null @@ -1,55 +0,0 @@ -var COLOR_WAND_MODEL_URL = ''; -var COLOR_WAND_DIMENSIONS = { - x: 0, - y: 0, - z: 0 -}; -var COLOR_WAND_START_POSITION = { - x: 0, - y: 0, - z: 0 -}; -var STARTING_COLORS = [ - ['red', { - red: 255, - green: 0, - blue: 0 - }], - ['yellow', { - red: 255, - green: 255, - blue: 0 - }], - ['blue', { - red: 0, - green: 0, - blue: 255 - }] -] - -function chooseStartingColor() { - var startingColor = STARTING_COLORS[Math.floor(Math.random() * STARTING_COLORS.length)]; - return startingColor -} - -function createColorBusterWand() { - - var startingColor = chooseStartingColor(); - var colorBusterWandProperties = { - name: 'Hifi-ColorBusterWand', - type: 'Model', - url: COLOR_WAND_MODEL_URL, - dimensions: COLOR_WAND_DIMENSIONS, - position: COLOR_WAND_START_POSITION, - userData: JSON.stringify({ - hifiColorBusterWandKey: { - owner: MyAvatar.sessionUUID, - currentColor: startingColor[1], - originalColorName: startingColor[0], - colorLocked: false - } - }) - }; - - Entities.addEntity(colorBusterWandProperties); -} \ No newline at end of file diff --git a/examples/color_busters_game/colorBusterWand.js b/examples/example/games/color_busters/colorBusterWand.js similarity index 69% rename from examples/color_busters_game/colorBusterWand.js rename to examples/example/games/color_busters/colorBusterWand.js index 26948da91b..6080d6f345 100644 --- a/examples/color_busters_game/colorBusterWand.js +++ b/examples/example/games/color_busters/colorBusterWand.js @@ -1,42 +1,63 @@ +// +// colorBusterWand.js +// +// Created by James B. Pollack @imgntn on 11/2/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This is the entity script that attaches to a wand for the Color Busters game +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + + (function() { + Script.include("../../../libraries/utils.js"); - //seconds that the combination lasts - var COMBINED_COLOR_DURATION = 10; + var COMBINED_COLOR_DURATION = 5; - var INDICATOR_OFFSET_UP = 0.5; + var INDICATOR_OFFSET_UP = 0.40; - var REMOVE_CUBE_SOUND_URL = ''; - var COMBINE_COLORS_SOUND_URL = ''; + var REMOVE_CUBE_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/color_busters/boop.wav'; + var COMBINE_COLORS_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/color_busters/powerup.wav'; + + var COLOR_INDICATOR_DIMENSIONS = { + x: 0.10, + y: 0.10, + z: 0.10 + }; var _this; - function ColorWand() { + function ColorBusterWand() { _this = this; - }; + } ColorBusterWand.prototype = { combinedColorsTimer: null, - + soundIsPlaying: false, preload: function(entityID) { print("preload"); this.entityID = entityID; this.REMOVE_CUBE_SOUND = SoundCache.getSound(REMOVE_CUBE_SOUND_URL); this.COMBINE_COLORS_SOUND = SoundCache.getSound(COMBINE_COLORS_SOUND_URL); - }, - entityCollisionWithEntity: function(me, otherEntity, collision) { - + collisionWithEntity: function(me, otherEntity, collision) { var otherProperties = Entities.getEntityProperties(otherEntity, ["name", "userData"]); - var myProperties = Entities.getEntityProperties(otherEntity, ["userData"]); + var myProperties = Entities.getEntityProperties(me, ["userData"]); var myUserData = JSON.parse(myProperties.userData); var otherUserData = JSON.parse(otherProperties.userData); if (otherProperties.name === 'Hifi-ColorBusterWand') { + print('HIT ANOTHER COLOR WAND!!'); if (otherUserData.hifiColorBusterWandKey.colorLocked !== true && myUserData.hifiColorBusterWandKey.colorLocked !== true) { if (otherUserData.hifiColorBusterWandKey.originalColorName === myUserData.hifiColorBusterWandKey.originalColorName) { + print('BUT ITS THE SAME COLOR!') return; } else { + print('COMBINE COLORS!' + this.entityID); this.combineColorsWithOtherWand(otherUserData.hifiColorBusterWandKey.originalColorName, myUserData.hifiColorBusterWandKey.originalColorName); } } @@ -44,15 +65,23 @@ if (otherProperties.name === 'Hifi-ColorBusterCube') { if (otherUserData.hifiColorBusterCubeKey.originalColorName === myUserData.hifiColorBusterWandKey.currentColor) { - removeCubeOfSameColor(otherEntity); + print('HIT THE SAME COLOR CUBE'); + this.removeCubeOfSameColor(otherEntity); + } else { + print('HIT A CUBE OF A DIFFERENT COLOR'); } - } }, combineColorsWithOtherWand: function(otherColor, myColor) { - var newColor; + print('combining my :' + myColor + " with their: " + otherColor); + if ((myColor === 'violet') || (myColor === 'orange') || (myColor === 'green')) { + print('MY WAND ALREADY COMBINED'); + return; + } + + var newColor; if ((otherColor === 'red' && myColor == 'yellow') || (myColor === 'red' && otherColor === 'yellow')) { //orange newColor = 'orange'; @@ -73,19 +102,18 @@ _this.combinedColorsTimer = null; }, COMBINED_COLOR_DURATION * 1000); - setEntityCustomData(hifiColorWandKey, this.entityID, { + setEntityCustomData('hifiColorBusterWandKey', this.entityID, { owner: MyAvatar.sessionUUID, - currentColor: newColor + currentColor: newColor, originalColorName: myColor, colorLocked: false }); - _this.setCurrentColor(newColor); + this.playSoundAtCurrentPosition(false); }, setCurrentColor: function(newColor) { - var color; if (newColor === 'orange') { @@ -138,23 +166,27 @@ Entities.editEntity(this.colorIndicator, { color: color - }) + }); + + // print('SET THIS COLOR INDICATOR TO:' + newColor); }, resetToOriginalColor: function(myColor) { - setEntityCustomData(hifiColorWandKey, this.entityID, { + setEntityCustomData('hifiColorBusterWandKey', this.entityID, { owner: MyAvatar.sessionUUID, - currentColor: myColor + currentColor: myColor, originalColorName: myColor, - colorLocked: true + colorLocked: false }); this.setCurrentColor(myColor); }, removeCubeOfSameColor: function(cube) { + this.playSoundAtCurrentPosition(true); Entities.callEntityMethod(cube, 'cubeEnding'); Entities.deleteEntity(cube); + }, startNearGrab: function() { @@ -164,24 +196,31 @@ continueNearGrab: function() { this.currentProperties = Entities.getEntityProperties(this.entityID); + + var color = JSON.parse(this.currentProperties.userData).hifiColorBusterWandKey.currentColor; + + this.setCurrentColor(color); this.updateColorIndicatorLocation(); }, releaseGrab: function() { - this.deleteEntity(this.colorIndicator); + Entities.deleteEntity(this.colorIndicator); if (this.combinedColorsTimer !== null) { Script.clearTimeout(this.combinedColorsTimer); } }, - createColorIndicator: function() { + createColorIndicator: function(color) { + + var properties = { name: 'Hifi-ColorBusterIndicator', type: 'Box', dimensions: COLOR_INDICATOR_DIMENSIONS, - color: this.currentProperties.position, - position: this.currentProperties.position + position: this.currentProperties.position, + collisionsWillMove: false, + ignoreForCollisions: true } this.colorIndicator = Entities.addEntity(properties); @@ -204,15 +243,15 @@ }, - playSoundAtCurrentPosition: function(removeCubeSound) { - var position = Entities.getEntityProperties(this.entityID, "position").position; + playSoundAtCurrentPosition: function(isRemoveCubeSound) { + var position = Entities.getEntityProperties(this.entityID, "position").position; var audioProperties = { - volume: 0.25, + volume: 0.5, position: position }; - if (removeCubeSound) { + if (isRemoveCubeSound === true) { Audio.playSound(this.REMOVE_CUBE_SOUND, audioProperties); } else { Audio.playSound(this.COMBINE_COLORS_SOUND, audioProperties); diff --git a/examples/example/games/color_busters/createColorBusterCubes.js b/examples/example/games/color_busters/createColorBusterCubes.js new file mode 100644 index 0000000000..1b7aac51a5 --- /dev/null +++ b/examples/example/games/color_busters/createColorBusterCubes.js @@ -0,0 +1,130 @@ +// +// createColorBusterCubes.js +// +// Created by James B. Pollack @imgntn on 11/2/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This script creates cubes that can be removed with a Color Buster wand. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +var DELETE_AT_ENDING = true; + +var CUBE_DIMENSIONS = { + x: 1, + y: 1, + z: 1 +}; + +var NUMBER_OF_CUBES_PER_SIDE = 5; + +var STARTING_CORNER_POSITION = { + x: 100, + y: 100, + z: 100 +}; +var STARTING_COLORS = [ + ['red', { + red: 255, + green: 0, + blue: 0 + }], + ['yellow', { + red: 255, + green: 255, + blue: 0 + }], + ['blue', { + red: 0, + green: 0, + blue: 255 + }], + ['orange', { + red: 255, + green: 165, + blue: 0 + }], + ['violet', { + red: 128, + green: 0, + blue: 128 + }], + ['green', { + red: 0, + green: 255, + blue: 0 + }] +]; + +function chooseStartingColor() { + var startingColor = STARTING_COLORS[Math.floor(Math.random() * STARTING_COLORS.length)]; + return startingColor; +} + +var cubes = []; + +function createColorBusterCube(row, column, vertical) { + + print('make cube at ' + row + ':' + column + ":" + vertical); + + var position = { + x: STARTING_CORNER_POSITION.x + row, + y: STARTING_CORNER_POSITION.y + vertical, + z: STARTING_CORNER_POSITION.z + column + }; + + var startingColor = chooseStartingColor(); + var colorBusterCubeProperties = { + name: 'Hifi-ColorBusterCube', + type: 'Box', + dimensions: CUBE_DIMENSIONS, + collisionsWillMove: false, + ignoreForCollisions: false, + color: startingColor[1], + position: position, + userData: JSON.stringify({ + hifiColorBusterCubeKey: { + originalColorName: startingColor[0] + }, + grabbableKey: { + grabbable: false + } + }) + }; + var cube = Entities.addEntity(colorBusterCubeProperties); + cubes.push(cube); + return cube +} + +function createBoard() { + var vertical; + var row; + var column; + for (vertical = 0; vertical < NUMBER_OF_CUBES_PER_SIDE; vertical++) { + print('vertical:' + vertical) + //create a single layer + for (row = 0; row < NUMBER_OF_CUBES_PER_SIDE; row++) { + print('row:' + row) + for (column = 0; column < NUMBER_OF_CUBES_PER_SIDE; column++) { + print('column:' + column) + createColorBusterCube(row, column, vertical) + } + } + } +} + +function deleteCubes() { + while (cubes.length > 0) { + Entities.deleteEntity(cubes.pop()); + } +} + +if (DELETE_AT_ENDING === true) { + Script.scriptEnding.connect(deleteCubes); + +} + +createBoard(); \ No newline at end of file diff --git a/examples/example/games/color_busters/createColorBusterWand.js b/examples/example/games/color_busters/createColorBusterWand.js new file mode 100644 index 0000000000..a08f529aa8 --- /dev/null +++ b/examples/example/games/color_busters/createColorBusterWand.js @@ -0,0 +1,99 @@ +// +// createColorBusterWand.js +// +// Created by James B. Pollack @imgntn on 11/2/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This script creates a wand that can be used to remove color buster blocks. Touch your wand to someone else's to combine colors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var DELETE_AT_ENDING = false; + +var COLOR_WAND_MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/color_busters/wand.fbx'; +var COLOR_WAND_COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/color_busters/wand_collision_hull.obj'; +var COLOR_WAND_SCRIPT_URL = Script.resolvePath('colorBusterWand.js'); + +var COLOR_WAND_DIMENSIONS = { + x: 0.04, + y: 0.87, + z: 0.04 +}; + +var COLOR_WAND_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; + +var STARTING_COLORS = [ + ['red', { + red: 255, + green: 0, + blue: 0 + }], + ['yellow', { + red: 255, + green: 255, + blue: 0 + }], + ['blue', { + red: 0, + green: 0, + blue: 255 + }] +]; + +var center = Vec3.sum(Vec3.sum(MyAvatar.position, { + x: 0, + y: 0.5, + z: 0 +}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); + + +function chooseStartingColor() { + var startingColor = STARTING_COLORS[Math.floor(Math.random() * STARTING_COLORS.length)]; + return startingColor +} + +var wand; + +function createColorBusterWand() { + var startingColor = chooseStartingColor(); + var colorBusterWandProperties = { + name: 'Hifi-ColorBusterWand', + type: 'Model', + modelURL: COLOR_WAND_MODEL_URL, + shapeType: 'compound', + compoundShapeURL: COLOR_WAND_COLLISION_HULL_URL, + dimensions: COLOR_WAND_DIMENSIONS, + position: center, + script: COLOR_WAND_SCRIPT_URL, + collisionsWillMove: true, + userData: JSON.stringify({ + hifiColorBusterWandKey: { + owner: MyAvatar.sessionUUID, + currentColor: startingColor[0], + originalColorName: startingColor[0], + colorLocked: false + }, + grabbableKey: { + invertSolidWhileHeld: false + } + }) + }; + + wand = Entities.addEntity(colorBusterWandProperties); +} + +function deleteWand() { + Entities.deleteEntity(wand); +} + +if (DELETE_AT_ENDING === true) { + Script.scriptEnding.connect(deleteWand); +} + +createColorBusterWand(); \ No newline at end of file From aeac31cf6a5470f760af1536adb718e782b3d4ec Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 2 Nov 2015 16:37:24 -0800 Subject: [PATCH 05/23] dont delete cubes by default --- examples/example/games/color_busters/createColorBusterCubes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example/games/color_busters/createColorBusterCubes.js b/examples/example/games/color_busters/createColorBusterCubes.js index 1b7aac51a5..6a2942bbe9 100644 --- a/examples/example/games/color_busters/createColorBusterCubes.js +++ b/examples/example/games/color_busters/createColorBusterCubes.js @@ -11,7 +11,7 @@ // -var DELETE_AT_ENDING = true; +var DELETE_AT_ENDING = false; var CUBE_DIMENSIONS = { x: 1, From 811fd0cec7f786011dfe23bdf57634025ff21220 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 3 Nov 2015 10:42:15 -0800 Subject: [PATCH 06/23] prep for meeting --- examples/example/games/color_busters/colorBusterWand.js | 2 +- examples/example/games/color_busters/createColorBusterCubes.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example/games/color_busters/colorBusterWand.js b/examples/example/games/color_busters/colorBusterWand.js index 6080d6f345..f9d69e8414 100644 --- a/examples/example/games/color_busters/colorBusterWand.js +++ b/examples/example/games/color_busters/colorBusterWand.js @@ -247,7 +247,7 @@ var position = Entities.getEntityProperties(this.entityID, "position").position; var audioProperties = { - volume: 0.5, + volume: 0.25, position: position }; diff --git a/examples/example/games/color_busters/createColorBusterCubes.js b/examples/example/games/color_busters/createColorBusterCubes.js index 6a2942bbe9..3fdd772704 100644 --- a/examples/example/games/color_busters/createColorBusterCubes.js +++ b/examples/example/games/color_busters/createColorBusterCubes.js @@ -19,7 +19,7 @@ var CUBE_DIMENSIONS = { z: 1 }; -var NUMBER_OF_CUBES_PER_SIDE = 5; +var NUMBER_OF_CUBES_PER_SIDE = 8; var STARTING_CORNER_POSITION = { x: 100, From c002888808765940fc0b4dd42d444f6be25645d5 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 6 Nov 2015 14:52:12 -0800 Subject: [PATCH 07/23] Added cache extractor to the tools directory It should find the local High Fidelity/Interface qt cache, iterate over each file in the cache and output each corresponding file into the High Fidelity/Interface/extracted dir. The file path will be determined from the source url. Untested on windows. --- tools/CMakeLists.txt | 3 + tools/cache-extract/CMakeLists.txt | 6 + tools/cache-extract/src/CacheExtractApp.cpp | 125 ++++++++++++++++++++ tools/cache-extract/src/CacheExtractApp.h | 47 ++++++++ tools/cache-extract/src/main.cpp | 17 +++ 5 files changed, 198 insertions(+) create mode 100644 tools/cache-extract/CMakeLists.txt create mode 100644 tools/cache-extract/src/CacheExtractApp.cpp create mode 100644 tools/cache-extract/src/CacheExtractApp.h create mode 100644 tools/cache-extract/src/main.cpp diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 2056044a4b..9bc7031720 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -10,3 +10,6 @@ set_target_properties(udt-test PROPERTIES FOLDER "Tools") add_subdirectory(vhacd-util) set_target_properties(vhacd-util PROPERTIES FOLDER "Tools") + +add_subdirectory(cache-extract) +set_target_properties(cache-extract PROPERTIES FOLDER "Tools") diff --git a/tools/cache-extract/CMakeLists.txt b/tools/cache-extract/CMakeLists.txt new file mode 100644 index 0000000000..045fa996d2 --- /dev/null +++ b/tools/cache-extract/CMakeLists.txt @@ -0,0 +1,6 @@ +set(TARGET_NAME cache-extract) + +setup_hifi_project() + +link_hifi_libraries() + diff --git a/tools/cache-extract/src/CacheExtractApp.cpp b/tools/cache-extract/src/CacheExtractApp.cpp new file mode 100644 index 0000000000..e7e60973af --- /dev/null +++ b/tools/cache-extract/src/CacheExtractApp.cpp @@ -0,0 +1,125 @@ +// +// CacheExtractApp.cpp +// tools/cache-extract/src +// +// Created by Anthony Thibault on 11/6/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "CacheExtractApp.h" +#include +#include +#include +#include + +// extracted from qnetworkdiskcache.cpp +#define CACHE_VERSION 8 +enum { + CacheMagic = 0xe8, + CurrentCacheVersion = CACHE_VERSION +}; +#define DATA_DIR QLatin1String("data") + +CacheExtractApp::CacheExtractApp(int& argc, char** argv) : + QCoreApplication(argc, argv) +{ + QString myDataLoc = QStandardPaths::writableLocation(QStandardPaths::DataLocation); + int lastSlash = myDataLoc.lastIndexOf(QDir::separator()); + QString cachePath = myDataLoc.leftRef(lastSlash).toString() + QDir::separator() + + "High Fidelity" + QDir::separator() + "Interface" + QDir::separator() + + DATA_DIR + QString::number(CACHE_VERSION) + QLatin1Char('/'); + + QString outputPath = myDataLoc.leftRef(lastSlash).toString() + QDir::separator() + + "High Fidelity" + QDir::separator() + "Interface" + QDir::separator() + "extracted"; + + qDebug() << "Searching cachePath = " << cachePath << "..."; + + // build list of files + QList fileList; + QDir dir(cachePath); + dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + if (fileInfo.isDir()) { + QDir subDir(fileInfo.filePath()); + subDir.setFilter(QDir::Files); + QFileInfoList subList = subDir.entryInfoList(); + for (int j = 0; j < subList.size(); ++j) { + fileList << subList.at(j).filePath(); + } + } + } + + // dump each cache file into the outputPath + for (int i = 0; i < fileList.size(); ++i) { + QByteArray contents; + MyMetaData metaData; + if (extractFile(fileList.at(i), metaData, contents)) { + QString outFileName = outputPath + metaData.url.path(); + int lastSlash = outFileName.lastIndexOf(QDir::separator()); + QString outDirName = outFileName.leftRef(lastSlash).toString(); + QDir dir(outputPath); + dir.mkpath(outDirName); + QFile out(outFileName); + if (out.open(QIODevice::WriteOnly)) { + out.write(contents); + out.close(); + } + } else { + qCritical() << "Error extracting = " << fileList.at(i); + } + } + + QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); +} + +bool CacheExtractApp::extractFile(const QString& filePath, MyMetaData& metaData, QByteArray& data) const { + QFile f(filePath); + if (!f.open(QIODevice::ReadOnly)) { + qDebug() << "error opening " << filePath; + return false; + } + QDataStream in(&f); + // from qnetworkdiskcache.cpp QCacheItem::read() + qint32 marker, version, streamVersion; + in >> marker; + if (marker != CacheMagic) { + return false; + } + in >> version; + if (version != CurrentCacheVersion) { + return false; + } + in >> streamVersion; + if (streamVersion > in.version()) + return false; + in.setVersion(streamVersion); + + bool compressed; + in >> metaData; + in >> compressed; + if (compressed) { + QByteArray compressedData; + in >> compressedData; + QBuffer buffer; + buffer.setData(qUncompress(compressedData)); + buffer.open(QBuffer::ReadOnly); + data = buffer.readAll(); + } else { + data = f.readAll(); + } + return true; +} + +QDataStream &operator>>(QDataStream& in, MyMetaData& metaData) { + in >> metaData.url; + in >> metaData.expirationDate; + in >> metaData.lastModified; + in >> metaData.saveToDisk; + in >> metaData.attributes; + in >> metaData.rawHeaders; +} diff --git a/tools/cache-extract/src/CacheExtractApp.h b/tools/cache-extract/src/CacheExtractApp.h new file mode 100644 index 0000000000..3dde1f684d --- /dev/null +++ b/tools/cache-extract/src/CacheExtractApp.h @@ -0,0 +1,47 @@ +// +// CacheExtractApp.h +// tools/cache-extract/src +// +// Created by Anthony Thibault on 11/6/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_CacheExtractApp_h +#define hifi_CacheExtractApp_h + +#include +#include +#include +#include +#include +#include + +// copy of QNetworkCacheMetaData +class MyMetaData { +public: + typedef QPair RawHeader; + typedef QList RawHeaderList; + typedef QHash AttributesMap; + + QUrl url; + QDateTime expirationDate; + QDateTime lastModified; + bool saveToDisk; + AttributesMap attributes; + RawHeaderList rawHeaders; +}; + +QDataStream &operator>>(QDataStream &, MyMetaData &); + +class CacheExtractApp : public QCoreApplication { + Q_OBJECT +public: + CacheExtractApp(int& argc, char** argv); + + bool extractFile(const QString& filePath, MyMetaData& metaData, QByteArray& data) const; +}; + +#endif // hifi_CacheExtractApp_h diff --git a/tools/cache-extract/src/main.cpp b/tools/cache-extract/src/main.cpp new file mode 100644 index 0000000000..71a364ed3e --- /dev/null +++ b/tools/cache-extract/src/main.cpp @@ -0,0 +1,17 @@ +// +// main.cpp +// tools/cache-extract/src +// +// Created by Anthony Thibault on 11/6/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include "CacheExtractApp.h" + +int main (int argc, char** argv) { + CacheExtractApp app(argc, argv); + return app.exec(); +} From 086b0645273f33c9fc00cfd99cb82b82fef0725e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 6 Nov 2015 15:07:38 -0800 Subject: [PATCH 08/23] Dumps all urls extracted to stdout. --- tools/cache-extract/src/CacheExtractApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/cache-extract/src/CacheExtractApp.cpp b/tools/cache-extract/src/CacheExtractApp.cpp index e7e60973af..a0d0bf54ec 100644 --- a/tools/cache-extract/src/CacheExtractApp.cpp +++ b/tools/cache-extract/src/CacheExtractApp.cpp @@ -68,6 +68,7 @@ CacheExtractApp::CacheExtractApp(int& argc, char** argv) : if (out.open(QIODevice::WriteOnly)) { out.write(contents); out.close(); + qDebug().noquote() << metaData.url.toDisplayString(); } } else { qCritical() << "Error extracting = " << fileList.at(i); From 9a484ff00dd71b94c34712759fc4a863a99c910a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 6 Nov 2015 15:33:06 -0800 Subject: [PATCH 09/23] Fixes for windows --- tools/cache-extract/CMakeLists.txt | 1 + tools/cache-extract/src/CacheExtractApp.cpp | 22 ++++++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/cache-extract/CMakeLists.txt b/tools/cache-extract/CMakeLists.txt index 045fa996d2..1aaa4d9d04 100644 --- a/tools/cache-extract/CMakeLists.txt +++ b/tools/cache-extract/CMakeLists.txt @@ -3,4 +3,5 @@ set(TARGET_NAME cache-extract) setup_hifi_project() link_hifi_libraries() +copy_dlls_beside_windows_executable() diff --git a/tools/cache-extract/src/CacheExtractApp.cpp b/tools/cache-extract/src/CacheExtractApp.cpp index a0d0bf54ec..0cfaef3f83 100644 --- a/tools/cache-extract/src/CacheExtractApp.cpp +++ b/tools/cache-extract/src/CacheExtractApp.cpp @@ -14,6 +14,7 @@ #include #include #include +#include // extracted from qnetworkdiskcache.cpp #define CACHE_VERSION 8 @@ -21,19 +22,18 @@ enum { CacheMagic = 0xe8, CurrentCacheVersion = CACHE_VERSION }; -#define DATA_DIR QLatin1String("data") CacheExtractApp::CacheExtractApp(int& argc, char** argv) : QCoreApplication(argc, argv) { QString myDataLoc = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - int lastSlash = myDataLoc.lastIndexOf(QDir::separator()); - QString cachePath = myDataLoc.leftRef(lastSlash).toString() + QDir::separator() + - "High Fidelity" + QDir::separator() + "Interface" + QDir::separator() + - DATA_DIR + QString::number(CACHE_VERSION) + QLatin1Char('/'); + int lastSlash = myDataLoc.lastIndexOf("/"); + QString cachePath = myDataLoc.leftRef(lastSlash).toString() + "/" + + "High Fidelity" + "/" + "Interface" + "/" + + "data" + QString::number(CACHE_VERSION) + "/"; - QString outputPath = myDataLoc.leftRef(lastSlash).toString() + QDir::separator() + - "High Fidelity" + QDir::separator() + "Interface" + QDir::separator() + "extracted"; + QString outputPath = myDataLoc.leftRef(lastSlash).toString() + "/" + + "High Fidelity" + "/" + "Interface" + "/" + "extracted"; qDebug() << "Searching cachePath = " << cachePath << "..."; @@ -60,9 +60,9 @@ CacheExtractApp::CacheExtractApp(int& argc, char** argv) : MyMetaData metaData; if (extractFile(fileList.at(i), metaData, contents)) { QString outFileName = outputPath + metaData.url.path(); - int lastSlash = outFileName.lastIndexOf(QDir::separator()); + int lastSlash = outFileName.lastIndexOf("/"); QString outDirName = outFileName.leftRef(lastSlash).toString(); - QDir dir(outputPath); + QDir dir; dir.mkpath(outDirName); QFile out(outFileName); if (out.open(QIODevice::WriteOnly)) { @@ -70,6 +70,9 @@ CacheExtractApp::CacheExtractApp(int& argc, char** argv) : out.close(); qDebug().noquote() << metaData.url.toDisplayString(); } + else { + qCritical() << "Error opening outputFile = " << outFileName; + } } else { qCritical() << "Error extracting = " << fileList.at(i); } @@ -123,4 +126,5 @@ QDataStream &operator>>(QDataStream& in, MyMetaData& metaData) { in >> metaData.saveToDisk; in >> metaData.attributes; in >> metaData.rawHeaders; + return in; } From 82b26b75f4024099e569ef6703594adf3321759b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 9 Nov 2015 08:14:27 -0800 Subject: [PATCH 10/23] Code convention fixes --- tools/cache-extract/src/CacheExtractApp.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/cache-extract/src/CacheExtractApp.h b/tools/cache-extract/src/CacheExtractApp.h index 3dde1f684d..3b34ff891d 100644 --- a/tools/cache-extract/src/CacheExtractApp.h +++ b/tools/cache-extract/src/CacheExtractApp.h @@ -22,9 +22,9 @@ // copy of QNetworkCacheMetaData class MyMetaData { public: - typedef QPair RawHeader; - typedef QList RawHeaderList; - typedef QHash AttributesMap; + using RawHeader = QPair; + using RawHeaderList = QList; + using AttributesMap = QHash; QUrl url; QDateTime expirationDate; @@ -34,7 +34,7 @@ public: RawHeaderList rawHeaders; }; -QDataStream &operator>>(QDataStream &, MyMetaData &); +QDataStream &operator>>(QDataStream& in, MyMetaData& metaData); class CacheExtractApp : public QCoreApplication { Q_OBJECT From 006a1d60c82699612fa2d98629ba990735a3e356 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 10 Nov 2015 15:31:51 -0800 Subject: [PATCH 11/23] keep some additional erase entities history and send to viewers --- .../src/entities/EntityNodeData.h | 6 +- .../src/entities/EntityServer.cpp | 5 +- libraries/entities/src/EntityTree.cpp | 116 +++++++++--------- 3 files changed, 65 insertions(+), 62 deletions(-) diff --git a/assignment-client/src/entities/EntityNodeData.h b/assignment-client/src/entities/EntityNodeData.h index e4008fcb03..69da9ee14b 100644 --- a/assignment-client/src/entities/EntityNodeData.h +++ b/assignment-client/src/entities/EntityNodeData.h @@ -18,9 +18,7 @@ class EntityNodeData : public OctreeQueryNode { public: - EntityNodeData() : - OctreeQueryNode(), - _lastDeletedEntitiesSentAt(0) { } + EntityNodeData() : OctreeQueryNode() { } virtual PacketType getMyPacketType() const { return PacketType::EntityData; } @@ -28,7 +26,7 @@ public: void setLastDeletedEntitiesSentAt(quint64 sentAt) { _lastDeletedEntitiesSentAt = sentAt; } private: - quint64 _lastDeletedEntitiesSentAt; + quint64 _lastDeletedEntitiesSentAt { usecTimestampNow() }; }; #endif // hifi_EntityNodeData_h diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index f2a4c2664a..e2941541af 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -82,7 +82,6 @@ bool EntityServer::hasSpecialPacketsToSend(const SharedNodePointer& node) { EntityNodeData* nodeData = static_cast(node->getLinkedData()); if (nodeData) { quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); - EntityTreePointer tree = std::static_pointer_cast(_tree); shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt); } @@ -97,7 +96,6 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN if (nodeData) { quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); quint64 deletePacketSentAt = usecTimestampNow(); - EntityTreePointer tree = std::static_pointer_cast(_tree); bool hasMoreToSend = true; @@ -127,7 +125,6 @@ void EntityServer::pruneDeletedEntities() { if (tree->hasAnyDeletedEntities()) { quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future - DependencyManager::get()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) { if (node->getLinkedData()) { EntityNodeData* nodeData = static_cast(node->getLinkedData()); @@ -138,6 +135,8 @@ void EntityServer::pruneDeletedEntities() { } }); + int EXTRA_SECONDS_TO_KEEP = 4; + earliestLastDeletedEntitiesSent -= USECS_PER_SECOND * EXTRA_SECONDS_TO_KEEP; tree->forgetEntitiesDeletedBefore(earliestLastDeletedEntitiesSent); } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 8e32158362..c69c2daa16 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -384,16 +384,17 @@ void EntityTree::deleteEntities(QSet entityIDs, bool force, bool i } void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) { + quint64 deletedAt = usecTimestampNow(); const RemovedEntities& entities = theOperator.getEntities(); foreach(const EntityToDeleteDetails& details, entities) { EntityItemPointer theEntity = details.entity; if (getIsServer()) { // set up the deleted entities ID - quint64 deletedAt = usecTimestampNow(); - _recentlyDeletedEntitiesLock.lockForWrite(); - _recentlyDeletedEntityItemIDs.insert(deletedAt, theEntity->getEntityItemID()); - _recentlyDeletedEntitiesLock.unlock(); + { + QWriteLocker locker(&_recentlyDeletedEntitiesLock); + _recentlyDeletedEntityItemIDs.insert(deletedAt, theEntity->getEntityItemID()); + } } if (_simulation) { @@ -802,18 +803,23 @@ void EntityTree::update() { } bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { + int EXTRA_SECONDS_TO_CONSIDER = 4; + quint64 considerEntitiesSince = sinceTime - (USECS_PER_SECOND * EXTRA_SECONDS_TO_CONSIDER); + // we can probably leverage the ordered nature of QMultiMap to do this quickly... bool hasSomethingNewer = false; + { + QReadLocker locker(&_recentlyDeletedEntitiesLock); - _recentlyDeletedEntitiesLock.lockForRead(); - QMultiMap::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin(); - while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) { - if (iterator.key() > sinceTime) { - hasSomethingNewer = true; + QMultiMap::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin(); + while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) { + if (iterator.key() > considerEntitiesSince) { + hasSomethingNewer = true; + } + ++iterator; } - ++iterator; } - _recentlyDeletedEntitiesLock.unlock(); + return hasSomethingNewer; } @@ -821,6 +827,8 @@ bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, bool& hasMore) { + int EXTRA_SECONDS_TO_CONSIDER = 4; + quint64 considerEntitiesSince = sinceTime - (USECS_PER_SECOND * EXTRA_SECONDS_TO_CONSIDER); auto deletesPacket = NLPacket::create(PacketType::EntityErase); // pack in flags @@ -841,48 +849,46 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // we keep a multi map of entity IDs to timestamps, we only want to include the entity IDs that have been // deleted since we last sent to this node - _recentlyDeletedEntitiesLock.lockForRead(); + { + QReadLocker locker(&_recentlyDeletedEntitiesLock); - bool hasFilledPacket = false; + bool hasFilledPacket = false; - auto it = _recentlyDeletedEntityItemIDs.constBegin(); - while (it != _recentlyDeletedEntityItemIDs.constEnd()) { - QList values = _recentlyDeletedEntityItemIDs.values(it.key()); - for (int valueItem = 0; valueItem < values.size(); ++valueItem) { + auto it = _recentlyDeletedEntityItemIDs.constBegin(); + while (it != _recentlyDeletedEntityItemIDs.constEnd()) { + QList values = _recentlyDeletedEntityItemIDs.values(it.key()); + for (int valueItem = 0; valueItem < values.size(); ++valueItem) { - // if the timestamp is more recent then out last sent time, include it - if (it.key() > sinceTime) { - QUuid entityID = values.at(valueItem); - deletesPacket->write(entityID.toRfc4122()); + // if the timestamp is more recent then out last sent time, include it + if (it.key() > considerEntitiesSince) { + QUuid entityID = values.at(valueItem); + deletesPacket->write(entityID.toRfc4122()); + ++numberOfIDs; - ++numberOfIDs; - - // check to make sure we have room for one more ID - if (NUM_BYTES_RFC4122_UUID > deletesPacket->bytesAvailableForWrite()) { - hasFilledPacket = true; - break; + // check to make sure we have room for one more ID + if (NUM_BYTES_RFC4122_UUID > deletesPacket->bytesAvailableForWrite()) { + hasFilledPacket = true; + break; + } } } + + // check to see if we're about to return + if (hasFilledPacket) { + // let our caller know how far we got + sinceTime = it.key(); + break; + } + + ++it; } - // check to see if we're about to return - if (hasFilledPacket) { - // let our caller know how far we got - sinceTime = it.key(); - - break; + // if we got to the end, then we're done sending + if (it == _recentlyDeletedEntityItemIDs.constEnd()) { + hasMore = false; } - - ++it; } - // if we got to the end, then we're done sending - if (it == _recentlyDeletedEntityItemIDs.constEnd()) { - hasMore = false; - } - - _recentlyDeletedEntitiesLock.unlock(); - // replace the count for the number of included IDs deletesPacket->seek(numberOfIDsPos); deletesPacket->writePrimitive(numberOfIDs); @@ -895,23 +901,23 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) { QSet keysToRemove; - _recentlyDeletedEntitiesLock.lockForWrite(); - QMultiMap::iterator iterator = _recentlyDeletedEntityItemIDs.begin(); + { + QWriteLocker locker(&_recentlyDeletedEntitiesLock); + QMultiMap::iterator iterator = _recentlyDeletedEntityItemIDs.begin(); - // First find all the keys in the map that are older and need to be deleted - while (iterator != _recentlyDeletedEntityItemIDs.end()) { - if (iterator.key() <= sinceTime) { - keysToRemove << iterator.key(); + // First find all the keys in the map that are older and need to be deleted + while (iterator != _recentlyDeletedEntityItemIDs.end()) { + if (iterator.key() <= sinceTime) { + keysToRemove << iterator.key(); + } + ++iterator; } - ++iterator; - } - // Now run through the keysToRemove and remove them - foreach (quint64 value, keysToRemove) { - _recentlyDeletedEntityItemIDs.remove(value); + // Now run through the keysToRemove and remove them + foreach (quint64 value, keysToRemove) { + _recentlyDeletedEntityItemIDs.remove(value); + } } - - _recentlyDeletedEntitiesLock.unlock(); } From 3316b63bf6e8efb1c9a494dd5ce027983b76c026 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 10 Nov 2015 15:46:53 -0800 Subject: [PATCH 12/23] add a fixme comment --- libraries/entities/src/EntityTree.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index c69c2daa16..34b09eb67c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -862,6 +862,12 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // if the timestamp is more recent then out last sent time, include it if (it.key() > considerEntitiesSince) { QUuid entityID = values.at(valueItem); + + // FIXME - we still seem to see cases where incorrect EntityIDs get sent from the server + // to the client. These were causing "lost" entities like flashlights and laser pointers + // now that we keep around some additional history of the erased entities and resend that + // history for a longer time window, these entities are not "lost". But we haven't yet + // found/fixed the underlying issue that caused bad UUIDs to be sent to some users. deletesPacket->write(entityID.toRfc4122()); ++numberOfIDs; From a76385808041f4e6a3dc2b9576c242176bed9668 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 11 Nov 2015 11:22:05 -0800 Subject: [PATCH 13/23] Revert cache-extract This reverts these commits: * 82b26b7 Code convention fixes * 9a484ff Fixes for windows * 086b064 Dumps all urls extracted to stdout. * c002888 Added cache extractor to the tools directory --- tools/CMakeLists.txt | 3 - tools/cache-extract/CMakeLists.txt | 7 -- tools/cache-extract/src/CacheExtractApp.cpp | 130 -------------------- tools/cache-extract/src/CacheExtractApp.h | 47 ------- tools/cache-extract/src/main.cpp | 17 --- 5 files changed, 204 deletions(-) delete mode 100644 tools/cache-extract/CMakeLists.txt delete mode 100644 tools/cache-extract/src/CacheExtractApp.cpp delete mode 100644 tools/cache-extract/src/CacheExtractApp.h delete mode 100644 tools/cache-extract/src/main.cpp diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9bc7031720..2056044a4b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -10,6 +10,3 @@ set_target_properties(udt-test PROPERTIES FOLDER "Tools") add_subdirectory(vhacd-util) set_target_properties(vhacd-util PROPERTIES FOLDER "Tools") - -add_subdirectory(cache-extract) -set_target_properties(cache-extract PROPERTIES FOLDER "Tools") diff --git a/tools/cache-extract/CMakeLists.txt b/tools/cache-extract/CMakeLists.txt deleted file mode 100644 index 1aaa4d9d04..0000000000 --- a/tools/cache-extract/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(TARGET_NAME cache-extract) - -setup_hifi_project() - -link_hifi_libraries() -copy_dlls_beside_windows_executable() - diff --git a/tools/cache-extract/src/CacheExtractApp.cpp b/tools/cache-extract/src/CacheExtractApp.cpp deleted file mode 100644 index 0cfaef3f83..0000000000 --- a/tools/cache-extract/src/CacheExtractApp.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// -// CacheExtractApp.cpp -// tools/cache-extract/src -// -// Created by Anthony Thibault on 11/6/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "CacheExtractApp.h" -#include -#include -#include -#include -#include - -// extracted from qnetworkdiskcache.cpp -#define CACHE_VERSION 8 -enum { - CacheMagic = 0xe8, - CurrentCacheVersion = CACHE_VERSION -}; - -CacheExtractApp::CacheExtractApp(int& argc, char** argv) : - QCoreApplication(argc, argv) -{ - QString myDataLoc = QStandardPaths::writableLocation(QStandardPaths::DataLocation); - int lastSlash = myDataLoc.lastIndexOf("/"); - QString cachePath = myDataLoc.leftRef(lastSlash).toString() + "/" + - "High Fidelity" + "/" + "Interface" + "/" + - "data" + QString::number(CACHE_VERSION) + "/"; - - QString outputPath = myDataLoc.leftRef(lastSlash).toString() + "/" + - "High Fidelity" + "/" + "Interface" + "/" + "extracted"; - - qDebug() << "Searching cachePath = " << cachePath << "..."; - - // build list of files - QList fileList; - QDir dir(cachePath); - dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); - QFileInfoList list = dir.entryInfoList(); - for (int i = 0; i < list.size(); ++i) { - QFileInfo fileInfo = list.at(i); - if (fileInfo.isDir()) { - QDir subDir(fileInfo.filePath()); - subDir.setFilter(QDir::Files); - QFileInfoList subList = subDir.entryInfoList(); - for (int j = 0; j < subList.size(); ++j) { - fileList << subList.at(j).filePath(); - } - } - } - - // dump each cache file into the outputPath - for (int i = 0; i < fileList.size(); ++i) { - QByteArray contents; - MyMetaData metaData; - if (extractFile(fileList.at(i), metaData, contents)) { - QString outFileName = outputPath + metaData.url.path(); - int lastSlash = outFileName.lastIndexOf("/"); - QString outDirName = outFileName.leftRef(lastSlash).toString(); - QDir dir; - dir.mkpath(outDirName); - QFile out(outFileName); - if (out.open(QIODevice::WriteOnly)) { - out.write(contents); - out.close(); - qDebug().noquote() << metaData.url.toDisplayString(); - } - else { - qCritical() << "Error opening outputFile = " << outFileName; - } - } else { - qCritical() << "Error extracting = " << fileList.at(i); - } - } - - QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); -} - -bool CacheExtractApp::extractFile(const QString& filePath, MyMetaData& metaData, QByteArray& data) const { - QFile f(filePath); - if (!f.open(QIODevice::ReadOnly)) { - qDebug() << "error opening " << filePath; - return false; - } - QDataStream in(&f); - // from qnetworkdiskcache.cpp QCacheItem::read() - qint32 marker, version, streamVersion; - in >> marker; - if (marker != CacheMagic) { - return false; - } - in >> version; - if (version != CurrentCacheVersion) { - return false; - } - in >> streamVersion; - if (streamVersion > in.version()) - return false; - in.setVersion(streamVersion); - - bool compressed; - in >> metaData; - in >> compressed; - if (compressed) { - QByteArray compressedData; - in >> compressedData; - QBuffer buffer; - buffer.setData(qUncompress(compressedData)); - buffer.open(QBuffer::ReadOnly); - data = buffer.readAll(); - } else { - data = f.readAll(); - } - return true; -} - -QDataStream &operator>>(QDataStream& in, MyMetaData& metaData) { - in >> metaData.url; - in >> metaData.expirationDate; - in >> metaData.lastModified; - in >> metaData.saveToDisk; - in >> metaData.attributes; - in >> metaData.rawHeaders; - return in; -} diff --git a/tools/cache-extract/src/CacheExtractApp.h b/tools/cache-extract/src/CacheExtractApp.h deleted file mode 100644 index 3b34ff891d..0000000000 --- a/tools/cache-extract/src/CacheExtractApp.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// CacheExtractApp.h -// tools/cache-extract/src -// -// Created by Anthony Thibault on 11/6/2015 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_CacheExtractApp_h -#define hifi_CacheExtractApp_h - -#include -#include -#include -#include -#include -#include - -// copy of QNetworkCacheMetaData -class MyMetaData { -public: - using RawHeader = QPair; - using RawHeaderList = QList; - using AttributesMap = QHash; - - QUrl url; - QDateTime expirationDate; - QDateTime lastModified; - bool saveToDisk; - AttributesMap attributes; - RawHeaderList rawHeaders; -}; - -QDataStream &operator>>(QDataStream& in, MyMetaData& metaData); - -class CacheExtractApp : public QCoreApplication { - Q_OBJECT -public: - CacheExtractApp(int& argc, char** argv); - - bool extractFile(const QString& filePath, MyMetaData& metaData, QByteArray& data) const; -}; - -#endif // hifi_CacheExtractApp_h diff --git a/tools/cache-extract/src/main.cpp b/tools/cache-extract/src/main.cpp deleted file mode 100644 index 71a364ed3e..0000000000 --- a/tools/cache-extract/src/main.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// main.cpp -// tools/cache-extract/src -// -// Created by Anthony Thibault on 11/6/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html - -#include -#include "CacheExtractApp.h" - -int main (int argc, char** argv) { - CacheExtractApp app(argc, argv); - return app.exec(); -} From f40e46957bea804287ca1925de2df531976e90dc Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Tue, 10 Nov 2015 17:18:34 -0800 Subject: [PATCH 14/23] handControlledHead.js added --- .../avatarcontrol/handControlledHead.js | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 examples/example/avatarcontrol/handControlledHead.js diff --git a/examples/example/avatarcontrol/handControlledHead.js b/examples/example/avatarcontrol/handControlledHead.js new file mode 100644 index 0000000000..87c24e9a7e --- /dev/null +++ b/examples/example/avatarcontrol/handControlledHead.js @@ -0,0 +1,65 @@ +// handControlledHead.js + +//This script allows you to look around, driving the rotation of the avatar's head by the right hand orientation. + +const YAW_MULTIPLIER = 20000; +const PITCH_MULTIPLIER = 15000; +const EPSILON = 0.001; +var firstPress = true; +var handPreviousVerticalRotation = 0.0; +var handCurrentVerticalRotation = 0.0; +var handPreviousHorizontalRotation = 0.0; +var handCurrentHorizontalRotation = 0.0; +var rotatedHandPosition; +var rotatedTipPosition; + +function update(deltaTime) { + if(Controller.getValue(Controller.Standard.RightPrimaryThumb)){ + pitchManager(deltaTime); + }else if(!firstPress){ + firstPress = true; + } + if(firstPress && MyAvatar.headYaw){ + MyAvatar.headYaw -= MyAvatar.headYaw/10; + } + +} + +function pitchManager(deltaTime){ + + rotatedHandPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, -MyAvatar.bodyYaw, 0), MyAvatar.getRightHandPosition()); + rotatedTipPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, -MyAvatar.bodyYaw, 0), MyAvatar.getRightHandTipPosition()); + + handCurrentVerticalRotation = Vec3.subtract(rotatedTipPosition, rotatedHandPosition).y; + handCurrentHorizontalRotation = Vec3.subtract(rotatedTipPosition, rotatedHandPosition).x; + + var handCurrentHorizontalRotationFiltered = handCurrentHorizontalRotation; + + //to avoid yaw drift + if((handCurrentHorizontalRotation - handPreviousHorizontalRotation) < EPSILON && (handCurrentHorizontalRotation - handPreviousHorizontalRotation) > -EPSILON){ + handCurrentHorizontalRotationFiltered = handPreviousHorizontalRotation; + } + + if(firstPress){ + handPreviousVerticalRotation = handCurrentVerticalRotation; + handPreviousHorizontalRotation = handCurrentHorizontalRotation; + firstPress = false; + } + + MyAvatar.headPitch += (handCurrentVerticalRotation - handPreviousVerticalRotation)*PITCH_MULTIPLIER*deltaTime; + MyAvatar.headYaw -= (handCurrentHorizontalRotationFiltered - handPreviousHorizontalRotation)*YAW_MULTIPLIER*deltaTime; + + + handPreviousVerticalRotation = handCurrentVerticalRotation; + handPreviousHorizontalRotation = handCurrentHorizontalRotationFiltered; + + +} + +function clean(){ + MyAvatar.headYaw = 0.0; +} + + +Script.update.connect(update); +Script.scriptEnding.connect(clean); \ No newline at end of file From e4b1b54e005384e5bc072824278e1a3bb9bebb46 Mon Sep 17 00:00:00 2001 From: AlessandroSigna Date: Wed, 11 Nov 2015 12:07:54 -0800 Subject: [PATCH 15/23] added header --- .../example/avatarcontrol/handControlledHead.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/example/avatarcontrol/handControlledHead.js b/examples/example/avatarcontrol/handControlledHead.js index 87c24e9a7e..95ad1655ab 100644 --- a/examples/example/avatarcontrol/handControlledHead.js +++ b/examples/example/avatarcontrol/handControlledHead.js @@ -1,6 +1,14 @@ -// handControlledHead.js - -//This script allows you to look around, driving the rotation of the avatar's head by the right hand orientation. +// +// handControlledHead.js +// examples +// +// Created by Alessandro Signa on 10/11/15. +// Copyright 2015 High Fidelity, Inc. +// +// This script allows you to look around, driving the rotation of the avatar's head by the right hand orientation. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html const YAW_MULTIPLIER = 20000; const PITCH_MULTIPLIER = 15000; From 866116d2855baf69b25777cde78cbafe4c66741a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 11 Nov 2015 12:13:47 -0800 Subject: [PATCH 16/23] more debugging --- .../src/entities/EntityServer.cpp | 11 +++- .../src/octree/OctreeSendThread.cpp | 2 +- libraries/entities/src/EntityTree.cpp | 65 +++++++++++-------- libraries/entities/src/EntityTree.h | 1 + 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index e2941541af..81dabd4dcd 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -84,6 +84,10 @@ bool EntityServer::hasSpecialPacketsToSend(const SharedNodePointer& node) { quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); EntityTreePointer tree = std::static_pointer_cast(_tree); shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt); + if (shouldSendDeletedEntities) { + int elapsed = usecTimestampNow() - deletedEntitiesSentAt; + qDebug() << "shouldSendDeletedEntities to node:" << node->getUUID() << "deletedEntitiesSentAt:" << deletedEntitiesSentAt << "elapsed:" << elapsed; + } } return shouldSendDeletedEntities; @@ -116,6 +120,10 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN nodeData->setLastDeletedEntitiesSentAt(deletePacketSentAt); } + if (packetsSent > 0) { + qDebug() << "EntityServer::sendSpecialPackets() sent " << packetsSent << "special packets of " << totalBytes << " total bytes to node:" << node->getUUID(); + } + // TODO: caller is expecting a packetLength, what if we send more than one packet?? return totalBytes; } @@ -134,9 +142,6 @@ void EntityServer::pruneDeletedEntities() { } } }); - - int EXTRA_SECONDS_TO_KEEP = 4; - earliestLastDeletedEntitiesSent -= USECS_PER_SECOND * EXTRA_SECONDS_TO_KEEP; tree->forgetEntitiesDeletedBefore(earliestLastDeletedEntitiesSent); } } diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 2696c92253..b94317050c 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -570,7 +570,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus } - if (somethingToSend) { + if (somethingToSend && _myServer->wantsVerboseDebug()) { qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval << " maxPacketsPerInterval = " << maxPacketsPerInterval << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 34b09eb67c..7f350888be 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -25,6 +25,7 @@ #include "RecurseOctreeToMapOperator.h" #include "LogHandler.h" +const quint64 EntityTree::DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 500; EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), @@ -803,21 +804,26 @@ void EntityTree::update() { } bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { - int EXTRA_SECONDS_TO_CONSIDER = 4; - quint64 considerEntitiesSince = sinceTime - (USECS_PER_SECOND * EXTRA_SECONDS_TO_CONSIDER); + quint64 considerEntitiesSince = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER; // we can probably leverage the ordered nature of QMultiMap to do this quickly... bool hasSomethingNewer = false; - { - QReadLocker locker(&_recentlyDeletedEntitiesLock); - QMultiMap::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin(); - while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) { - if (iterator.key() > considerEntitiesSince) { - hasSomethingNewer = true; - } - ++iterator; + QReadLocker locker(&_recentlyDeletedEntitiesLock); + QMultiMap::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin(); + while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) { + if (iterator.key() > considerEntitiesSince) { + hasSomethingNewer = true; + break; // if we have at least one item, we don't need to keep searching } + ++iterator; + } + + if (hasSomethingNewer) { + int elapsed = usecTimestampNow() - considerEntitiesSince; + int difference = considerEntitiesSince - sinceTime; + qDebug() << "EntityTree::hasEntitiesDeletedSince() sinceTime:" << sinceTime + << "considerEntitiesSince:" << considerEntitiesSince << "elapsed:" << elapsed << "difference:" << difference; } return hasSomethingNewer; @@ -826,14 +832,16 @@ bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { // sinceTime is an in/out parameter - it will be side effected with the last time sent out std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, bool& hasMore) { + qDebug() << "EntityTree::encodeEntitiesDeletedSince()"; - int EXTRA_SECONDS_TO_CONSIDER = 4; - quint64 considerEntitiesSince = sinceTime - (USECS_PER_SECOND * EXTRA_SECONDS_TO_CONSIDER); + quint64 considerEntitiesSince = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER; auto deletesPacket = NLPacket::create(PacketType::EntityErase); + qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // pack in flags OCTREE_PACKET_FLAGS flags = 0; deletesPacket->writePrimitive(flags); + qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // pack in sequence number deletesPacket->writePrimitive(sequenceNumber); @@ -841,11 +849,13 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // pack in timestamp OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); deletesPacket->writePrimitive(now); + qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // figure out where we are now and pack a temporary number of IDs uint16_t numberOfIDs = 0; qint64 numberOfIDsPos = deletesPacket->pos(); deletesPacket->writePrimitive(numberOfIDs); + qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // we keep a multi map of entity IDs to timestamps, we only want to include the entity IDs that have been // deleted since we last sent to this node @@ -869,6 +879,8 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // history for a longer time window, these entities are not "lost". But we haven't yet // found/fixed the underlying issue that caused bad UUIDs to be sent to some users. deletesPacket->write(entityID.toRfc4122()); + qDebug() << "EntityTree::encodeEntitiesDeletedSince() including:" << entityID; + qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); ++numberOfIDs; // check to make sure we have room for one more ID @@ -898,6 +910,9 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // replace the count for the number of included IDs deletesPacket->seek(numberOfIDsPos); deletesPacket->writePrimitive(numberOfIDs); + qDebug() << " ---- at line:" << __LINE__ <<" deletes packet size:" << deletesPacket->getDataSize(); + + qDebug() << " ---- EntityTree::encodeEntitiesDeletedSince() numberOfIDs:" << numberOfIDs; return deletesPacket; } @@ -905,24 +920,22 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // called by the server when it knows all nodes have been sent deleted packets void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) { + quint64 considerSinceTime = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER; QSet keysToRemove; + QWriteLocker locker(&_recentlyDeletedEntitiesLock); + QMultiMap::iterator iterator = _recentlyDeletedEntityItemIDs.begin(); - { - QWriteLocker locker(&_recentlyDeletedEntitiesLock); - QMultiMap::iterator iterator = _recentlyDeletedEntityItemIDs.begin(); - - // First find all the keys in the map that are older and need to be deleted - while (iterator != _recentlyDeletedEntityItemIDs.end()) { - if (iterator.key() <= sinceTime) { - keysToRemove << iterator.key(); - } - ++iterator; + // First find all the keys in the map that are older and need to be deleted + while (iterator != _recentlyDeletedEntityItemIDs.end()) { + if (iterator.key() <= considerSinceTime) { + keysToRemove << iterator.key(); } + ++iterator; + } - // Now run through the keysToRemove and remove them - foreach (quint64 value, keysToRemove) { - _recentlyDeletedEntityItemIDs.remove(value); - } + // Now run through the keysToRemove and remove them + foreach (quint64 value, keysToRemove) { + _recentlyDeletedEntityItemIDs.remove(value); } } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index c177840199..dd31901a4d 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -147,6 +147,7 @@ public: void addNewlyCreatedHook(NewlyCreatedEntityHook* hook); void removeNewlyCreatedHook(NewlyCreatedEntityHook* hook); + static const quint64 DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER; bool hasAnyDeletedEntities() const { return _recentlyDeletedEntityItemIDs.size() > 0; } bool hasEntitiesDeletedSince(quint64 sinceTime); std::unique_ptr encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, From 040bae60142ef9ed611510382cae777f64d77450 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 11 Nov 2015 12:31:50 -0800 Subject: [PATCH 17/23] more debugging --- libraries/entities/src/EntityTree.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 7f350888be..49d50b28ff 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -942,6 +942,7 @@ void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) { // TODO: consider consolidating processEraseMessageDetails() and processEraseMessage() int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) { + qDebug() << "EntityTree::processEraseMessage()"; withWriteLock([&] { packet.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME)); @@ -959,6 +960,7 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s } QUuid entityID = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + qDebug() << " ---- EntityTree::processEraseMessage() contained ID:" << entityID; EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; @@ -978,6 +980,7 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s // NOTE: Caller must lock the tree before calling this. // TODO: consider consolidating processEraseMessageDetails() and processEraseMessage() int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { + qDebug() << "EntityTree::processEraseMessageDetails()"; const unsigned char* packetData = (const unsigned char*)dataByteArray.constData(); const unsigned char* dataAt = packetData; size_t packetLength = dataByteArray.size(); @@ -1004,6 +1007,8 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons dataAt += encodedID.size(); processedBytes += encodedID.size(); + qDebug() << " ---- EntityTree::processEraseMessageDetails() contains id:" << entityID; + EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; From bdfe304f7aee9f8b6a8b3e6969b8146cea690aaa Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 11 Nov 2015 14:08:15 -0800 Subject: [PATCH 18/23] remove some logging --- .../src/entities/EntityServer.cpp | 20 +++++++---- libraries/entities/src/EntityTree.cpp | 35 ++++++++++--------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 81dabd4dcd..493a16fea4 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -84,10 +84,13 @@ bool EntityServer::hasSpecialPacketsToSend(const SharedNodePointer& node) { quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt(); EntityTreePointer tree = std::static_pointer_cast(_tree); shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt); - if (shouldSendDeletedEntities) { - int elapsed = usecTimestampNow() - deletedEntitiesSentAt; - qDebug() << "shouldSendDeletedEntities to node:" << node->getUUID() << "deletedEntitiesSentAt:" << deletedEntitiesSentAt << "elapsed:" << elapsed; - } + + #ifdef EXTRA_ERASE_DEBUGGING + if (shouldSendDeletedEntities) { + int elapsed = usecTimestampNow() - deletedEntitiesSentAt; + qDebug() << "shouldSendDeletedEntities to node:" << node->getUUID() << "deletedEntitiesSentAt:" << deletedEntitiesSentAt << "elapsed:" << elapsed; + } + #endif } return shouldSendDeletedEntities; @@ -120,9 +123,12 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN nodeData->setLastDeletedEntitiesSentAt(deletePacketSentAt); } - if (packetsSent > 0) { - qDebug() << "EntityServer::sendSpecialPackets() sent " << packetsSent << "special packets of " << totalBytes << " total bytes to node:" << node->getUUID(); - } + #ifdef EXTRA_ERASE_DEBUGGING + if (packetsSent > 0) { + qDebug() << "EntityServer::sendSpecialPackets() sent " << packetsSent << "special packets of " + << totalBytes << " total bytes to node:" << node->getUUID(); + } + #endif // TODO: caller is expecting a packetLength, what if we send more than one packet?? return totalBytes; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 49d50b28ff..077bd1b76b 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -25,7 +25,7 @@ #include "RecurseOctreeToMapOperator.h" #include "LogHandler.h" -const quint64 EntityTree::DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 500; +const quint64 EntityTree::DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 50; EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), @@ -819,12 +819,14 @@ bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { ++iterator; } +#ifdef EXTRA_ERASE_DEBUGGING if (hasSomethingNewer) { int elapsed = usecTimestampNow() - considerEntitiesSince; int difference = considerEntitiesSince - sinceTime; qDebug() << "EntityTree::hasEntitiesDeletedSince() sinceTime:" << sinceTime << "considerEntitiesSince:" << considerEntitiesSince << "elapsed:" << elapsed << "difference:" << difference; } +#endif return hasSomethingNewer; } @@ -832,16 +834,12 @@ bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) { // sinceTime is an in/out parameter - it will be side effected with the last time sent out std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, bool& hasMore) { - qDebug() << "EntityTree::encodeEntitiesDeletedSince()"; - quint64 considerEntitiesSince = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER; auto deletesPacket = NLPacket::create(PacketType::EntityErase); - qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // pack in flags OCTREE_PACKET_FLAGS flags = 0; deletesPacket->writePrimitive(flags); - qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // pack in sequence number deletesPacket->writePrimitive(sequenceNumber); @@ -849,13 +847,11 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // pack in timestamp OCTREE_PACKET_SENT_TIME now = usecTimestampNow(); deletesPacket->writePrimitive(now); - qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // figure out where we are now and pack a temporary number of IDs uint16_t numberOfIDs = 0; qint64 numberOfIDsPos = deletesPacket->pos(); deletesPacket->writePrimitive(numberOfIDs); - qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); // we keep a multi map of entity IDs to timestamps, we only want to include the entity IDs that have been // deleted since we last sent to this node @@ -879,10 +875,12 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // history for a longer time window, these entities are not "lost". But we haven't yet // found/fixed the underlying issue that caused bad UUIDs to be sent to some users. deletesPacket->write(entityID.toRfc4122()); - qDebug() << "EntityTree::encodeEntitiesDeletedSince() including:" << entityID; - qDebug() << " ---- at line:" << __LINE__ << " deletes packet size:" << deletesPacket->getDataSize(); ++numberOfIDs; + #ifdef EXTRA_ERASE_DEBUGGING + qDebug() << "EntityTree::encodeEntitiesDeletedSince() including:" << entityID; + #endif + // check to make sure we have room for one more ID if (NUM_BYTES_RFC4122_UUID > deletesPacket->bytesAvailableForWrite()) { hasFilledPacket = true; @@ -910,9 +908,6 @@ std::unique_ptr EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S // replace the count for the number of included IDs deletesPacket->seek(numberOfIDsPos); deletesPacket->writePrimitive(numberOfIDs); - qDebug() << " ---- at line:" << __LINE__ <<" deletes packet size:" << deletesPacket->getDataSize(); - - qDebug() << " ---- EntityTree::encodeEntitiesDeletedSince() numberOfIDs:" << numberOfIDs; return deletesPacket; } @@ -942,7 +937,9 @@ void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) { // TODO: consider consolidating processEraseMessageDetails() and processEraseMessage() int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) { - qDebug() << "EntityTree::processEraseMessage()"; + #ifdef EXTRA_ERASE_DEBUGGING + qDebug() << "EntityTree::processEraseMessage()"; + #endif withWriteLock([&] { packet.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME)); @@ -960,7 +957,9 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s } QUuid entityID = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - qDebug() << " ---- EntityTree::processEraseMessage() contained ID:" << entityID; + #ifdef EXTRA_ERASE_DEBUGGING + qDebug() << " ---- EntityTree::processEraseMessage() contained ID:" << entityID; + #endif EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; @@ -980,7 +979,9 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s // NOTE: Caller must lock the tree before calling this. // TODO: consider consolidating processEraseMessageDetails() and processEraseMessage() int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { - qDebug() << "EntityTree::processEraseMessageDetails()"; + #ifdef EXTRA_ERASE_DEBUGGING + qDebug() << "EntityTree::processEraseMessageDetails()"; + #endif const unsigned char* packetData = (const unsigned char*)dataByteArray.constData(); const unsigned char* dataAt = packetData; size_t packetLength = dataByteArray.size(); @@ -1007,7 +1008,9 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons dataAt += encodedID.size(); processedBytes += encodedID.size(); - qDebug() << " ---- EntityTree::processEraseMessageDetails() contains id:" << entityID; + #ifdef EXTRA_ERASE_DEBUGGING + qDebug() << " ---- EntityTree::processEraseMessageDetails() contains id:" << entityID; + #endif EntityItemID entityItemID(entityID); entityItemIDsToDelete << entityItemID; From 2f903a9513f43a7e5da301a756e4eccf082359bb Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 11 Nov 2015 14:21:14 -0800 Subject: [PATCH 19/23] CR feedback and some cleanup --- assignment-client/src/entities/EntityNodeData.h | 2 -- libraries/entities/src/EntityTree.cpp | 8 +++----- libraries/entities/src/EntityTree.h | 1 - 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/entities/EntityNodeData.h b/assignment-client/src/entities/EntityNodeData.h index 69da9ee14b..0ca0834fef 100644 --- a/assignment-client/src/entities/EntityNodeData.h +++ b/assignment-client/src/entities/EntityNodeData.h @@ -18,8 +18,6 @@ class EntityNodeData : public OctreeQueryNode { public: - EntityNodeData() : OctreeQueryNode() { } - virtual PacketType getMyPacketType() const { return PacketType::EntityData; } quint64 getLastDeletedEntitiesSentAt() const { return _lastDeletedEntitiesSentAt; } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 077bd1b76b..0174dbe39b 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -25,7 +25,7 @@ #include "RecurseOctreeToMapOperator.h" #include "LogHandler.h" -const quint64 EntityTree::DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 50; +static const quint64 DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 50; EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), @@ -392,10 +392,8 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) if (getIsServer()) { // set up the deleted entities ID - { - QWriteLocker locker(&_recentlyDeletedEntitiesLock); - _recentlyDeletedEntityItemIDs.insert(deletedAt, theEntity->getEntityItemID()); - } + QWriteLocker locker(&_recentlyDeletedEntitiesLock); + _recentlyDeletedEntityItemIDs.insert(deletedAt, theEntity->getEntityItemID()); } if (_simulation) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index dd31901a4d..c177840199 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -147,7 +147,6 @@ public: void addNewlyCreatedHook(NewlyCreatedEntityHook* hook); void removeNewlyCreatedHook(NewlyCreatedEntityHook* hook); - static const quint64 DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER; bool hasAnyDeletedEntities() const { return _recentlyDeletedEntityItemIDs.size() > 0; } bool hasEntitiesDeletedSince(quint64 sinceTime); std::unique_ptr encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, From 0f057d722987180d9a47c6c1373201b0e3325de8 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Fri, 6 Nov 2015 18:58:50 -0800 Subject: [PATCH 20/23] Set clip for ControlledAC --- examples/acScripts/ControlACs.js | 29 +++++++++++++++++++++++++++-- examples/acScripts/ControlledAC.js | 16 +++++++++++++--- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/examples/acScripts/ControlACs.js b/examples/acScripts/ControlACs.js index 403c0878cb..fb33dd3178 100644 --- a/examples/acScripts/ControlACs.js +++ b/examples/acScripts/ControlACs.js @@ -17,17 +17,21 @@ var NAMES = new Array("Craig", "Clement", "Jeff"); // ACs names ordered by IDs ( // Those variables MUST be common to every scripts var controlEntitySize = 0.25; -var controlEntityPosition = { x: 2000 , y: 0, z: 0 }; +var controlEntityPosition = { x: 0, y: 0, z: 0 }; // Script. DO NOT MODIFY BEYOND THIS LINE. Script.include("../libraries/toolBars.js"); +var filename = null; +var fileloaded = null; + var DO_NOTHING = 0; var PLAY = 1; var PLAY_LOOP = 2; var STOP = 3; var SHOW = 4; var HIDE = 5; +var LOAD = 6; var COLORS = []; COLORS[PLAY] = { red: PLAY, green: 0, blue: 0 }; @@ -35,6 +39,7 @@ COLORS[PLAY_LOOP] = { red: PLAY_LOOP, green: 0, blue: 0 }; COLORS[STOP] = { red: STOP, green: 0, blue: 0 }; COLORS[SHOW] = { red: SHOW, green: 0, blue: 0 }; COLORS[HIDE] = { red: HIDE, green: 0, blue: 0 }; +COLORS[LOAD] = { red: LOAD, green: 0, blue: 0 }; @@ -53,6 +58,7 @@ var onOffIcon = new Array(); var playIcon = new Array(); var playLoopIcon = new Array(); var stopIcon = new Array(); +var loadIcon = new Array(); setupToolBars(); @@ -104,6 +110,14 @@ function setupToolBars() { alpha: ALPHA_OFF, visible: true }, false); + + loadIcon[i] = toolBars[i].addTool({ + imageURL: TOOL_ICON_URL + "recording-upload.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: ALPHA_OFF, + visible: true + }, false); nameOverlays.push(Overlays.addOverlay("text", { backgroundColor: { red: 0, green: 0, blue: 0 }, @@ -129,11 +143,13 @@ function sendCommand(id, action) { toolBars[id].setAlpha(ALPHA_ON, playIcon[id]); toolBars[id].setAlpha(ALPHA_ON, playLoopIcon[id]); toolBars[id].setAlpha(ALPHA_ON, stopIcon[id]); + toolBars[id].setAlpha(ALPHA_ON, loadIcon[id]); } else if (action === HIDE) { toolBars[id].selectTool(onOffIcon[id], true); toolBars[id].setAlpha(ALPHA_OFF, playIcon[id]); toolBars[id].setAlpha(ALPHA_OFF, playLoopIcon[id]); toolBars[id].setAlpha(ALPHA_OFF, stopIcon[id]); + toolBars[id].setAlpha(ALPHA_OFF, loadIcon[id]); } else if (toolBars[id].toolSelected(onOffIcon[id])) { return; } @@ -148,6 +164,7 @@ function sendCommand(id, action) { var position = { x: controlEntityPosition.x + id * controlEntitySize, y: controlEntityPosition.y, z: controlEntityPosition.z }; Entities.addEntity({ + name: filename, type: "Box", position: position, dimensions: { x: controlEntitySize, y: controlEntitySize, z: controlEntitySize }, @@ -173,6 +190,8 @@ function mousePressEvent(event) { sendCommand(i, PLAY_LOOP); } else if (stopIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { sendCommand(i, STOP); + } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { + sendCommand(i, LOAD); } else { // Check individual controls for (i = 0; i < NUM_AC; i++) { @@ -188,6 +207,12 @@ function mousePressEvent(event) { sendCommand(i, PLAY_LOOP); } else if (stopIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { sendCommand(i, STOP); + } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { + fileloaded = Window.browse("Load recording from file", ".", "Recordings (*.hfr *.rec *.HFR *.REC)"); + if (!(fileloaded === "null" || fileloaded === null || fileloaded === "")) { + filename = fileloaded; + sendCommand(i, LOAD); + } } else { } @@ -231,4 +256,4 @@ Controller.mousePressEvent.connect(mousePressEvent); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); -moveUI(); +moveUI(); \ No newline at end of file diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index 93c71aa1a1..25c2ae72d9 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -22,7 +22,7 @@ var useAvatarModel = true; var id = 0; // Set avatar model URL -Avatar.skeletonModelURL = "https://hifi-public.s3.amazonaws.com/marketplace/contents/e21c0b95-e502-4d15-8c41-ea2fc40f1125/3585ddf674869a67d31d5964f7b52de1.fst?1427169998"; +Avatar.skeletonModelURL = "https://hifi-public.s3.amazonaws.com/marketplace/contents/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73/4618d52e711fbb34df442b414da767bb.fst?1427170144"; // Set position/orientation/scale here if playFromCurrentLocation is true Avatar.position = { x:1, y: 1, z: 1 }; Avatar.orientation = Quat.fromPitchYawRollDegrees(0, 0, 0); @@ -30,7 +30,7 @@ Avatar.scale = 1.0; // Those variables MUST be common to every scripts var controlEntitySize = 0.25; -var controlEntityPosition = { x: 2000, y: 0, z: 0 }; +var controlEntityPosition = { x: 0, y: 0, z: 0 }; // Script. DO NOT MODIFY BEYOND THIS LINE. var DO_NOTHING = 0; @@ -39,6 +39,7 @@ var PLAY_LOOP = 2; var STOP = 3; var SHOW = 4; var HIDE = 5; +var LOAD = 6; var COLORS = []; COLORS[PLAY] = { red: PLAY, green: 0, blue: 0 }; @@ -46,6 +47,7 @@ COLORS[PLAY_LOOP] = { red: PLAY_LOOP, green: 0, blue: 0 }; COLORS[STOP] = { red: STOP, green: 0, blue: 0 }; COLORS[SHOW] = { red: SHOW, green: 0, blue: 0 }; COLORS[HIDE] = { red: HIDE, green: 0, blue: 0 }; +COLORS[LOAD] = { red: LOAD, green: 0, blue: 0 }; controlEntityPosition.x += id * controlEntitySize; @@ -68,7 +70,9 @@ function setupEntityViewer() { EntityViewer.queryOctree(); } -function getAction(controlEntity) { +function getAction(controlEntity) { + filename = controlEntity.name; + if (controlEntity === null || controlEntity.position.x !== controlEntityPosition.x || controlEntity.position.y !== controlEntityPosition.y || @@ -141,6 +145,12 @@ function update(event) { } Agent.isAvatar = false; break; + case LOAD: + print("Load"); + if(filename !== null) { + Avatar.loadRecording(filename); + } + break; case DO_NOTHING: break; default: From 55d386aaabc040184ae5e9450b7487b47792dc06 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Mon, 9 Nov 2015 18:14:42 -0800 Subject: [PATCH 21/23] Fixes: Prompt and userData --- examples/acScripts/ControlACs.js | 13 +++++++------ examples/acScripts/ControlledAC.js | 10 +++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/examples/acScripts/ControlACs.js b/examples/acScripts/ControlACs.js index fb33dd3178..60b72446bb 100644 --- a/examples/acScripts/ControlACs.js +++ b/examples/acScripts/ControlACs.js @@ -22,8 +22,8 @@ var controlEntityPosition = { x: 0, y: 0, z: 0 }; // Script. DO NOT MODIFY BEYOND THIS LINE. Script.include("../libraries/toolBars.js"); -var filename = null; -var fileloaded = null; +var clip_url = null; +var input_text = null; var DO_NOTHING = 0; var PLAY = 1; @@ -164,7 +164,8 @@ function sendCommand(id, action) { var position = { x: controlEntityPosition.x + id * controlEntitySize, y: controlEntityPosition.y, z: controlEntityPosition.z }; Entities.addEntity({ - name: filename, + name: "Actor Controller", + userData: clip_url, type: "Box", position: position, dimensions: { x: controlEntitySize, y: controlEntitySize, z: controlEntitySize }, @@ -208,9 +209,9 @@ function mousePressEvent(event) { } else if (stopIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { sendCommand(i, STOP); } else if (loadIcon[i] === toolBars[i].clicked(clickedOverlay, false)) { - fileloaded = Window.browse("Load recording from file", ".", "Recordings (*.hfr *.rec *.HFR *.REC)"); - if (!(fileloaded === "null" || fileloaded === null || fileloaded === "")) { - filename = fileloaded; + input_text = Window.prompt("Insert the url of the clip: ",""); + if(!(input_text === "" || input_text === null)){ + clip_url = input_text; sendCommand(i, LOAD); } } else { diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index 25c2ae72d9..8be1172080 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -12,7 +12,7 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; // Set the following variables to the values needed -var filename = "/Users/clement/Desktop/recording.hfr"; +var clip_url = "https://dl.dropboxusercontent.com/u/14127429/Clips/recording1.hfr"; var playFromCurrentLocation = true; var useDisplayName = true; var useAttachments = true; @@ -51,7 +51,7 @@ COLORS[LOAD] = { red: LOAD, green: 0, blue: 0 }; controlEntityPosition.x += id * controlEntitySize; -Avatar.loadRecording(filename); +Avatar.loadRecording(clip_url); Avatar.setPlayFromCurrentLocation(playFromCurrentLocation); Avatar.setPlayerUseDisplayName(useDisplayName); @@ -71,7 +71,7 @@ function setupEntityViewer() { } function getAction(controlEntity) { - filename = controlEntity.name; + clip_url = controlEntity.userData; if (controlEntity === null || controlEntity.position.x !== controlEntityPosition.x || @@ -147,8 +147,8 @@ function update(event) { break; case LOAD: print("Load"); - if(filename !== null) { - Avatar.loadRecording(filename); + if(clip_url !== null) { + Avatar.loadRecording(clip_url); } break; case DO_NOTHING: From da2b49a1b04a7f310ffc0001a6205c18cf439991 Mon Sep 17 00:00:00 2001 From: EdgarPironti Date: Wed, 11 Nov 2015 15:03:19 -0800 Subject: [PATCH 22/23] Remove hardcoded url --- examples/acScripts/ControlledAC.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/acScripts/ControlledAC.js b/examples/acScripts/ControlledAC.js index 8be1172080..4eecc11136 100644 --- a/examples/acScripts/ControlledAC.js +++ b/examples/acScripts/ControlledAC.js @@ -9,10 +9,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; // Set the following variables to the values needed -var clip_url = "https://dl.dropboxusercontent.com/u/14127429/Clips/recording1.hfr"; +var clip_url = null; var playFromCurrentLocation = true; var useDisplayName = true; var useAttachments = true; @@ -21,8 +20,6 @@ var useAvatarModel = true; // ID of the agent. Two agents can't have the same ID. var id = 0; -// Set avatar model URL -Avatar.skeletonModelURL = "https://hifi-public.s3.amazonaws.com/marketplace/contents/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73/4618d52e711fbb34df442b414da767bb.fst?1427170144"; // Set position/orientation/scale here if playFromCurrentLocation is true Avatar.position = { x:1, y: 1, z: 1 }; Avatar.orientation = Quat.fromPitchYawRollDegrees(0, 0, 0); From 07f3d8eca04aa1c82a990a32ea7f1520d9fa3d55 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 11 Nov 2015 16:03:08 -0800 Subject: [PATCH 23/23] more debugging prints --- .../entities/src/EntityActionInterface.cpp | 21 ++++++++++ .../entities/src/EntityActionInterface.h | 2 + libraries/entities/src/EntityItem.cpp | 38 ++++++++++--------- libraries/entities/src/EntityTree.cpp | 20 ++++------ libraries/entities/src/SimulationOwner.cpp | 2 +- 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index 549aacbd0a..ce9a93a6ac 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -304,3 +304,24 @@ QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType) entityActionType = (EntityActionType)actionTypeAsInt; return stream; } + +QString serializedActionsToDebugString(QByteArray data) { + if (data.size() == 0) { + return QString(); + } + QVector serializedActions; + QDataStream serializedActionsStream(data); + serializedActionsStream >> serializedActions; + + QString result; + foreach(QByteArray serializedAction, serializedActions) { + QDataStream serializedActionStream(serializedAction); + EntityActionType actionType; + QUuid actionID; + serializedActionStream >> actionType; + serializedActionStream >> actionID; + result += EntityActionInterface::actionTypeToString(actionType) + "-" + actionID.toString() + " "; + } + + return result; +} diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index b257df3325..01292e3840 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -89,4 +89,6 @@ typedef std::shared_ptr EntityActionPointer; QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType); QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType); +QString serializedActionsToDebugString(QByteArray data); + #endif // hifi_EntityActionInterface_h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8aa2bdb5d3..807186a304 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -630,11 +630,11 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef dataAt += bytes; bytesRead += bytes; + if (wantTerseEditLogging() && _simulationOwner != newSimOwner) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; + } if (_simulationOwner.set(newSimOwner)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner; - } } } { // When we own the simulation we don't accept updates to the entity's transform/velocities @@ -740,7 +740,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // this "new" data is actually slightly out of date. We calculate the time we need to skip forward and // use our simulation helper routine to get a best estimate of where the entity should be. float skipTimeForward = (float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND); - + // we want to extrapolate the motion forward to compensate for packet travel time, but // we don't want the side effect of flag setting. simulateKinematicMotion(skipTimeForward, false); @@ -748,7 +748,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef if (overwriteLocalData) { if (!_simulationOwner.matchesValidID(myNodeID)) { - _lastSimulated = now; } } @@ -1500,33 +1499,36 @@ void EntityItem::updateCreated(uint64_t value) { } void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) { - if (_simulationOwner.set(id, priority)) { - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id; - } + if (wantTerseEditLogging() && (id != _simulationOwner.getID() || priority != _simulationOwner.getPriority())) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority; } + _simulationOwner.set(id, priority); } void EntityItem::setSimulationOwner(const SimulationOwner& owner) { - if (_simulationOwner.set(owner)) { - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner; - } + if (wantTerseEditLogging() && _simulationOwner != owner) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner; } + + _simulationOwner.set(owner); } void EntityItem::updateSimulatorID(const QUuid& value) { + if (wantTerseEditLogging() && _simulationOwner.getID() != value) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value; + } + if (_simulationOwner.setID(value)) { _dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; - if (wantTerseEditLogging()) { - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value; - } } } void EntityItem::clearSimulationOwnership() { + if (wantTerseEditLogging() && !_simulationOwner.isNull()) { + qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null"; + } + _simulationOwner.clear(); - qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null"; // don't bother setting the DIRTY_SIMULATOR_ID flag because clearSimulationOwnership() // is only ever called entity-server-side and the flags are only used client-side //_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID; @@ -1669,7 +1671,7 @@ void EntityItem::deserializeActionsInternal() { return; } - EntityTreePointer entityTree = _element ? _element->getTree() : nullptr; + EntityTreePointer entityTree = getTree(); assert(entityTree); EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr; assert(simulation); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 179e68ea29..de97af988d 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -197,13 +197,11 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI properties.setVelocityChanged(false); properties.setAngularVelocityChanged(false); properties.setAccelerationChanged(false); - } - // if (wantTerseEditLogging()) { - // if (properties.simulationOwnerChanged()) { - // qCDebug(entities) << "sim ownership for" << entity->getDebugName() << "is now" << senderID; - // } - // } + if (wantTerseEditLogging()) { + qCDebug(entities) << senderNode->getUUID() << "physical edits suppressed"; + } + } } // else client accepts what the server says @@ -666,10 +664,7 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { QByteArray value = properties.getActionData(); - QString changeHint = "0"; - if (value.size() > 0) { - changeHint = "+"; - } + QString changeHint = serializedActionsToDebugString(value); changedProperties[index] = QString("actionData:") + changeHint; } } @@ -763,7 +758,8 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - qCDebug(entities) << "edit" << existingEntity->getDebugName() << changedProperties; + qCDebug(entities) << senderNode->getUUID() << "edit" << + existingEntity->getDebugName() << changedProperties; } endLogging = usecTimestampNow(); @@ -793,7 +789,7 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi if (wantTerseEditLogging()) { QList changedProperties = properties.listChangedProperties(); fixupTerseEditLogging(properties, changedProperties); - qCDebug(entities) << "add" << entityItemID << changedProperties; + qCDebug(entities) << senderNode->getUUID() << "add" << entityItemID << changedProperties; } endLogging = usecTimestampNow(); diff --git a/libraries/entities/src/SimulationOwner.cpp b/libraries/entities/src/SimulationOwner.cpp index d6957873e2..24f6784954 100644 --- a/libraries/entities/src/SimulationOwner.cpp +++ b/libraries/entities/src/SimulationOwner.cpp @@ -157,7 +157,7 @@ void SimulationOwner::test() { } bool SimulationOwner::operator!=(const SimulationOwner& other) { - return (_id != other._id && _priority != other._priority); + return (_id != other._id || _priority != other._priority); } SimulationOwner& SimulationOwner::operator=(const SimulationOwner& other) {