Skip to content

Commit 1e56dad

Browse files
committed
Support function execution in voxel
1 parent 6eaa9fa commit 1e56dad

File tree

1 file changed

+81
-59
lines changed

1 file changed

+81
-59
lines changed

blockly/src/voxel/voxel.js

Lines changed: 81 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
'use strict';
1818

19-
var Voxel = module.exports;
20-
2119
/**
2220
* Create a namespace for the application.
2321
*/
@@ -53,6 +51,7 @@ var CANVAS_WIDTH = 400;
5351
* Initialize Blockly and the Voxel. Called on page load.
5452
*/
5553
Voxel.init = function(config) {
54+
Voxel.globals = {};
5655

5756
skin = config.skin;
5857
level = config.level;
@@ -98,25 +97,50 @@ Voxel.init = function(config) {
9897
var resetButton = document.getElementById('resetButton');
9998
dom.addClickTouchEvent(resetButton, Voxel.resetButtonClick);
10099

101-
window.game.plugins.get('voxel-reach').on('use', function(target) { Voxel.handleWhenRightClick(target);});
102-
//window.game.plugins.get('voxel-reach').on('start mining', function(target) { Voxel.handleWhenLeftClick(target);});
103-
window.game.on('fire', function() { Voxel.handleWhenLeftClick();});
100+
var shareButton = document.getElementById('rightButton');
101+
dom.addClickTouchEvent(shareButton, Voxel.endAttempt);
102+
if (!level.freePlay) {
103+
var shareButtonArea = document.getElementById('right-button-cell');
104+
shareButtonArea.style.display = 'none';
105+
}
104106

107+
window.game.plugins.get('voxel-reach').on('use', Voxel.generateEventBlockCodeRunner('voxel_whenRightClick'));
108+
//window.game.plugins.get('voxel-reach').on('start mining', function(target) { Voxel.handleWhenLeftClick(target);});
109+
window.game.on('fire', Voxel.generateEventBlockCodeRunner('voxel_whenRightClick'));
105110
};
106111

107112
BlocklyApps.init(config);
108113
};
109114

