Switch JavaScript engine to goja
* Switch from otto to goja for JavaScript engine. * goja supports many ES6 syntax features like arrow functions, const/let, for-of with more coming soon. * Same great features as otto, more modern environment for doodads!
This commit is contained in:
parent
d67c1cfcf1
commit
4d08bf1d85
|
@ -47,28 +47,24 @@ Except as contained in this notice, the name of Tavmjong Bah shall not be used i
|
||||||
|
|
||||||
## Go Modules
|
## Go Modules
|
||||||
|
|
||||||
### github.com/robertkrimen/otto
|
### github.com/dop251/goja
|
||||||
|
|
||||||
```
|
```
|
||||||
|
Copyright (c) 2016 Dmitry Panov
|
||||||
|
|
||||||
Copyright (c) 2012 Robert Krimen
|
Copyright (c) 2012 Robert Krimen
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
in the Software without restriction, including without limitation the rights
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### github.com/satori/go.uuid
|
### github.com/satori/go.uuid
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Azulian (Red)
|
|
||||||
// DEPRECATED: they both share azulian.js now.
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
var playerSpeed = 4;
|
|
||||||
var gravity = 4;
|
|
||||||
var Vx = Vy = 0;
|
|
||||||
|
|
||||||
var direction = "right";
|
|
||||||
|
|
||||||
Self.SetHitbox(0, 0, 32, 32)
|
|
||||||
Self.SetMobile(true);
|
|
||||||
Self.SetInventory(true);
|
|
||||||
Self.SetGravity(true);
|
|
||||||
Self.AddAnimation("walk-left", 100, ["red-wl1", "red-wl2", "red-wl3", "red-wl4"]);
|
|
||||||
Self.AddAnimation("walk-right", 100, ["red-wr1", "red-wr2", "red-wr3", "red-wr4"]);
|
|
||||||
|
|
||||||
// Sample our X position every few frames and detect if we've hit a solid wall.
|
|
||||||
var sampleTick = 0;
|
|
||||||
var sampleRate = 5;
|
|
||||||
var lastSampledX = 0;
|
|
||||||
|
|
||||||
setInterval(function () {
|
|
||||||
if (sampleTick % sampleRate === 0) {
|
|
||||||
var curX = Self.Position().X;
|
|
||||||
var delta = Math.abs(curX - lastSampledX);
|
|
||||||
if (delta < 5) {
|
|
||||||
direction = direction === "right" ? "left" : "right";
|
|
||||||
}
|
|
||||||
lastSampledX = curX;
|
|
||||||
}
|
|
||||||
sampleTick++;
|
|
||||||
|
|
||||||
// TODO: Vector() requires floats, pain in the butt for JS,
|
|
||||||
// the JS API should be friendlier and custom...
|
|
||||||
var Vx = parseFloat(playerSpeed * (direction === "left" ? -1 : 1));
|
|
||||||
Self.SetVelocity(Vector(Vx, 0.0));
|
|
||||||
|
|
||||||
if (!Self.IsAnimating()) {
|
|
||||||
Self.PlayAnimation("walk-" + direction, null);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ var playerSpeed = 12,
|
||||||
lastDirection = "right";
|
lastDirection = "right";
|
||||||
|
|
||||||
function setupAnimations(color) {
|
function setupAnimations(color) {
|
||||||
var left = color === 'blue' ? 'blu-wl' : 'red-wl',
|
let left = color === 'blue' ? 'blu-wl' : 'red-wl',
|
||||||
right = color === 'blue' ? 'blu-wr' : 'red-wr',
|
right = color === 'blue' ? 'blu-wr' : 'red-wr',
|
||||||
leftFrames = [left + '1', left + '2', left + '3', left + '4'],
|
leftFrames = [left + '1', left + '2', left + '3', left + '4'],
|
||||||
rightFrames = [right + '1', right + '2', right + '3', right + '4'];
|
rightFrames = [right + '1', right + '2', right + '3', right + '4'];
|
||||||
|
@ -15,7 +15,7 @@ function setupAnimations(color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
var color = Self.GetTag("color");
|
const color = Self.GetTag("color");
|
||||||
playerSpeed = color === 'blue' ? 2 : 4;
|
playerSpeed = color === 'blue' ? 2 : 4;
|
||||||
|
|
||||||
Self.SetMobile(true);
|
Self.SetMobile(true);
|
||||||
|
@ -32,14 +32,14 @@ function main() {
|
||||||
// when it meets resistance.
|
// when it meets resistance.
|
||||||
|
|
||||||
// Sample our X position every few frames and detect if we've hit a solid wall.
|
// Sample our X position every few frames and detect if we've hit a solid wall.
|
||||||
var sampleTick = 0;
|
let sampleTick = 0;
|
||||||
var sampleRate = 5;
|
let sampleRate = 5;
|
||||||
var lastSampledX = 0;
|
let lastSampledX = 0;
|
||||||
|
|
||||||
setInterval(function () {
|
setInterval(() => {
|
||||||
if (sampleTick % sampleRate === 0) {
|
if (sampleTick % sampleRate === 0) {
|
||||||
var curX = Self.Position().X;
|
let curX = Self.Position().X;
|
||||||
var delta = Math.abs(curX - lastSampledX);
|
let delta = Math.abs(curX - lastSampledX);
|
||||||
if (delta < 5) {
|
if (delta < 5) {
|
||||||
direction = direction === "right" ? "left" : "right";
|
direction = direction === "right" ? "left" : "right";
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ function main() {
|
||||||
}
|
}
|
||||||
sampleTick++;
|
sampleTick++;
|
||||||
|
|
||||||
var Vx = parseFloat(playerSpeed * (direction === "left" ? -1 : 1));
|
let Vx = parseFloat(playerSpeed * (direction === "left" ? -1 : 1));
|
||||||
Self.SetVelocity(Vector(Vx, 0.0));
|
Self.SetVelocity(Vector(Vx, 0.0));
|
||||||
|
|
||||||
// If we changed directions, stop animating now so we can
|
// If we changed directions, stop animating now so we can
|
||||||
|
@ -66,7 +66,7 @@ function main() {
|
||||||
|
|
||||||
function playerControls() {
|
function playerControls() {
|
||||||
// Note: player speed is controlled by the engine.
|
// Note: player speed is controlled by the engine.
|
||||||
Events.OnKeypress(function (ev) {
|
Events.OnKeypress((ev) => {
|
||||||
if (ev.Right) {
|
if (ev.Right) {
|
||||||
if (!Self.IsAnimating()) {
|
if (!Self.IsAnimating()) {
|
||||||
Self.PlayAnimation("walk-right", null);
|
Self.PlayAnimation("walk-right", null);
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
// Bird
|
// Bird
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
var speed = 4;
|
let speed = 4,
|
||||||
var Vx = Vy = 0;
|
Vx = Vy = 0,
|
||||||
var altitude = Self.Position().Y; // original height in the level
|
altitude = Self.Position().Y; // original height in the level
|
||||||
|
|
||||||
var direction = "left",
|
let direction = "left",
|
||||||
lastDirection = "left";
|
lastDirection = "left";
|
||||||
var states = {
|
let states = {
|
||||||
flying: 0,
|
flying: 0,
|
||||||
diving: 1,
|
diving: 1,
|
||||||
};
|
};
|
||||||
var state = states.flying;
|
let state = states.flying;
|
||||||
|
|
||||||
Self.SetMobile(true);
|
Self.SetMobile(true);
|
||||||
Self.SetGravity(false);
|
Self.SetGravity(false);
|
||||||
|
@ -24,22 +24,22 @@ function main() {
|
||||||
return player();
|
return player();
|
||||||
}
|
}
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (e.Actor.IsMobile() && e.InHitbox) {
|
if (e.Actor.IsMobile() && e.InHitbox) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sample our X position every few frames and detect if we've hit a solid wall.
|
// Sample our X position every few frames and detect if we've hit a solid wall.
|
||||||
var sampleTick = 0;
|
let sampleTick = 0,
|
||||||
var sampleRate = 2;
|
sampleRate = 2,
|
||||||
var lastSampledX = 0;
|
lastSampledX = 0,
|
||||||
var lastSampledY = 0;
|
lastSampledY = 0;
|
||||||
|
|
||||||
setInterval(function () {
|
setInterval(() => {
|
||||||
if (sampleTick % sampleRate === 0) {
|
if (sampleTick % sampleRate === 0) {
|
||||||
var curX = Self.Position().X;
|
let curX = Self.Position().X;
|
||||||
var delta = Math.abs(curX - lastSampledX);
|
let delta = Math.abs(curX - lastSampledX);
|
||||||
if (delta < 5) {
|
if (delta < 5) {
|
||||||
direction = direction === "right" ? "left" : "right";
|
direction = direction === "right" ? "left" : "right";
|
||||||
}
|
}
|
||||||
|
@ -48,15 +48,15 @@ function main() {
|
||||||
sampleTick++;
|
sampleTick++;
|
||||||
|
|
||||||
// If we are not flying at our original altitude, correct for that.
|
// If we are not flying at our original altitude, correct for that.
|
||||||
var curV = Self.Position();
|
let curV = Self.Position();
|
||||||
var Vy = 0.0;
|
let Vy = 0.0;
|
||||||
if (curV.Y != altitude) {
|
if (curV.Y != altitude) {
|
||||||
Vy = curV.Y < altitude ? 1 : -1;
|
Vy = curV.Y < altitude ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Vector() requires floats, pain in the butt for JS,
|
// TODO: Vector() requires floats, pain in the butt for JS,
|
||||||
// the JS API should be friendlier and custom...
|
// the JS API should be friendlier and custom...
|
||||||
var Vx = parseFloat(speed * (direction === "left" ? -1 : 1));
|
let Vx = parseFloat(speed * (direction === "left" ? -1 : 1));
|
||||||
Self.SetVelocity(Vector(Vx, Vy));
|
Self.SetVelocity(Vector(Vx, Vy));
|
||||||
|
|
||||||
// If we changed directions, stop animating now so we can
|
// If we changed directions, stop animating now so we can
|
||||||
|
@ -76,7 +76,7 @@ function main() {
|
||||||
// If under control of the player character.
|
// If under control of the player character.
|
||||||
function player() {
|
function player() {
|
||||||
Self.SetInventory(true);
|
Self.SetInventory(true);
|
||||||
Events.OnKeypress(function (ev) {
|
Events.OnKeypress((ev) => {
|
||||||
Vx = 0;
|
Vx = 0;
|
||||||
Vy = 0;
|
Vy = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
// Pushable Box.
|
// Pushable Box.
|
||||||
var speed = 4;
|
|
||||||
var size = 75;
|
const speed = 4,
|
||||||
|
size = 75;
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
Self.SetMobile(true);
|
Self.SetMobile(true);
|
||||||
Self.SetGravity(true);
|
Self.SetGravity(true);
|
||||||
Self.SetHitbox(0, 0, size, size);
|
Self.SetHitbox(0, 0, size, size);
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
// Ignore events from neighboring Boxes.
|
// Ignore events from neighboring Boxes.
|
||||||
if (e.Actor.Actor.Filename === "box.doodad") {
|
if (e.Actor.Actor.Filename === "box.doodad") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.Actor.IsMobile() && e.InHitbox) {
|
if (e.Actor.IsMobile() && e.InHitbox) {
|
||||||
var overlap = e.Overlap;
|
let overlap = e.Overlap;
|
||||||
|
|
||||||
if (overlap.Y === 0 && !(overlap.X === 0 && overlap.W < 5) && !(overlap.X === size)) {
|
if (overlap.Y === 0 && !(overlap.X === 0 && overlap.W < 5) && !(overlap.X === size)) {
|
||||||
// Standing on top, ignore.
|
// Standing on top, ignore.
|
||||||
|
@ -39,8 +40,8 @@ function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// When we receive power, we reset to our original position.
|
// When we receive power, we reset to our original position.
|
||||||
var origPoint = Self.Position();
|
let origPoint = Self.Position();
|
||||||
Message.Subscribe("power", function (powered) {
|
Message.Subscribe("power", (powered) => {
|
||||||
Self.MoveTo(origPoint);
|
Self.MoveTo(origPoint);
|
||||||
Self.SetVelocity(Vector(0, 0));
|
Self.SetVelocity(Vector(0, 0));
|
||||||
});
|
});
|
||||||
|
@ -52,8 +53,8 @@ function main() {
|
||||||
function animate() {
|
function animate() {
|
||||||
Self.AddAnimation("animate", 100, [0, 1, 2, 3, 2, 1]);
|
Self.AddAnimation("animate", 100, [0, 1, 2, 3, 2, 1]);
|
||||||
|
|
||||||
var running = false;
|
let running = false;
|
||||||
setInterval(function () {
|
setInterval(() => {
|
||||||
if (!running) {
|
if (!running) {
|
||||||
running = true;
|
running = true;
|
||||||
Self.PlayAnimation("animate", function () {
|
Self.PlayAnimation("animate", function () {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
const playerSpeed = 12;
|
||||||
|
|
||||||
|
let Vx = Vy = 0,
|
||||||
|
animating = false,
|
||||||
|
animStart = animEnd = 0;
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
var playerSpeed = 12;
|
|
||||||
var Vx = Vy = 0;
|
|
||||||
|
|
||||||
var animating = false;
|
|
||||||
var animStart = animEnd = 0;
|
|
||||||
|
|
||||||
Self.SetMobile(true);
|
Self.SetMobile(true);
|
||||||
Self.SetInventory(true);
|
Self.SetInventory(true);
|
||||||
Self.SetGravity(true);
|
Self.SetGravity(true);
|
||||||
|
@ -13,13 +13,13 @@ function main() {
|
||||||
Self.AddAnimation("walk-right", 200, ["stand-right", "walk-right-1", "walk-right-2", "walk-right-3", "walk-right-2", "walk-right-1"]);
|
Self.AddAnimation("walk-right", 200, ["stand-right", "walk-right-1", "walk-right-2", "walk-right-3", "walk-right-2", "walk-right-1"]);
|
||||||
|
|
||||||
// If the player suddenly changes direction, reset the animation state to quickly switch over.
|
// If the player suddenly changes direction, reset the animation state to quickly switch over.
|
||||||
var lastVelocity = Vector(0, 0);
|
let lastVelocity = Vector(0, 0);
|
||||||
|
|
||||||
Events.OnKeypress(function (ev) {
|
Events.OnKeypress((ev) => {
|
||||||
Vx = 0;
|
Vx = 0;
|
||||||
Vy = 0;
|
Vy = 0;
|
||||||
|
|
||||||
var curVelocity = Self.GetVelocity();
|
let curVelocity = Self.GetVelocity();
|
||||||
if ((lastVelocity.X < 0 && curVelocity.X > 0) ||
|
if ((lastVelocity.X < 0 && curVelocity.X > 0) ||
|
||||||
(lastVelocity.X > 0 && curVelocity.X < 0)) {
|
(lastVelocity.X > 0 && curVelocity.X < 0)) {
|
||||||
Self.StopAnimation();
|
Self.StopAnimation();
|
||||||
|
@ -40,7 +40,5 @@ function main() {
|
||||||
Self.StopAnimation();
|
Self.StopAnimation();
|
||||||
animating = false;
|
animating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Self.SetVelocity(Point(Vx, Vy));
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
function main() {
|
function main() {
|
||||||
var timer = 0;
|
let timer = 0;
|
||||||
var pressed = false;
|
let pressed = false;
|
||||||
|
|
||||||
// Has a linked Sticky Button been pressed permanently down?
|
// Has a linked Sticky Button been pressed permanently down?
|
||||||
var stickyDown = false;
|
let stickyDown = false;
|
||||||
Message.Subscribe("sticky:down", function (down) {
|
Message.Subscribe("sticky:down", (down) => {
|
||||||
stickyDown = down;
|
stickyDown = down;
|
||||||
Self.ShowLayer(stickyDown ? 1 : 0);
|
Self.ShowLayer(stickyDown ? 1 : 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Track who all is colliding with us.
|
// Track who all is colliding with us.
|
||||||
var colliders = {};
|
let colliders = {};
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ function main() {
|
||||||
Self.ShowLayer(1);
|
Self.ShowLayer(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnLeave(function (e) {
|
Events.OnLeave((e) => {
|
||||||
delete colliders[e.Actor.ID()];
|
delete colliders[e.Actor.ID()];
|
||||||
|
|
||||||
if (Object.keys(colliders).length === 0 && !stickyDown) {
|
if (Object.keys(colliders).length === 0 && !stickyDown) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
function main() {
|
function main() {
|
||||||
var pressed = false;
|
let pressed = false;
|
||||||
|
|
||||||
// When a sticky button receives power, it pops back up.
|
// When a sticky button receives power, it pops back up.
|
||||||
Message.Subscribe("power", function (powered) {
|
Message.Subscribe("power", (powered) => {
|
||||||
if (powered && pressed) {
|
if (powered && pressed) {
|
||||||
Self.ShowLayer(0);
|
Self.ShowLayer(0);
|
||||||
pressed = false;
|
pressed = false;
|
||||||
|
@ -12,7 +12,7 @@ function main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,19 +6,16 @@ function main() {
|
||||||
Self.AddAnimation("fall", 100, ["fall1", "fall2", "fall3", "fall4"]);
|
Self.AddAnimation("fall", 100, ["fall1", "fall2", "fall3", "fall4"]);
|
||||||
|
|
||||||
// Recover time for the floor to respawn.
|
// Recover time for the floor to respawn.
|
||||||
var recover = 5000;
|
let recover = 5000;
|
||||||
|
|
||||||
// States of the floor.
|
// States of the floor.
|
||||||
var stateSolid = 0;
|
let stateSolid = 0;
|
||||||
var stateShaking = 1;
|
let stateShaking = 1;
|
||||||
var stateFalling = 2;
|
let stateFalling = 2;
|
||||||
var stateFallen = 3;
|
let stateFallen = 3;
|
||||||
var state = stateSolid;
|
let state = stateSolid;
|
||||||
|
|
||||||
// Started the animation?
|
Events.OnCollide((e) => {
|
||||||
var startedAnimation = false;
|
|
||||||
|
|
||||||
Events.OnCollide(function(e) {
|
|
||||||
|
|
||||||
// If the floor is falling, the player passes right thru.
|
// If the floor is falling, the player passes right thru.
|
||||||
if (state === stateFalling || state === stateFallen) {
|
if (state === stateFalling || state === stateFallen) {
|
||||||
|
@ -40,15 +37,15 @@ function main() {
|
||||||
// Begin the animation sequence if we're in the solid state.
|
// Begin the animation sequence if we're in the solid state.
|
||||||
if (state === stateSolid) {
|
if (state === stateSolid) {
|
||||||
state = stateShaking;
|
state = stateShaking;
|
||||||
Self.PlayAnimation("shake", function() {
|
Self.PlayAnimation("shake", () => {
|
||||||
state = stateFalling;
|
state = stateFalling;
|
||||||
Self.PlayAnimation("fall", function() {
|
Self.PlayAnimation("fall", () => {
|
||||||
Sound.Play("crumbly-break.wav")
|
Sound.Play("crumbly-break.wav")
|
||||||
state = stateFallen;
|
state = stateFallen;
|
||||||
Self.ShowLayerNamed("fallen");
|
Self.ShowLayerNamed("fallen");
|
||||||
|
|
||||||
// Recover after a while.
|
// Recover after a while.
|
||||||
setTimeout(function() {
|
setTimeout(() => {
|
||||||
Self.ShowLayer(0);
|
Self.ShowLayer(0);
|
||||||
state = stateSolid;
|
state = stateSolid;
|
||||||
}, recover);
|
}, recover);
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
function main() {
|
// Colored Locked Doors.
|
||||||
var color = Self.GetTag("color");
|
|
||||||
var keyname = color === "small" ? "small-key.doodad" : "key-" + color + ".doodad";
|
|
||||||
|
|
||||||
|
const color = Self.GetTag("color"),
|
||||||
|
keyname = color === "small" ? "small-key.doodad" : "key-" + color + ".doodad";
|
||||||
|
|
||||||
|
function main() {
|
||||||
// Layers in the doodad image.
|
// Layers in the doodad image.
|
||||||
var layer = {
|
let layer = {
|
||||||
closed: 0,
|
closed: 0,
|
||||||
unlocked: 1,
|
unlocked: 1,
|
||||||
right: 2,
|
right: 2,
|
||||||
|
@ -11,13 +13,13 @@ function main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Variables that change in event handler.
|
// Variables that change in event handler.
|
||||||
var unlocked = false; // Key has been used to unlock the door (one time).
|
let unlocked = false; // Key has been used to unlock the door (one time).
|
||||||
var opened = false; // If door is currently showing its opened state.
|
let opened = false; // If door is currently showing its opened state.
|
||||||
var enterSide = 0; // Side of player entering the door, -1 or 1, left or right.
|
let enterSide = 0; // Side of player entering the door, -1 or 1, left or right.
|
||||||
|
|
||||||
Self.SetHitbox(34, 0, 13, 76);
|
Self.SetHitbox(34, 0, 13, 76);
|
||||||
|
|
||||||
Events.OnCollide(function(e) {
|
Events.OnCollide((e) => {
|
||||||
// Record the side that this actor has touched us, in case the door
|
// Record the side that this actor has touched us, in case the door
|
||||||
// needs to open.
|
// needs to open.
|
||||||
if (enterSide === 0) {
|
if (enterSide === 0) {
|
||||||
|
@ -37,7 +39,7 @@ function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do they have our key?
|
// Do they have our key?
|
||||||
var hasKey = e.Actor.HasItem(keyname) >= 0;
|
let hasKey = e.Actor.HasItem(keyname) >= 0;
|
||||||
if (!hasKey) {
|
if (!hasKey) {
|
||||||
// Door is locked.
|
// Door is locked.
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,7 +57,7 @@ function main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Events.OnLeave(function(e) {
|
Events.OnLeave((e) => {
|
||||||
Self.ShowLayer(unlocked ? layer.unlocked : layer.closed);
|
Self.ShowLayer(unlocked ? layer.unlocked : layer.closed);
|
||||||
// Sound.Play("door-close.wav")
|
// Sound.Play("door-close.wav")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
var animating = false;
|
// Electric Door
|
||||||
var opened = false;
|
|
||||||
var powerState = false;
|
let animating = false;
|
||||||
|
let opened = false;
|
||||||
|
let powerState = false;
|
||||||
|
|
||||||
// Function to handle the door opening or closing.
|
// Function to handle the door opening or closing.
|
||||||
function setPoweredState(powered) {
|
function setPoweredState(powered) {
|
||||||
|
@ -13,14 +15,14 @@ function setPoweredState(powered) {
|
||||||
|
|
||||||
animating = true;
|
animating = true;
|
||||||
Sound.Play("electric-door.wav")
|
Sound.Play("electric-door.wav")
|
||||||
Self.PlayAnimation("open", function () {
|
Self.PlayAnimation("open", () => {
|
||||||
opened = true;
|
opened = true;
|
||||||
animating = false;
|
animating = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
animating = true;
|
animating = true;
|
||||||
Sound.Play("electric-door.wav")
|
Sound.Play("electric-door.wav")
|
||||||
Self.PlayAnimation("close", function () {
|
Self.PlayAnimation("close", () => {
|
||||||
opened = false;
|
opened = false;
|
||||||
animating = false;
|
animating = false;
|
||||||
})
|
})
|
||||||
|
@ -31,7 +33,6 @@ function main() {
|
||||||
Self.AddAnimation("open", 100, [0, 1, 2, 3]);
|
Self.AddAnimation("open", 100, [0, 1, 2, 3]);
|
||||||
Self.AddAnimation("close", 100, [3, 2, 1, 0]);
|
Self.AddAnimation("close", 100, [3, 2, 1, 0]);
|
||||||
|
|
||||||
|
|
||||||
Self.SetHitbox(0, 0, 34, 76);
|
Self.SetHitbox(0, 0, 34, 76);
|
||||||
|
|
||||||
// A linked Switch that activates the door will send the Toggle signal
|
// A linked Switch that activates the door will send the Toggle signal
|
||||||
|
@ -39,13 +40,13 @@ function main() {
|
||||||
// state on this signal, and ignore the very next Power signal. Ordinary
|
// state on this signal, and ignore the very next Power signal. Ordinary
|
||||||
// power sources like Buttons will work as normal, as they emit only a power
|
// power sources like Buttons will work as normal, as they emit only a power
|
||||||
// signal.
|
// signal.
|
||||||
var ignoreNextPower = false;
|
let ignoreNextPower = false;
|
||||||
Message.Subscribe("switch:toggle", function (powered) {
|
Message.Subscribe("switch:toggle", (powered) => {
|
||||||
ignoreNextPower = true;
|
ignoreNextPower = true;
|
||||||
setPoweredState(!powerState);
|
setPoweredState(!powerState);
|
||||||
})
|
})
|
||||||
|
|
||||||
Message.Subscribe("power", function (powered) {
|
Message.Subscribe("power", (powered) => {
|
||||||
if (ignoreNextPower) {
|
if (ignoreNextPower) {
|
||||||
ignoreNextPower = false;
|
ignoreNextPower = false;
|
||||||
return;
|
return;
|
||||||
|
@ -54,7 +55,7 @@ function main() {
|
||||||
setPoweredState(powered);
|
setPoweredState(powered);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (e.InHitbox) {
|
if (e.InHitbox) {
|
||||||
if (!opened) {
|
if (!opened) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
function main() {
|
// Colored Keys and Small Key
|
||||||
var color = Self.GetTag("color");
|
|
||||||
var quantity = color === "small" ? 1 : 0;
|
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
const color = Self.GetTag("color"),
|
||||||
|
quantity = color === "small" ? 1 : 0;
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
Events.OnCollide((e) => {
|
||||||
if (e.Settled) {
|
if (e.Settled) {
|
||||||
if (e.Actor.HasInventory()) {
|
if (e.Actor.HasInventory()) {
|
||||||
// If we don't have a quantity, and the actor already has
|
// If we don't have a quantity, and the actor already has
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
// DEPRECATED: old locked door script. Superceded by colored-door.js.
|
|
||||||
function main() {
|
|
||||||
Self.AddAnimation("open", 0, [1]);
|
|
||||||
var unlocked = false;
|
|
||||||
var color = Self.GetTag("color");
|
|
||||||
|
|
||||||
Self.SetHitbox(16, 0, 32, 64);
|
|
||||||
|
|
||||||
Events.OnCollide(function(e) {
|
|
||||||
if (unlocked) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.InHitbox) {
|
|
||||||
var data = e.Actor.GetData("key:" + color);
|
|
||||||
if (data === "") {
|
|
||||||
// Door is locked.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Settled) {
|
|
||||||
unlocked = true;
|
|
||||||
Self.PlayAnimation("open", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -8,9 +8,9 @@ function main() {
|
||||||
Self.SetGravity(true);
|
Self.SetGravity(true);
|
||||||
|
|
||||||
// Monitor our Y position to tell if we've been falling.
|
// Monitor our Y position to tell if we've been falling.
|
||||||
var lastPoint = Self.Position();
|
let lastPoint = Self.Position();
|
||||||
setInterval(function () {
|
setInterval(() => {
|
||||||
var nowAt = Self.Position();
|
let nowAt = Self.Position();
|
||||||
if (nowAt.Y > lastPoint.Y) {
|
if (nowAt.Y > lastPoint.Y) {
|
||||||
falling = true;
|
falling = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,7 +19,7 @@ function main() {
|
||||||
lastPoint = nowAt;
|
lastPoint = nowAt;
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,8 @@ function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// When we receive power, we reset to our original position.
|
// When we receive power, we reset to our original position.
|
||||||
var origPoint = Self.Position();
|
let origPoint = Self.Position();
|
||||||
Message.Subscribe("power", function (powered) {
|
Message.Subscribe("power", (powered) => {
|
||||||
Self.MoveTo(origPoint);
|
Self.MoveTo(origPoint);
|
||||||
Self.SetVelocity(Vector(0, 0));
|
Self.SetVelocity(Vector(0, 0));
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,11 +7,11 @@ function main() {
|
||||||
|
|
||||||
// Checkpoints broadcast to all of their peers so they all
|
// Checkpoints broadcast to all of their peers so they all
|
||||||
// know which one is the most recently activated.
|
// know which one is the most recently activated.
|
||||||
Message.Subscribe("broadcast:checkpoint", function (currentID) {
|
Message.Subscribe("broadcast:checkpoint", (currentID) => {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
function main() {
|
function main() {
|
||||||
Self.SetHitbox(22 + 16, 16, 75 - 16, 86);
|
Self.SetHitbox(22 + 16, 16, 75 - 16, 86);
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@ function main() {
|
||||||
|
|
||||||
// Linking a doodad to the Start Flag sets the
|
// Linking a doodad to the Start Flag sets the
|
||||||
// player character. Destroy the original doodads.
|
// player character. Destroy the original doodads.
|
||||||
var links = Self.GetLinks();
|
for (var link of Self.GetLinks()) {
|
||||||
for (var i = 0; i < links.length; i++) {
|
link.Destroy();
|
||||||
links[i].Destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ function main() {
|
||||||
Self.SetHitbox(0, 0, 42, 42);
|
Self.SetHitbox(0, 0, 42, 42);
|
||||||
|
|
||||||
// Blue block is ON by default.
|
// Blue block is ON by default.
|
||||||
var state = true;
|
let state = true;
|
||||||
|
|
||||||
Message.Subscribe("broadcast:state-change", function(newState) {
|
Message.Subscribe("broadcast:state-change", (newState) => {
|
||||||
state = !newState;
|
state = !newState;
|
||||||
|
|
||||||
// Layer 0: ON
|
// Layer 0: ON
|
||||||
|
@ -13,7 +13,7 @@ function main() {
|
||||||
Self.ShowLayer(state ? 0 : 1);
|
Self.ShowLayer(state ? 0 : 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function(e) {
|
Events.OnCollide((e) => {
|
||||||
if (e.Actor.IsMobile() && e.InHitbox) {
|
if (e.Actor.IsMobile() && e.InHitbox) {
|
||||||
if (state) {
|
if (state) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -3,9 +3,9 @@ function main() {
|
||||||
Self.SetHitbox(0, 0, 42, 42);
|
Self.SetHitbox(0, 0, 42, 42);
|
||||||
|
|
||||||
// Orange block is OFF by default.
|
// Orange block is OFF by default.
|
||||||
var state = false;
|
let state = false;
|
||||||
|
|
||||||
Message.Subscribe("broadcast:state-change", function(newState) {
|
Message.Subscribe("broadcast:state-change", (newState) => {
|
||||||
state = newState;
|
state = newState;
|
||||||
|
|
||||||
// Layer 0: OFF
|
// Layer 0: OFF
|
||||||
|
@ -13,7 +13,7 @@ function main() {
|
||||||
Self.ShowLayer(state ? 1 : 0);
|
Self.ShowLayer(state ? 1 : 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function(e) {
|
Events.OnCollide((e) => {
|
||||||
if (e.Actor.IsMobile() && e.InHitbox) {
|
if (e.Actor.IsMobile() && e.InHitbox) {
|
||||||
if (state) {
|
if (state) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
// State Block Control Button
|
// State Block Control Button
|
||||||
|
|
||||||
// Button is "OFF" by default.
|
// Button is "OFF" by default.
|
||||||
var state = false;
|
let state = false;
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
Self.SetHitbox(0, 0, 42, 42);
|
Self.SetHitbox(0, 0, 42, 42);
|
||||||
|
|
||||||
// When the button is activated, don't keep toggling state until we're not
|
// When the button is activated, don't keep toggling state until we're not
|
||||||
// being touched again.
|
// being touched again.
|
||||||
var colliding = false;
|
let colliding = false;
|
||||||
|
|
||||||
// If we receive a state change event from a DIFFERENT on/off button, update
|
// If we receive a state change event from a DIFFERENT on/off button, update
|
||||||
// ourself to match the state received.
|
// ourself to match the state received.
|
||||||
Message.Subscribe("broadcast:state-change", function(value) {
|
Message.Subscribe("broadcast:state-change", (value) => {
|
||||||
state = value;
|
state = value;
|
||||||
showSprite();
|
showSprite();
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function(e) {
|
Events.OnCollide((e) => {
|
||||||
if (colliding) {
|
if (colliding) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ function main() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnLeave(function(e) {
|
Events.OnLeave((e) => {
|
||||||
colliding = false;
|
colliding = false;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@ function main() {
|
||||||
|
|
||||||
// Checkpoints broadcast to all of their peers so they all
|
// Checkpoints broadcast to all of their peers so they all
|
||||||
// know which one is the most recently activated.
|
// know which one is the most recently activated.
|
||||||
Message.Subscribe("broadcast:checkpoint", function (currentID) {
|
Message.Subscribe("broadcast:checkpoint", (currentID) => {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (isCurrentCheckpoint || !e.Settled) {
|
if (isCurrentCheckpoint || !e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
function main() {
|
function main() {
|
||||||
Self.Hide();
|
Self.Hide();
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
function main() {
|
function main() {
|
||||||
Self.Hide();
|
Self.Hide();
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ function main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Message.Subscribe("broadcast:ready", function () {
|
Message.Subscribe("broadcast:ready", () => {
|
||||||
Message.Publish("switch:toggle", true);
|
Message.Publish("switch:toggle", true);
|
||||||
Message.Publish("power", true);
|
Message.Publish("power", true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
function main() {
|
function main() {
|
||||||
Self.Hide();
|
Self.Hide();
|
||||||
|
|
||||||
var active = true,
|
let active = true,
|
||||||
timeout = 250,
|
timeout = 250,
|
||||||
ms = Self.GetTag("ms");
|
ms = Self.GetTag("ms");
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ function main() {
|
||||||
timeout = parseInt(ms);
|
timeout = parseInt(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!active || !e.Settled) {
|
if (!active || !e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ function main() {
|
||||||
if (e.InHitbox) {
|
if (e.InHitbox) {
|
||||||
// Grab hold of the player.
|
// Grab hold of the player.
|
||||||
e.Actor.Freeze();
|
e.Actor.Freeze();
|
||||||
setTimeout(function () {
|
setTimeout(() => {
|
||||||
e.Actor.Unfreeze();
|
e.Actor.Unfreeze();
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset the trap if powered by a button.
|
// Reset the trap if powered by a button.
|
||||||
Message.Subscribe("power", function (powered) {
|
Message.Subscribe("power", (powered) => {
|
||||||
active = true;
|
active = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,15 @@ function main() {
|
||||||
// 0: Off
|
// 0: Off
|
||||||
// 1: On
|
// 1: On
|
||||||
|
|
||||||
var state = false;
|
let state = false;
|
||||||
var collide = false;
|
let collide = false;
|
||||||
|
|
||||||
Message.Subscribe("power", function (powered) {
|
Message.Subscribe("power", (powered) => {
|
||||||
state = powered;
|
state = powered;
|
||||||
showState(state);
|
showState(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
if (!e.Settled || !e.Actor.IsMobile()) {
|
if (!e.Settled || !e.Actor.IsMobile()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ function main() {
|
||||||
Sound.Play("button-down.wav")
|
Sound.Play("button-down.wav")
|
||||||
state = !state;
|
state = !state;
|
||||||
|
|
||||||
var nonce = Math.random() * 2147483647;
|
|
||||||
Message.Publish("switch:toggle", state);
|
Message.Publish("switch:toggle", state);
|
||||||
Message.Publish("power", state);
|
Message.Publish("power", state);
|
||||||
showState(state);
|
showState(state);
|
||||||
|
@ -30,7 +29,7 @@ function main() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnLeave(function (e) {
|
Events.OnLeave((e) => {
|
||||||
collide = false;
|
collide = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ function main() {
|
||||||
// Common "steal" power between playable and A.I. thieves.
|
// Common "steal" power between playable and A.I. thieves.
|
||||||
function stealable() {
|
function stealable() {
|
||||||
// Steals your items.
|
// Steals your items.
|
||||||
Events.OnCollide(function (e) {
|
Events.OnCollide((e) => {
|
||||||
var victim = e.Actor;
|
let victim = e.Actor;
|
||||||
if (!e.Settled) {
|
if (!e.Settled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -33,17 +33,17 @@ function stealable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steal inventory
|
// Steal inventory
|
||||||
var stolen = 0;
|
let stolen = 0;
|
||||||
if (victim.HasInventory()) {
|
if (victim.HasInventory()) {
|
||||||
var myInventory = Self.Inventory(),
|
let myInventory = Self.Inventory(),
|
||||||
theirInventory = victim.Inventory();
|
theirInventory = victim.Inventory();
|
||||||
|
|
||||||
for (var key in theirInventory) {
|
for (let key in theirInventory) {
|
||||||
if (!theirInventory.hasOwnProperty(key)) {
|
if (!theirInventory.hasOwnProperty(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = theirInventory[key];
|
let value = theirInventory[key];
|
||||||
if (value > 0 || myInventory[key] === undefined) {
|
if (value > 0 || myInventory[key] === undefined) {
|
||||||
victim.RemoveItem(key, value);
|
victim.RemoveItem(key, value);
|
||||||
Self.AddItem(key, value);
|
Self.AddItem(key, value);
|
||||||
|
@ -68,7 +68,7 @@ function stealable() {
|
||||||
// when it encounters and obstacle.
|
// when it encounters and obstacle.
|
||||||
function ai() {
|
function ai() {
|
||||||
// Walks back and forth.
|
// Walks back and forth.
|
||||||
var Vx = Vy = 0.0,
|
let Vx = Vy = 0.0,
|
||||||
playerSpeed = 4,
|
playerSpeed = 4,
|
||||||
direction = "right",
|
direction = "right",
|
||||||
lastDirection = "right",
|
lastDirection = "right",
|
||||||
|
@ -76,9 +76,9 @@ function ai() {
|
||||||
sampleTick = 0,
|
sampleTick = 0,
|
||||||
sampleRate = 2;
|
sampleRate = 2;
|
||||||
|
|
||||||
setInterval(function () {
|
setInterval(() => {
|
||||||
if (sampleTick % sampleRate === 0) {
|
if (sampleTick % sampleRate === 0) {
|
||||||
var curX = Self.Position().X,
|
let curX = Self.Position().X,
|
||||||
delta = Math.abs(curX - lastSampledX);
|
delta = Math.abs(curX - lastSampledX);
|
||||||
if (delta < 5) {
|
if (delta < 5) {
|
||||||
direction = direction === "right" ? "left" : "right";
|
direction = direction === "right" ? "left" : "right";
|
||||||
|
@ -106,7 +106,7 @@ function ai() {
|
||||||
|
|
||||||
// If under control of the player character.
|
// If under control of the player character.
|
||||||
function playable() {
|
function playable() {
|
||||||
Events.OnKeypress(function (ev) {
|
Events.OnKeypress((ev) => {
|
||||||
Vx = 0;
|
Vx = 0;
|
||||||
Vy = 0;
|
Vy = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
function main() {
|
|
||||||
var timer = 0;
|
|
||||||
|
|
||||||
Self.SetHitbox(0, 0, 72, 6);
|
|
||||||
|
|
||||||
var animationSpeed = 100;
|
|
||||||
var opened = false;
|
|
||||||
Self.AddAnimation("open", animationSpeed, ["down1", "down2", "down3", "down4"]);
|
|
||||||
Self.AddAnimation("close", animationSpeed, ["down4", "down3", "down2", "down1"]);
|
|
||||||
|
|
||||||
Events.OnCollide( function(e) {
|
|
||||||
if (opened) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the actor colliding our solid part?
|
|
||||||
if (e.InHitbox) {
|
|
||||||
// Touching the top or the bottom?
|
|
||||||
if (e.Overlap.Y > 0) {
|
|
||||||
return false; // solid wall when touched from below
|
|
||||||
} else {
|
|
||||||
opened = true;
|
|
||||||
Self.PlayAnimation("open", function() {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Events.OnLeave(function() {
|
|
||||||
if (opened) {
|
|
||||||
Self.PlayAnimation("close", function() {
|
|
||||||
opened = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
// Trapdoors.
|
||||||
|
|
||||||
|
// What direction is the trapdoor facing?
|
||||||
|
const direction = Self.GetTag("direction");
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
// What direction is the trapdoor facing?
|
|
||||||
var direction = Self.GetTag("direction");
|
|
||||||
|
|
||||||
var timer = 0;
|
|
||||||
|
|
||||||
// Set our hitbox based on our orientation.
|
// Set our hitbox based on our orientation.
|
||||||
var thickness = 10;
|
let thickness = 10;
|
||||||
var doodadSize = 86;
|
let doodadSize = 86;
|
||||||
if (direction === "left") {
|
if (direction === "left") {
|
||||||
Self.SetHitbox(48, 0, doodadSize, doodadSize);
|
Self.SetHitbox(48, 0, doodadSize, doodadSize);
|
||||||
} else if (direction === "right") {
|
} else if (direction === "right") {
|
||||||
|
@ -17,12 +17,12 @@ function main() {
|
||||||
Self.SetHitbox(0, 0, doodadSize, thickness);
|
Self.SetHitbox(0, 0, doodadSize, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
var animationSpeed = 100;
|
let animationSpeed = 100;
|
||||||
var opened = false;
|
let opened = false;
|
||||||
|
|
||||||
// Register our animations.
|
// Register our animations.
|
||||||
var frames = [];
|
let frames = [];
|
||||||
for (var i = 1; i <= 4; i++) {
|
for (let i = 1; i <= 4; i++) {
|
||||||
frames.push(direction + i);
|
frames.push(direction + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ function main() {
|
||||||
frames.reverse();
|
frames.reverse();
|
||||||
Self.AddAnimation("close", animationSpeed, frames);
|
Self.AddAnimation("close", animationSpeed, frames);
|
||||||
|
|
||||||
Events.OnCollide( function(e) {
|
Events.OnCollide((e) => {
|
||||||
if (opened) {
|
if (opened) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -78,9 +78,9 @@ function main() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.OnLeave(function() {
|
Events.OnLeave(() => {
|
||||||
if (opened) {
|
if (opened) {
|
||||||
Self.PlayAnimation("close", function() {
|
Self.PlayAnimation("close", () => {
|
||||||
opened = false;
|
opened = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// Warp Doors
|
// Warp Doors
|
||||||
|
|
||||||
|
const color = Self.GetTag("color"),
|
||||||
|
isStateDoor = color === 'blue' || color === 'orange';
|
||||||
|
|
||||||
|
// State in case we're a blue warp door.
|
||||||
|
let state = color === 'blue',
|
||||||
|
animating = false,
|
||||||
|
collide = false;
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
// Are we a blue or orange door? Regular warp door will be 'none'
|
|
||||||
var color = Self.GetTag("color");
|
|
||||||
var isStateDoor = color === 'blue' || color === 'orange';
|
|
||||||
var state = color === 'blue'; // Blue door is ON by default.
|
|
||||||
|
|
||||||
var animating = false;
|
|
||||||
var collide = false;
|
|
||||||
|
|
||||||
// Declare animations and sprite names.
|
// Declare animations and sprite names.
|
||||||
var animSpeed = 100;
|
let animSpeed = 100;
|
||||||
var spriteDefault, spriteDisabled; // the latter for state doors.
|
let spriteDefault, spriteDisabled; // the latter for state doors.
|
||||||
if (color === 'blue') {
|
if (color === 'blue') {
|
||||||
Self.AddAnimation("open", animSpeed, ["blue-2", "blue-3", "blue-4"]);
|
Self.AddAnimation("open", animSpeed, ["blue-2", "blue-3", "blue-4"]);
|
||||||
Self.AddAnimation("close", animSpeed, ["blue-4", "blue-3", "blue-2", "blue-1"]);
|
Self.AddAnimation("close", animSpeed, ["blue-4", "blue-3", "blue-2", "blue-1"]);
|
||||||
|
@ -33,17 +34,17 @@ function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find our linked Warp Door.
|
// Find our linked Warp Door.
|
||||||
var links = Self.GetLinks()
|
let linkedDoor = null;
|
||||||
var linkedDoor = null;
|
for (let link of Self.GetLinks()) {
|
||||||
for (var i = 0; i < links.length; i++) {
|
if (link.Title.indexOf("Warp Door") > -1) {
|
||||||
if (links[i].Title.indexOf("Warp Door") > -1) {
|
linkedDoor = link;
|
||||||
linkedDoor = links[i];
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subscribe to the global state-change if we are a state door.
|
// Subscribe to the global state-change if we are a state door.
|
||||||
if (isStateDoor) {
|
if (isStateDoor) {
|
||||||
Message.Subscribe("broadcast:state-change", function(newState) {
|
Message.Subscribe("broadcast:state-change", (newState) => {
|
||||||
state = color === 'blue' ? !newState : newState;
|
state = color === 'blue' ? !newState : newState;
|
||||||
|
|
||||||
// Activate or deactivate the door.
|
// Activate or deactivate the door.
|
||||||
|
@ -52,12 +53,11 @@ function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For player groundedness work-around
|
// For player groundedness work-around
|
||||||
var playerLastY = []; // last sampling of Y values
|
let playerLastY = []; // last sampling of Y values
|
||||||
var lastUsed = time.Now();
|
|
||||||
|
|
||||||
// The player Uses the door.
|
// The player Uses the door.
|
||||||
var flashedCooldown = false; // "Locked Door" flashed message.
|
let flashedCooldown = false; // "Locked Door" flashed message.
|
||||||
Events.OnUse(function(e) {
|
Events.OnUse((e) => {
|
||||||
if (animating) {
|
if (animating) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ function main() {
|
||||||
// Work-around: if two Boxes are stacked atop each other the player can
|
// Work-around: if two Boxes are stacked atop each other the player can
|
||||||
// get stuck if he jumps on top. He may not be Grounded but isn't changing
|
// get stuck if he jumps on top. He may not be Grounded but isn't changing
|
||||||
// effective Y position and a warp door may work as a good way out.
|
// effective Y position and a warp door may work as a good way out.
|
||||||
var yValue = e.Actor.Position().Y;
|
let yValue = e.Actor.Position().Y;
|
||||||
|
|
||||||
// Collect a sampling of last few Y values. If the player Y position
|
// Collect a sampling of last few Y values. If the player Y position
|
||||||
// is constant the last handful of frames, treat them as if they're
|
// is constant the last handful of frames, treat them as if they're
|
||||||
|
@ -100,8 +100,8 @@ function main() {
|
||||||
playerLastY.pop();
|
playerLastY.pop();
|
||||||
|
|
||||||
// Hasn't moved?
|
// Hasn't moved?
|
||||||
var isGrounded = true;
|
let isGrounded = true;
|
||||||
for (var i = 0; i < playerLastY.length; i++) {
|
for (let i = 0; i < playerLastY.length; i++) {
|
||||||
if (yValue !== playerLastY[i]) {
|
if (yValue !== playerLastY[i]) {
|
||||||
isGrounded = false;
|
isGrounded = false;
|
||||||
break;
|
break;
|
||||||
|
@ -120,9 +120,9 @@ function main() {
|
||||||
|
|
||||||
// Play the open and close animation.
|
// Play the open and close animation.
|
||||||
animating = true;
|
animating = true;
|
||||||
Self.PlayAnimation("open", function() {
|
Self.PlayAnimation("open", () => {
|
||||||
e.Actor.Hide()
|
e.Actor.Hide()
|
||||||
Self.PlayAnimation("close", function() {
|
Self.PlayAnimation("close", () => {
|
||||||
Self.ShowLayerNamed(isStateDoor && !state ? spriteDisabled : spriteDefault);
|
Self.ShowLayerNamed(isStateDoor && !state ? spriteDisabled : spriteDefault);
|
||||||
animating = false;
|
animating = false;
|
||||||
|
|
||||||
|
@ -139,12 +139,12 @@ function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Respond to incoming warp events.
|
// Respond to incoming warp events.
|
||||||
Message.Subscribe("warp-door:incoming", function(player) {
|
Message.Subscribe("warp-door:incoming", (player) => {
|
||||||
animating = true;
|
animating = true;
|
||||||
player.Unfreeze();
|
player.Unfreeze();
|
||||||
Self.PlayAnimation("open", function() {
|
Self.PlayAnimation("open", () => {
|
||||||
player.Show();
|
player.Show();
|
||||||
Self.PlayAnimation("close", function() {
|
Self.PlayAnimation("close", () => {
|
||||||
animating = false;
|
animating = false;
|
||||||
|
|
||||||
// If the receiving door was a State Door, fix its state.
|
// If the receiving door was a State Door, fix its state.
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -10,12 +10,13 @@ require (
|
||||||
github.com/aichaos/rivescript-go v0.3.1
|
github.com/aichaos/rivescript-go v0.3.1
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
github.com/dop251/goja v0.0.0-20220110113543-261677941f3c
|
||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
github.com/gen2brain/dlgs v0.0.0-20211108104213-bade24837f0b
|
github.com/gen2brain/dlgs v0.0.0-20211108104213-bade24837f0b
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd // indirect
|
github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd // indirect
|
||||||
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
|
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
|
||||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f // indirect
|
||||||
github.com/tomnomnom/xtermcolor v0.0.0-20160428124646-b78803f00a7e // indirect
|
github.com/tomnomnom/xtermcolor v0.0.0-20160428124646-b78803f00a7e // indirect
|
||||||
github.com/urfave/cli/v2 v2.3.0
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
github.com/veandco/go-sdl2 v0.4.10
|
github.com/veandco/go-sdl2 v0.4.10
|
||||||
|
|
16
go.sum
16
go.sum
|
@ -69,11 +69,16 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E=
|
||||||
|
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
|
github.com/dop251/goja v0.0.0-20220110113543-261677941f3c h1:1XnAlcjYBdO7xsa2rhNB/BTztiu4cFKOxE+3brXVtG4=
|
||||||
|
github.com/dop251/goja v0.0.0-20220110113543-261677941f3c/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
|
||||||
|
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
@ -91,6 +96,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
|
||||||
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
@ -196,8 +203,10 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
@ -227,7 +236,6 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
|
||||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
@ -259,7 +267,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tomnomnom/xtermcolor v0.0.0-20160428124646-b78803f00a7e h1:Ee+VZw13r9NTOMnwTPs6O5KZ0MJU54hsxu9FpZ4pQ10=
|
github.com/tomnomnom/xtermcolor v0.0.0-20160428124646-b78803f00a7e h1:Ee+VZw13r9NTOMnwTPs6O5KZ0MJU54hsxu9FpZ4pQ10=
|
||||||
|
@ -459,6 +466,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -624,6 +632,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
@ -640,7 +649,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"git.kirsle.net/apps/doodle/pkg/modal"
|
"git.kirsle.net/apps/doodle/pkg/modal"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Command is a parsed shell command.
|
// Command is a parsed shell command.
|
||||||
|
@ -330,13 +330,13 @@ func (c Command) BoolProp(d *Doodle) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunScript evaluates some JavaScript code safely.
|
// RunScript evaluates some JavaScript code safely.
|
||||||
func (c Command) RunScript(d *Doodle, code interface{}) (otto.Value, error) {
|
func (c Command) RunScript(d *Doodle, code string) (goja.Value, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
d.FlashError("Command.RunScript: Panic: %s", err)
|
d.FlashError("Command.RunScript: Panic: %s", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
out, err := d.shell.js.Run(code)
|
out, err := d.shell.js.RunString(code)
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
||||||
|
|
||||||
fileMenu.AddItemAccel("Open...", "Ctrl-O", u.Scene.MenuOpen)
|
fileMenu.AddItemAccel("Open...", "Ctrl-O", u.Scene.MenuOpen)
|
||||||
fileMenu.AddSeparator()
|
fileMenu.AddSeparator()
|
||||||
fileMenu.AddItem("Quit to menu", func() {
|
fileMenu.AddItem("Exit to menu", func() {
|
||||||
u.Scene.ConfirmUnload(func() {
|
u.Scene.ConfirmUnload(func() {
|
||||||
d.Goto(&MainScene{})
|
d.Goto(&MainScene{})
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,10 +2,11 @@ package scripting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/pkg/keybind"
|
"git.kirsle.net/apps/doodle/pkg/keybind"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event name constants.
|
// Event name constants.
|
||||||
|
@ -26,19 +27,21 @@ var (
|
||||||
|
|
||||||
// Events API for Doodad scripts.
|
// Events API for Doodad scripts.
|
||||||
type Events struct {
|
type Events struct {
|
||||||
registry map[string][]otto.Value
|
runtime *goja.Runtime
|
||||||
|
registry map[string][]goja.Value
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEvents initializes the Events API.
|
// NewEvents initializes the Events API.
|
||||||
func NewEvents() *Events {
|
func NewEvents(runtime *goja.Runtime) *Events {
|
||||||
return &Events{
|
return &Events{
|
||||||
registry: map[string][]otto.Value{},
|
runtime: runtime,
|
||||||
|
registry: map[string][]goja.Value{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnCollide fires when another actor collides with yours.
|
// OnCollide fires when another actor collides with yours.
|
||||||
func (e *Events) OnCollide(call otto.FunctionCall) otto.Value {
|
func (e *Events) OnCollide(call goja.FunctionCall) goja.Value {
|
||||||
return e.register(CollideEvent, call.Argument(0))
|
return e.register(CollideEvent, call.Argument(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +51,7 @@ func (e *Events) RunCollide(v interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnUse fires when another actor collides with yours.
|
// OnUse fires when another actor collides with yours.
|
||||||
func (e *Events) OnUse(call otto.FunctionCall) otto.Value {
|
func (e *Events) OnUse(call goja.FunctionCall) goja.Value {
|
||||||
return e.register(UseEvent, call.Argument(0))
|
return e.register(UseEvent, call.Argument(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ func (e *Events) RunUse(v interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnLeave fires when another actor stops colliding with yours.
|
// OnLeave fires when another actor stops colliding with yours.
|
||||||
func (e *Events) OnLeave(call otto.FunctionCall) otto.Value {
|
func (e *Events) OnLeave(call goja.FunctionCall) goja.Value {
|
||||||
return e.register(LeaveEvent, call.Argument(0))
|
return e.register(LeaveEvent, call.Argument(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,30 +71,26 @@ func (e *Events) RunLeave(v interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnKeypress fires when another actor collides with yours.
|
// OnKeypress fires when another actor collides with yours.
|
||||||
func (e *Events) OnKeypress(call otto.FunctionCall) otto.Value {
|
func (e *Events) OnKeypress(call goja.FunctionCall) goja.Value {
|
||||||
return e.register(KeypressEvent, call.Argument(0))
|
return e.register(KeypressEvent, call.Argument(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunKeypress invokes the OnCollide handler function.
|
// RunKeypress invokes the OnCollide handler function.
|
||||||
func (e *Events) RunKeypress(ev keybind.State) error {
|
func (e *Events) RunKeypress(ev keybind.State) error {
|
||||||
return e.run(KeypressEvent, ev)
|
return e.run(KeypressEvent, e.runtime.ToValue(ev))
|
||||||
}
|
}
|
||||||
|
|
||||||
// register a named event.
|
// register a named event.
|
||||||
func (e *Events) register(name string, callback otto.Value) otto.Value {
|
func (e *Events) register(name string, callback goja.Value) goja.Value {
|
||||||
if !callback.IsFunction() {
|
|
||||||
return otto.Value{} // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
e.lock.Lock()
|
e.lock.Lock()
|
||||||
defer e.lock.Unlock()
|
defer e.lock.Unlock()
|
||||||
|
|
||||||
if _, ok := e.registry[name]; !ok {
|
if _, ok := e.registry[name]; !ok {
|
||||||
e.registry[name] = []otto.Value{}
|
e.registry[name] = []goja.Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
e.registry[name] = append(e.registry[name], callback)
|
e.registry[name] = append(e.registry[name], callback)
|
||||||
return otto.Value{}
|
return goja.Undefined()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run an event handler. Returns an error only if there was a JavaScript error
|
// Run an event handler. Returns an error only if there was a JavaScript error
|
||||||
|
@ -104,20 +103,28 @@ func (e *Events) run(name string, args ...interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var params = make([]goja.Value, len(args))
|
||||||
|
for i, v := range args {
|
||||||
|
params[i] = e.runtime.ToValue(v)
|
||||||
|
}
|
||||||
|
|
||||||
for _, callback := range e.registry[name] {
|
for _, callback := range e.registry[name] {
|
||||||
value, err := callback.Call(otto.Value{}, args...)
|
function, ok := goja.AssertFunction(callback)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("failed to callback %s: %s", name, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := function(goja.Undefined(), params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the event handler returned a boolean false, stop all other
|
// If the event handler returned a boolean false, stop all other
|
||||||
// callbacks and return the boolean.
|
// callbacks and return the boolean.
|
||||||
if value.IsBoolean() {
|
if b, ok := value.Export().(bool); ok && !b {
|
||||||
if b, err := value.ToBoolean(); err == nil && b == false {
|
|
||||||
return ErrReturnFalse
|
return ErrReturnFalse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package scripting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Message holds data being published from one script VM with information sent
|
// Message holds data being published from one script VM with information sent
|
||||||
|
@ -10,7 +10,7 @@ import (
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Name string
|
Name string
|
||||||
SenderID string
|
SenderID string
|
||||||
Args []interface{}
|
Args []goja.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -29,7 +29,10 @@ func RegisterPublishHooks(s *Supervisor, vm *VM) {
|
||||||
if _, ok := vm.subscribe[msg.Name]; ok {
|
if _, ok := vm.subscribe[msg.Name]; ok {
|
||||||
for _, callback := range vm.subscribe[msg.Name] {
|
for _, callback := range vm.subscribe[msg.Name] {
|
||||||
log.Debug("PubSub: %s receives from %s: %s", vm.Name, msg.SenderID, msg.Name)
|
log.Debug("PubSub: %s receives from %s: %s", vm.Name, msg.SenderID, msg.Name)
|
||||||
callback.Call(otto.Value{}, msg.Args...)
|
if function, ok := goja.AssertFunction(callback); ok {
|
||||||
|
result, err := function(goja.Undefined(), msg.Args...)
|
||||||
|
log.Debug("Result: %s, %s", result, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,22 +42,22 @@ func RegisterPublishHooks(s *Supervisor, vm *VM) {
|
||||||
|
|
||||||
// Register the Message.Subscribe and Message.Publish functions.
|
// Register the Message.Subscribe and Message.Publish functions.
|
||||||
vm.vm.Set("Message", map[string]interface{}{
|
vm.vm.Set("Message", map[string]interface{}{
|
||||||
"Subscribe": func(name string, callback otto.Value) {
|
"Subscribe": func(name string, callback goja.Value) {
|
||||||
vm.muSubscribe.Lock()
|
vm.muSubscribe.Lock()
|
||||||
defer vm.muSubscribe.Unlock()
|
defer vm.muSubscribe.Unlock()
|
||||||
|
|
||||||
if !callback.IsFunction() {
|
if _, ok := goja.AssertFunction(callback); !ok {
|
||||||
log.Error("SUBSCRIBE(%s): callback is not a function", name)
|
log.Error("SUBSCRIBE(%s): callback is not a function", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := vm.subscribe[name]; !ok {
|
if _, ok := vm.subscribe[name]; !ok {
|
||||||
vm.subscribe[name] = []otto.Value{}
|
vm.subscribe[name] = []goja.Value{}
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.subscribe[name] = append(vm.subscribe[name], callback)
|
vm.subscribe[name] = append(vm.subscribe[name], callback)
|
||||||
},
|
},
|
||||||
|
|
||||||
"Publish": func(name string, v ...interface{}) {
|
"Publish": func(name string, v ...goja.Value) {
|
||||||
for _, channel := range vm.Outbound {
|
for _, channel := range vm.Outbound {
|
||||||
channel <- Message{
|
channel <- Message{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -64,7 +67,7 @@ func RegisterPublishHooks(s *Supervisor, vm *VM) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"Broadcast": func(name string, v ...interface{}) {
|
"Broadcast": func(name string, v ...goja.Value) {
|
||||||
// Send the message to all actor VMs.
|
// Send the message to all actor VMs.
|
||||||
for _, toVM := range s.scripts {
|
for _, toVM := range s.scripts {
|
||||||
if vm.Name == toVM.Name {
|
if vm.Name == toVM.Name {
|
||||||
|
|
|
@ -3,13 +3,13 @@ package scripting
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Timer keeps track of delayed function calls for the scripting engine.
|
// Timer keeps track of delayed function calls for the scripting engine.
|
||||||
type Timer struct {
|
type Timer struct {
|
||||||
id int
|
id int
|
||||||
callback otto.Value
|
callback goja.Value
|
||||||
interval time.Duration // milliseconds delay for timeout
|
interval time.Duration // milliseconds delay for timeout
|
||||||
next time.Time // scheduled time for next invocation
|
next time.Time // scheduled time for next invocation
|
||||||
repeat bool // for setInterval
|
repeat bool // for setInterval
|
||||||
|
@ -27,7 +27,7 @@ with 1000 being 'one second.'
|
||||||
Returns the ID number of the timer in case you want to clear it. The underlying
|
Returns the ID number of the timer in case you want to clear it. The underlying
|
||||||
Timer type is NOT exposed to JavaScript.
|
Timer type is NOT exposed to JavaScript.
|
||||||
*/
|
*/
|
||||||
func (vm *VM) SetTimeout(callback otto.Value, interval int) int {
|
func (vm *VM) SetTimeout(callback goja.Value, interval int) int {
|
||||||
return vm.AddTimer(callback, interval, false)
|
return vm.AddTimer(callback, interval, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +37,14 @@ SetInterval registers a callback function to be run repeatedly.
|
||||||
Returns the ID number of the timer in case you want to clear it. The underlying
|
Returns the ID number of the timer in case you want to clear it. The underlying
|
||||||
Timer type is NOT exposed to JavaScript.
|
Timer type is NOT exposed to JavaScript.
|
||||||
*/
|
*/
|
||||||
func (vm *VM) SetInterval(callback otto.Value, interval int) int {
|
func (vm *VM) SetInterval(callback goja.Value, interval int) int {
|
||||||
return vm.AddTimer(callback, interval, true)
|
return vm.AddTimer(callback, interval, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
AddTimer loads timeouts and intervals into the VM's memory and returns the ID.
|
AddTimer loads timeouts and intervals into the VM's memory and returns the ID.
|
||||||
*/
|
*/
|
||||||
func (vm *VM) AddTimer(callback otto.Value, interval int, repeat bool) int {
|
func (vm *VM) AddTimer(callback goja.Value, interval int, repeat bool) int {
|
||||||
// Get the next timer ID. The first timer has ID 1.
|
// Get the next timer ID. The first timer has ID 1.
|
||||||
vm.timerLastID++
|
vm.timerLastID++
|
||||||
id := vm.timerLastID
|
id := vm.timerLastID
|
||||||
|
@ -72,7 +72,10 @@ func (vm *VM) TickTimer(now time.Time) {
|
||||||
|
|
||||||
for id, timer := range vm.timers {
|
for id, timer := range vm.timers {
|
||||||
if now.After(timer.next) {
|
if now.After(timer.next) {
|
||||||
timer.callback.Call(otto.Value{})
|
if function, ok := goja.AssertFunction(timer.callback); ok {
|
||||||
|
function(goja.Undefined())
|
||||||
|
}
|
||||||
|
|
||||||
if timer.repeat {
|
if timer.repeat {
|
||||||
timer.Schedule()
|
timer.Schedule()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package scripting
|
package scripting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VM manages a single isolated JavaScript VM.
|
// VM manages a single isolated JavaScript VM.
|
||||||
|
@ -24,10 +25,10 @@ type VM struct {
|
||||||
// messages.
|
// messages.
|
||||||
Inbound chan Message
|
Inbound chan Message
|
||||||
Outbound []chan Message
|
Outbound []chan Message
|
||||||
subscribe map[string][]otto.Value // Subscribed message handlers by name.
|
subscribe map[string][]goja.Value // Subscribed message handlers by name.
|
||||||
muSubscribe sync.RWMutex
|
muSubscribe sync.RWMutex
|
||||||
|
|
||||||
vm *otto.Otto
|
vm *goja.Runtime
|
||||||
|
|
||||||
// setTimeout and setInterval variables.
|
// setTimeout and setInterval variables.
|
||||||
timerLastID int // becomes 1 when first timer is set
|
timerLastID int // becomes 1 when first timer is set
|
||||||
|
@ -38,21 +39,21 @@ type VM struct {
|
||||||
func NewVM(name string) *VM {
|
func NewVM(name string) *VM {
|
||||||
vm := &VM{
|
vm := &VM{
|
||||||
Name: name,
|
Name: name,
|
||||||
Events: NewEvents(),
|
vm: goja.New(),
|
||||||
vm: otto.New(),
|
|
||||||
timers: map[int]*Timer{},
|
timers: map[int]*Timer{},
|
||||||
|
|
||||||
// Pub/sub structs.
|
// Pub/sub structs.
|
||||||
Inbound: make(chan Message),
|
Inbound: make(chan Message),
|
||||||
Outbound: []chan Message{},
|
Outbound: []chan Message{},
|
||||||
subscribe: map[string][]otto.Value{},
|
subscribe: map[string][]goja.Value{},
|
||||||
}
|
}
|
||||||
|
vm.Events = NewEvents(vm.vm)
|
||||||
return vm
|
return vm
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run code in the VM.
|
// Run code in the VM.
|
||||||
func (vm *VM) Run(src interface{}) (otto.Value, error) {
|
func (vm *VM) Run(src string) (goja.Value, error) {
|
||||||
v, err := vm.vm.Run(src)
|
v, err := vm.vm.RunString(src)
|
||||||
return v, err
|
return v, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +79,9 @@ func (vm *VM) RegisterLevelHooks() error {
|
||||||
|
|
||||||
// Main calls the main function of the script.
|
// Main calls the main function of the script.
|
||||||
func (vm *VM) Main() error {
|
func (vm *VM) Main() error {
|
||||||
function, err := vm.vm.Get("main")
|
function, ok := goja.AssertFunction(vm.vm.Get("main"))
|
||||||
if err != nil {
|
if !ok {
|
||||||
return err
|
return errors.New("didn't find function main()")
|
||||||
}
|
|
||||||
|
|
||||||
if !function.IsFunction() {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catch panics.
|
// Catch panics.
|
||||||
|
@ -94,6 +91,6 @@ func (vm *VM) Main() error {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
_, err = function.Call(otto.Value{})
|
_, err := function(goja.Undefined())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"git.kirsle.net/go/render/event"
|
"git.kirsle.net/go/render/event"
|
||||||
"git.kirsle.net/go/ui"
|
"git.kirsle.net/go/ui"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Flash a message to the user.
|
// Flash a message to the user.
|
||||||
|
@ -59,7 +59,7 @@ type Shell struct {
|
||||||
historyIndex int
|
historyIndex int
|
||||||
|
|
||||||
// JavaScript shell interpreter.
|
// JavaScript shell interpreter.
|
||||||
js *otto.Otto
|
js *goja.Runtime
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flash holds a message to flash on screen.
|
// Flash holds a message to flash on screen.
|
||||||
|
@ -79,7 +79,7 @@ func NewShell(d *Doodle) Shell {
|
||||||
Prompt: ">",
|
Prompt: ">",
|
||||||
cursor: '_',
|
cursor: '_',
|
||||||
cursorRate: balance.ShellCursorBlinkRate,
|
cursorRate: balance.ShellCursorBlinkRate,
|
||||||
js: otto.New(),
|
js: goja.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the Doodle instance available to the shell.
|
// Make the Doodle instance available to the shell.
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"git.kirsle.net/apps/doodle/pkg/physics"
|
"git.kirsle.net/apps/doodle/pkg/physics"
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
|
"github.com/dop251/goja"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/robertkrimen/otto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Actor is an object that marries together the three things that make a
|
// Actor is an object that marries together the three things that make a
|
||||||
|
@ -52,7 +52,7 @@ type Actor struct {
|
||||||
// Animation variables.
|
// Animation variables.
|
||||||
animations map[string]*Animation
|
animations map[string]*Animation
|
||||||
activeAnimation *Animation
|
activeAnimation *Animation
|
||||||
animationCallback otto.Value
|
animationCallback goja.Value
|
||||||
|
|
||||||
// Mutex.
|
// Mutex.
|
||||||
muInventory sync.RWMutex
|
muInventory sync.RWMutex
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.kirsle.net/apps/doodle/pkg/log"
|
"git.kirsle.net/apps/doodle/pkg/log"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Animation holds a named animation for a doodad script.
|
// Animation holds a named animation for a doodad script.
|
||||||
|
@ -103,7 +103,7 @@ func (a *Actor) AddAnimation(name string, interval int64, layers []interface{})
|
||||||
|
|
||||||
// PlayAnimation starts an animation and then calls a JavaScript function when
|
// PlayAnimation starts an animation and then calls a JavaScript function when
|
||||||
// the last frame has played out. Set a null function to ignore the callback.
|
// the last frame has played out. Set a null function to ignore the callback.
|
||||||
func (a *Actor) PlayAnimation(name string, callback otto.Value) error {
|
func (a *Actor) PlayAnimation(name string, callback goja.Value) error {
|
||||||
anim, ok := a.animations[name]
|
anim, ok := a.animations[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("animation named '%s' not found", name)
|
return fmt.Errorf("animation named '%s' not found", name)
|
||||||
|
@ -132,5 +132,5 @@ func (a *Actor) StopAnimation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
a.activeAnimation = nil
|
a.activeAnimation = nil
|
||||||
a.animationCallback = otto.NullValue()
|
a.animationCallback = goja.Null()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"git.kirsle.net/apps/doodle/pkg/physics"
|
"git.kirsle.net/apps/doodle/pkg/physics"
|
||||||
"git.kirsle.net/apps/doodle/pkg/scripting"
|
"git.kirsle.net/apps/doodle/pkg/scripting"
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"github.com/robertkrimen/otto"
|
"github.com/dop251/goja"
|
||||||
)
|
)
|
||||||
|
|
||||||
// loopActorCollision is the Loop function that checks if pairs of
|
// loopActorCollision is the Loop function that checks if pairs of
|
||||||
|
@ -56,8 +56,8 @@ func (w *Canvas) loopActorCollision() error {
|
||||||
a.StopAnimation()
|
a.StopAnimation()
|
||||||
|
|
||||||
// Call the callback function.
|
// Call the callback function.
|
||||||
if callback.IsFunction() {
|
if function, ok := goja.AssertFunction(callback); ok {
|
||||||
callback.Call(otto.NullValue())
|
function(goja.Undefined())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user