110-
Voxel.handleWhenRightClick = function(target) {
111-
evalCode(Blockly.Generator.blockSpaceToCode(
112-
'JavaScript',
113-
'voxel_whenRightClick'));
115+
Voxel.generateEventBlockCodeRunner = function(blockType) {
116+
return function() {
117+
Voxel.evaluateCodeUnderBlockType(blockType);
118+
};
119+
};
120+
121+
Voxel.evaluateCodeUnderBlockType = function(blockType) {
122+
Voxel.evaluateCode(Voxel.allProcedures() + Blockly.Generator.blockSpaceToCode('JavaScript', blockType));
123+
};
124+
125+
Voxel.allProcedures = function() {
126+
return Voxel.defineProceduresForType('procedures_defreturn') +
127+
Voxel.defineProceduresForType('procedures_defnoreturn') +
128+
Voxel.defineProceduresForType('functional_definition');
114129
};
115130

116-
Voxel.handleWhenLeftClick = function(target) {
117-
evalCode(Blockly.Generator.blockSpaceToCode(
118-
'JavaScript',
119-
'voxel_whenLeftClick'));
131+
Voxel.defineProceduresForType = function(blockType) {
132+
return Blockly.Generator.blockSpaceToCode('JavaScript', blockType);
133+
};
134+
135+
Voxel.evaluateCode = function(code) {
136+
try {
137+
codegen.evalWith(code, {
138+
BlocklyApps: BlocklyApps,
139+
Voxel: api,
140+
Globals: Voxel.Globals
141+
}
142+
);
143+
} catch (e) { }
120144
};
121145

122146
/**
@@ -137,47 +161,13 @@ Voxel.resetButtonClick = function () {
137161

138162
};
139163

140-
141-
function evalCode (code) {
142-
try {
143-
return codegen.evalWith(code, {
144-
BlocklyApps: BlocklyApps,
145-
Voxel: api
146-
});
147-
} catch (e) {
148-
// Infinity is thrown if we detect an infinite loop. In that case we'll
149-
// stop further execution, animate what occured before the infinite loop,
150-
// and analyze success/failure based on what was drawn.
151-
// Otherwise, abnormal termination is a user error.
152-
if (e !== Infinity) {
153-
// call window.onerror so that we get new relic collection. prepend with
154-
// UserCode so that it's clear this is in eval'ed code.
155-
if (window.onerror) {
156-
window.onerror("UserCode:" + e.message, document.URL, 0);
157-
}
158-
if (console && console.log) {
159-
console.log(e);
160-
}
161-
}
162-
}
163-
}
164-
165-
/**
166-
* Execute the user's code. Heaven help us...
167-
*/
168164
Voxel.execute = function() {
169165
Voxel.result = BlocklyApps.ResultType.UNSET;
170166
Voxel.testResults = BlocklyApps.TestResults.NO_TESTS_RUN;
171167
Voxel.message = undefined;
172168

173-
// Run the app
174-
var codeWhenRunButton = Blockly.Generator.blockSpaceToCode(
175-
'JavaScript',
176-
'when_run');
169+
Voxel.evaluateCodeUnderBlockType('when_run');
177170

178-
// Get a result
179-
Voxel.result = evalCode(codeWhenRunButton);
180-
return; // TODO(bjordan): remove
181171
Voxel.testResults = BlocklyApps.getTestResults(Voxel.result);
182172

183173
if (level.freePlay) {
@@ -194,39 +184,71 @@ Voxel.execute = function() {
194184
result: Voxel.result,
195185
testResult: Voxel.testResults,
196186
program: encodeURIComponent(textBlocks),
197-
onComplete: onReportComplete
187+
onComplete: Voxel.onReportComplete
198188
};
199189

200190
BlocklyApps.report(reportData);
201191
};
202192

193+
Voxel.endAttempt = function() {
194+
if (level.freePlay) {
195+
Voxel.result = BlocklyApps.ResultType.SUCCESS;
196+
}
197+
198+
// If we know they succeeded, mark levelComplete true
199+
// Note that we have not yet animated the succesful run
200+
var levelComplete = (Voxel.result == BlocklyApps.ResultType.SUCCESS);
201+
202+
if (level.freePlay) {
203+
Voxel.testResults = BlocklyApps.TestResults.FREE_PLAY;
204+
} else {
205+
Voxel.testResults = BlocklyApps.getTestResults(levelComplete);
206+
}
207+
208+
if (Voxel.testResults >= BlocklyApps.TestResults.FREE_PLAY) {
209+
BlocklyApps.playAudio('win');
210+
} else {
211+
BlocklyApps.playAudio('failure');
212+
}
213+
214+
var xml = Blockly.Xml.blockSpaceToDom(Blockly.mainBlockSpace);
215+
var textBlocks = Blockly.Xml.domToText(xml);
216+
217+
// Report result to server.
218+
BlocklyApps.report({
219+
app: 'voxel',
220+
level: level.id,
221+
result: Voxel.result === BlocklyApps.ResultType.SUCCESS,
222+
testResult: Voxel.testResults,
223+
program: encodeURIComponent(textBlocks),
224+
onComplete: Voxel.onReportComplete
225+
});
226+
};
227+
203228
/**
204229
* App specific displayFeedback function that calls into
205230
* BlocklyApps.displayFeedback when appropriate
206231
*/
207232
var displayFeedback = function(response) {
208-
// override extra top blocks message
209-
level.extraTopBlocks = voxelMsg.extraTopBlocks();
210-
211233
BlocklyApps.displayFeedback({
212234
app: 'Voxel',
213235
skin: skin.id,
214236
feedbackType: Voxel.testResults,
215237
response: response,
216238
level: level,
239+
showingSharing: level.freePlay,
217240
appStrings: {
218-
reinfFeedbackMsg: voxelMsg.reinfFeedbackMsg()
219-
},
241+
reinfFeedbackMsg: voxelMsg.reinfFeedbackMsg(),
242+
sharingText: voxelMsg.shareGame()
243+
}
220244
});
221245
};
222246

223247
/**
224248
* Function to be called when the service report call is complete
225249
* @param {object} JSON response (if available)
226250
*/
227-
function onReportComplete(response) {
228-
// Disable the run button until onReportComplete is called.
229-
var runButton = document.getElementById('runButton');
230-
runButton.disabled = false;
251+
Voxel.onReportComplete = function(response) {
252+
Voxel.response = response;
231253
displayFeedback(response);
232-
}
254+
};

0 commit comments

Comments
 (0)