From f751946b40f544a87c39baf5406eeed8a15f93fb Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Mon, 15 Jan 2024 10:47:16 -0800
Subject: [PATCH 01/13] Create Pause-Utilities.js
---
extensions/SharkPool/Pause-Utilities.js | 347 ++++++++++++++++++++++++
1 file changed, 347 insertions(+)
create mode 100644 extensions/SharkPool/Pause-Utilities.js
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
new file mode 100644
index 0000000000..958a040e53
--- /dev/null
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -0,0 +1,347 @@
+// Name: Pause Utilities
+// ID: SPPause
+// Description: Pause the Project and certain Scripts
+// By: SharkPool
+
+// Version V.1.6.0
+
+(function (Scratch) {
+ "use strict";
+ if (!Scratch.extensions.unsandboxed) alert("Pause Utilities Extension must run unsandboxed!");
+ const vm = Scratch.vm;
+ const runtime = Scratch.vm.runtime;
+ const Cast = Scratch.Cast;
+ let storedScripts = {};
+ let projectPaused = false;
+
+ const menuIconURI =
+"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTgiIHdpZHRoPSIxOCI+PHBhdGggZD0iTTIzMS40MjkgMTg4LjkyOVYxNzEuMDdoNC4yODV2MTcuODU4em0xMi4xNDIgMFYxNzEuMDdoNC4yODZ2MTcuODU4eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzMwOSAwIDAgLjk1NDI3IC0yMzguNTczIC0xNjIuNzY5KSIgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsPSIjZmZhZTAwIiBzdHJva2U9IiNkODk0MDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOm5vcm1hbCIvPjwvc3ZnPg==";
+
+ const blockIconURI =
+"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzMS40NzcxNCIgaGVpZ2h0PSIzMS40NzcxNCIgdmlld0JveD0iMCwwLDMxLjQ3NzE0LDMxLjQ3NzE0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjI0LjI2MTQzLC0xNjQuMjYxNDMpIj48ZyBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGwtcnVsZT0ibm9uemVybyIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLWRhc2hhcnJheT0iIiBzdHJva2UtZGFzaG9mZnNldD0iMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjxwYXRoIGQ9Ik0yMjQuMjYxNDMsMTk1LjczODU3di0zMS40NzcxNGgzMS40NzcxNHYzMS40NzcxNHoiIGZpbGw9IiM1ZjViNDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+PHBhdGggZD0iTTIzMS41MjgxOSwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI2Nzl2MTcuMDQxMzV6TTI0NC4wNzE5NiwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI3ODJ2MTcuMDQxMzV6IiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGw9IiNmZmFlMDAiIHN0cm9rZT0iI2Q4OTQwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9nPjwvZz48L3N2Zz4=";
+
+ runtime.on("PROJECT_STOP_ALL", () => { storedScripts = {} });
+
+ function beginScan() {
+ let isChecking = false;
+ const check = () => {
+ if (isChecking) return;
+ const isPM = Scratch.extensions.isPenguinMod;
+ isChecking = true;
+ try {
+ projectPaused = runtime.ioDevices.clock._paused;
+ if (!projectPaused && !isPM) return;
+ const allUtils = vm.runtime.targets;
+ for (let i = 0; i < allUtils.length; i++) {
+ const util = allUtils[i];
+ const object = util.blocks._blocks;
+ const keysV = getKeysByValue(object, "opcode", "SPPause_whenProjectPaused");
+ for (const keyV of keysV) {
+ if (projectPaused) vm.setEditingTarget(util.id);
+ if (runtime.threads) {
+ let threadExists = runtime.threads.some(thread => thread.topBlock === object[keyV].id);
+ if (!threadExists) {
+ if (projectPaused) {
+ vm.runtime.toggleScript(object[keyV].id, util);
+ checkReset(object[keyV].id);
+ } else if (isPM) { checkReset(object[keyV].id) }
+ } else { checkReset(object[keyV].id) }
+ }
+ }
+ }
+ if (isPM) vm.runtime._step();
+ } catch {} finally {
+ isChecking = false;
+ setTimeout(check, 10);
+ }
+ };
+ check();
+ }
+ function getKeysByValue(object, name, value) {
+ const keys = [];
+ for (const key in object) {
+ if (object[key][name] === value) keys.push(key);
+ }
+ return keys;
+ }
+ function checkReset(ID) {
+ const threadExists = runtime.threads.find(thread => thread.topBlock === ID);
+ if (threadExists.status === undefined) threadExists.status = 4;
+ }
+
+ class SPPause {
+ getInfo() {
+ return {
+ id: "SPPause",
+ name: "Pause Utilities",
+ color1: "#5f5b49",
+ menuIconURI,
+ blockIconURI,
+ blocks: [
+ { blockType: Scratch.BlockType.LABEL, text: "Project Control" },
+ {
+ opcode: "pause",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "pause project"
+ },
+ {
+ opcode: "unpause",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "unpause project"
+ },
+ {
+ opcode: "whenProjectPaused",
+ blockType: Scratch.BlockType.EVENT,
+ text: "when project is paused",
+ isEdgeActivated: false
+ },
+ {
+ opcode: "isProjectPaused",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: "is project paused?"
+ },
+ { blockType: Scratch.BlockType.LABEL, text: "Sprite Control" },
+ {
+ opcode: "pauseSprite",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "pause [SPRITE]",
+ arguments: {
+ SPRITE: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "TARGETS"
+ }
+ }
+ },
+ {
+ opcode: "unpauseSprite",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "unpause [SPRITE]",
+ arguments: {
+ SPRITE: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "TARGETS"
+ }
+ }
+ },
+ "---",
+ {
+ opcode: "pauseClones",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "pause clones of [SPRITE] with [VAR] set to [NUM]",
+ arguments: {
+ SPRITE: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "TARGETS2"
+ },
+ VAR: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my variable"
+ },
+ NUM: {
+ type: Scratch.ArgumentType.NUMBER,
+ defaultValue: 0
+ }
+ }
+ },
+ {
+ opcode: "unpauseClones",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "unpause clones of [SPRITE] with [VAR] set to [NUM]",
+ arguments: {
+ SPRITE: {
+ type: Scratch.ArgumentType.STRING,
+ menu: "TARGETS2"
+ },
+ VAR: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my variable"
+ },
+ NUM: {
+ type: Scratch.ArgumentType.NUMBER,
+ defaultValue: 0
+ }
+ }
+ },
+ { blockType: Scratch.BlockType.LABEL, text: "Script Control" },
+ {
+ opcode: "pauseLoop",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "pause this script with ID [NAME]",
+ arguments: {
+ NAME: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my script"
+ }
+ }
+ },
+ {
+ opcode: "breakLoop",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "unpause script with ID [NAME]",
+ arguments: {
+ NAME: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my script"
+ }
+ }
+ },
+ {
+ opcode: "breakAll",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "unpause all scripts"
+ },
+ "---",
+ {
+ opcode: "pauseLoopCon",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "if [CON] pause this script with ID [NAME]",
+ arguments: {
+ CON: { type: Scratch.ArgumentType.BOOLEAN },
+ NAME: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my script"
+ }
+ }
+ },
+ {
+ opcode: "breakLoopCon",
+ blockType: Scratch.BlockType.COMMAND,
+ text: "if [CON] unpause script with ID [NAME]",
+ arguments: {
+ CON: { type: Scratch.ArgumentType.BOOLEAN },
+ NAME: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my script"
+ }
+ }
+ },
+ "---",
+ {
+ opcode: "isPaused",
+ blockType: Scratch.BlockType.BOOLEAN,
+ text: "is script with ID [NAME] paused?",
+ arguments: {
+ NAME: {
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "my script"
+ }
+ }
+ },
+ {
+ opcode: "allPausedScripts",
+ blockType: Scratch.BlockType.REPORTER,
+ text: "all paused scripts",
+ disableMonitor: true
+ },
+ ],
+ menus: {
+ TARGETS: { acceptReporters: true, items: this._getTargets(0) },
+ TARGETS2: { acceptReporters: true, items: this._getTargets(1) }
+ }
+ };
+ }
+
+ _getTargets(ind) {
+ const spriteNames = [];
+ const targets = Scratch.vm.runtime.targets;
+ for (let index = ind; index < targets.length; index++) {
+ const target = targets[index];
+ if (target.isOriginal) spriteNames.push(target.getName());
+ }
+ return spriteNames.length > 0 ? spriteNames : [""];
+ }
+
+ pause() {
+ if (Scratch.extensions.isPenguinMod) {
+ runtime.pause();
+ } else {
+ const pauseButton = document.querySelector(
+ runtime.isPackaged ? `[class*="pause-button"]` :
+ "img.pause-btn.addons-display-none-pause"
+ );
+ if (pauseButton) {
+ pauseButton.click();
+ } else { console.log("Pause button not found") }
+ }
+ }
+
+ unpause() {
+ if (Scratch.extensions.isPenguinMod) {
+ runtime.play()
+ } else {
+ this.pause();
+ }
+ }
+
+ // by itself, the block is useless, but with the event block it is :D
+ isProjectPaused() { return projectPaused }
+
+ pauseSprite(args) {
+ const target = args.SPRITE === "Stage" ? runtime.getTargetForStage() : runtime.getSpriteTargetByName(args.SPRITE);
+ if (target) this.searchThreads(target.id, 1);
+ }
+ unpauseSprite(args) {
+ const target = args.SPRITE === "Stage" ? runtime.getTargetForStage() : runtime.getSpriteTargetByName(args.SPRITE);
+ if (target) this.searchThreads(target.id, 0);
+ }
+ pauseClones(args) { this.modifyClones.call(this, args, 1) }
+ unpauseClones(args) { this.modifyClones.call(this, args, 0) }
+
+ searchThreads(target, cntrl) {
+ const thread = runtime.threads;
+ thread.forEach(t => {
+ if (t.target.id === target && t.status !== cntrl) t.status = cntrl;
+ });
+ }
+ modifyClones(args, cntrl) {
+ const target = runtime.getSpriteTargetByName(args.SPRITE);
+ if (target) {
+ const clones = target.sprite.clones;
+ const varName = args.VAR;
+ const numValue = args.NUM;
+ for (let i = 1; i < clones.length; i++) {
+ const variable = clones[i].lookupVariableByNameAndType(varName, "");
+ if (variable && variable.value === numValue) this.searchThreads(clones[i].id, cntrl);
+ }
+ }
+ }
+
+ pauseLoopCon(args, util) { if (Cast.toBoolean(args.CON)) this.pauseLoop(args, util) }
+
+ breakLoopCon(args) { if (Cast.toBoolean(args.CON)) this.breakLoop(args) }
+
+ pauseLoop(args, util) {
+ const scriptName = Cast.toString(args.NAME);
+ const state = util.stackFrame.pausedScript;
+ if (!state) {
+ storedScripts[scriptName] = true;
+ util.stackFrame.pausedScript = scriptName;
+ util.yield();
+ } else if (state in storedScripts) {
+ util.yield();
+ }
+ }
+
+ breakLoop(args) {
+ const scriptName = Cast.toString(args.NAME);
+ if (scriptName in storedScripts) delete storedScripts[scriptName];
+ }
+
+ breakAll() {
+ const allScripts = Object.keys(storedScripts);
+ for (let i = 0; i < allScripts.length; i++) {
+ this.breakLoop({ NAME : allScripts[i] });
+ }
+ }
+
+ isPaused(args) {
+ const scriptName = Cast.toString(args.NAME);
+ return scriptName in storedScripts;
+ }
+
+ allPausedScripts() { return JSON.stringify(Object.keys(storedScripts)) }
+ }
+
+ beginScan()
+ Scratch.extensions.register(new SPPause());
+})(Scratch);
From 8fc3ab5d2a56c0ad4c130b3004ae4bb4fac324d1 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Mon, 15 Jan 2024 13:49:23 -0800
Subject: [PATCH 02/13] Update Pause-Utilities.js
---
extensions/SharkPool/Pause-Utilities.js | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index 958a040e53..fe3e13cd1a 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -3,7 +3,7 @@
// Description: Pause the Project and certain Scripts
// By: SharkPool
-// Version V.1.6.0
+// Version V.1.6.0 (TW Version)
(function (Scratch) {
"use strict";
@@ -26,11 +26,10 @@
let isChecking = false;
const check = () => {
if (isChecking) return;
- const isPM = Scratch.extensions.isPenguinMod;
isChecking = true;
try {
projectPaused = runtime.ioDevices.clock._paused;
- if (!projectPaused && !isPM) return;
+ if (!projectPaused) return;
const allUtils = vm.runtime.targets;
for (let i = 0; i < allUtils.length; i++) {
const util = allUtils[i];
@@ -44,12 +43,11 @@
if (projectPaused) {
vm.runtime.toggleScript(object[keyV].id, util);
checkReset(object[keyV].id);
- } else if (isPM) { checkReset(object[keyV].id) }
+ }
} else { checkReset(object[keyV].id) }
}
}
}
- if (isPM) vm.runtime._step();
} catch {} finally {
isChecking = false;
setTimeout(check, 10);
From 04bfc6b0a78df0c5d35d2fcc75c6b021bd0fb8df Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Mon, 15 Jan 2024 13:58:30 -0800
Subject: [PATCH 03/13] Create Pause-Utilities.svg
---
images/SharkPool/Pause-Utilities.svg | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 images/SharkPool/Pause-Utilities.svg
diff --git a/images/SharkPool/Pause-Utilities.svg b/images/SharkPool/Pause-Utilities.svg
new file mode 100644
index 0000000000..730e9e3acc
--- /dev/null
+++ b/images/SharkPool/Pause-Utilities.svg
@@ -0,0 +1,13 @@
+
+
From 740539b7452d2eeac2ce655d1c6a89afb0e9a5e7 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Wed, 24 Jan 2024 19:24:40 -0800
Subject: [PATCH 04/13] Use Push Thread
---
extensions/SharkPool/Pause-Utilities.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index fe3e13cd1a..a0418905d1 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -36,12 +36,11 @@
const object = util.blocks._blocks;
const keysV = getKeysByValue(object, "opcode", "SPPause_whenProjectPaused");
for (const keyV of keysV) {
- if (projectPaused) vm.setEditingTarget(util.id);
if (runtime.threads) {
let threadExists = runtime.threads.some(thread => thread.topBlock === object[keyV].id);
if (!threadExists) {
if (projectPaused) {
- vm.runtime.toggleScript(object[keyV].id, util);
+ vm.runtime._pushThread(object[keyV].id, util);
checkReset(object[keyV].id);
}
} else { checkReset(object[keyV].id) }
From 62381d5d575099e82955f926bc45ab37d781f4c3 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Wed, 7 Feb 2024 17:55:51 -0800
Subject: [PATCH 05/13] Update Pause-Utilities.js
---
extensions/SharkPool/Pause-Utilities.js | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index a0418905d1..bf9241bd28 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -135,8 +135,8 @@
defaultValue: "my variable"
},
NUM: {
- type: Scratch.ArgumentType.NUMBER,
- defaultValue: 0
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0"
}
}
},
@@ -154,8 +154,8 @@
defaultValue: "my variable"
},
NUM: {
- type: Scratch.ArgumentType.NUMBER,
- defaultValue: 0
+ type: Scratch.ArgumentType.STRING,
+ defaultValue: "0"
}
}
},
@@ -256,18 +256,14 @@
runtime.isPackaged ? `[class*="pause-button"]` :
"img.pause-btn.addons-display-none-pause"
);
- if (pauseButton) {
- pauseButton.click();
- } else { console.log("Pause button not found") }
+ if (pauseButton) pauseButton.click();
+ else console.log("Pause button not found");
}
}
unpause() {
- if (Scratch.extensions.isPenguinMod) {
- runtime.play()
- } else {
- this.pause();
- }
+ if (Scratch.extensions.isPenguinMod) runtime.play()
+ else this.pause();
}
// by itself, the block is useless, but with the event block it is :D
From 4464da07640bc5f28dd329112b9540bb4703a5a5 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Sun, 25 Feb 2024 18:54:38 -0800
Subject: [PATCH 06/13] Update Pause-Utilities.js
---
extensions/SharkPool/Pause-Utilities.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index bf9241bd28..124d9f5f27 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -3,7 +3,7 @@
// Description: Pause the Project and certain Scripts
// By: SharkPool
-// Version V.1.6.0 (TW Version)
+// Version V.1.6.4 (TW Version)
(function (Scratch) {
"use strict";
@@ -253,7 +253,7 @@
runtime.pause();
} else {
const pauseButton = document.querySelector(
- runtime.isPackaged ? `[class*="pause-button"]` :
+ typeof scaffolding !== "undefined" ? `[class*="pause-button"]` :
"img.pause-btn.addons-display-none-pause"
);
if (pauseButton) pauseButton.click();
From 9f99b0b6c8f517fc814af02677c1534d8e5a5db2 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Thu, 23 May 2024 21:34:48 -0700
Subject: [PATCH 07/13] Pause-Utilities -- Faster & Better Code
---
extensions/SharkPool/Pause-Utilities.js | 202 ++++++++++--------------
1 file changed, 85 insertions(+), 117 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index 124d9f5f27..e536aab268 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -3,16 +3,15 @@
// Description: Pause the Project and certain Scripts
// By: SharkPool
-// Version V.1.6.4 (TW Version)
+// Version V.1.7.0
(function (Scratch) {
"use strict";
- if (!Scratch.extensions.unsandboxed) alert("Pause Utilities Extension must run unsandboxed!");
+ if (!Scratch.extensions.unsandboxed) alert("Pause Utilities must run unsandboxed!");
+
const vm = Scratch.vm;
- const runtime = Scratch.vm.runtime;
+ const runtime = vm.runtime;
const Cast = Scratch.Cast;
- let storedScripts = {};
- let projectPaused = false;
const menuIconURI =
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTgiIHdpZHRoPSIxOCI+PHBhdGggZD0iTTIzMS40MjkgMTg4LjkyOVYxNzEuMDdoNC4yODV2MTcuODU4em0xMi4xNDIgMFYxNzEuMDdoNC4yODZ2MTcuODU4eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzMwOSAwIDAgLjk1NDI3IC0yMzguNTczIC0xNjIuNzY5KSIgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsPSIjZmZhZTAwIiBzdHJva2U9IiNkODk0MDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOm5vcm1hbCIvPjwvc3ZnPg==";
@@ -20,51 +19,57 @@
const blockIconURI =
"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzMS40NzcxNCIgaGVpZ2h0PSIzMS40NzcxNCIgdmlld0JveD0iMCwwLDMxLjQ3NzE0LDMxLjQ3NzE0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjI0LjI2MTQzLC0xNjQuMjYxNDMpIj48ZyBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGwtcnVsZT0ibm9uemVybyIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLWRhc2hhcnJheT0iIiBzdHJva2UtZGFzaG9mZnNldD0iMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjxwYXRoIGQ9Ik0yMjQuMjYxNDMsMTk1LjczODU3di0zMS40NzcxNGgzMS40NzcxNHYzMS40NzcxNHoiIGZpbGw9IiM1ZjViNDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+PHBhdGggZD0iTTIzMS41MjgxOSwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI2Nzl2MTcuMDQxMzV6TTI0NC4wNzE5NiwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI3ODJ2MTcuMDQxMzV6IiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGw9IiNmZmFlMDAiIHN0cm9rZT0iI2Q4OTQwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9nPjwvZz48L3N2Zz4=";
+ // Inject Pause Event
+ Object.defineProperty(runtime.ioDevices.clock, "_paused", {
+ set: function(value) {
+ this._pausedValue = value;
+ if (value) this.SP_whilePaused();
+ else this.SP_unpaused();
+ },
+ get: function() { return this._pausedValue; }
+ });
+
+ runtime.ioDevices.clock.SP_whilePaused = function() {
+ if (this.pauseEventInterval) return;
+ this.pauseEventInterval = setInterval(() => {
+ if (this._pausedValue) runtime.emit("SP_PROJECT_PAUSED", true);
+ }, 10);
+ };
+ runtime.ioDevices.clock.SP_unpaused = function() {
+ if (this.pauseEventInterval) {
+ clearInterval(this.pauseEventInterval);
+ this.pauseEventInterval = null;
+ // Delayed to Prevent Started Threads while Paused (rare condition, Failsafe)
+ setTimeout(function() { runtime.emit("SP_PROJECT_UNPAUSED", true) }, 10);
+ }
+ };
+
+ let storedScripts = {};
+ let projectPaused = false;
+
runtime.on("PROJECT_STOP_ALL", () => { storedScripts = {} });
+ runtime.on("SP_PROJECT_UNPAUSED", () => {
+ runtime.startHats("SPPause_whenProjectUnPaused");
+ // Fix Paused Threads (Rare and Shouldnt Happen, but Failsafe)
+ for (let i = 0; i < runtime.threads.length; i++) {
+ const thread = runtime.threads[i];
+ if (thread.status === undefined) thread.status = 4;
+ }
+ });
- function beginScan() {
- let isChecking = false;
- const check = () => {
- if (isChecking) return;
- isChecking = true;
- try {
- projectPaused = runtime.ioDevices.clock._paused;
- if (!projectPaused) return;
- const allUtils = vm.runtime.targets;
- for (let i = 0; i < allUtils.length; i++) {
- const util = allUtils[i];
- const object = util.blocks._blocks;
- const keysV = getKeysByValue(object, "opcode", "SPPause_whenProjectPaused");
- for (const keyV of keysV) {
- if (runtime.threads) {
- let threadExists = runtime.threads.some(thread => thread.topBlock === object[keyV].id);
- if (!threadExists) {
- if (projectPaused) {
- vm.runtime._pushThread(object[keyV].id, util);
- checkReset(object[keyV].id);
- }
- } else { checkReset(object[keyV].id) }
- }
- }
- }
- } catch {} finally {
- isChecking = false;
- setTimeout(check, 10);
+ runtime.on("SP_PROJECT_PAUSED", () => {
+ projectPaused = runtime.ioDevices.clock._paused;
+ runtime.allScriptsByOpcodeDo("SPPause_whenProjectPaused", (script, target) => {
+ const topBlockId = script.blockId;
+ const threadExists = runtime.threads.find(thread => thread.topBlock === topBlockId);
+ if (!threadExists) {
+ setTimeout(function() {
+ // Offset to not pause the generator
+ runtime._pushThread(topBlockId, target);
+ }, 1);
}
- };
- check();
- }
- function getKeysByValue(object, name, value) {
- const keys = [];
- for (const key in object) {
- if (object[key][name] === value) keys.push(key);
- }
- return keys;
- }
- function checkReset(ID) {
- const threadExists = runtime.threads.find(thread => thread.topBlock === ID);
- if (threadExists.status === undefined) threadExists.status = 4;
- }
+ });
+ });
class SPPause {
getInfo() {
@@ -92,6 +97,12 @@
text: "when project is paused",
isEdgeActivated: false
},
+ {
+ opcode: "whenProjectUnPaused",
+ blockType: Scratch.BlockType.EVENT,
+ text: "when project is unpaused",
+ isEdgeActivated: false
+ },
{
opcode: "isProjectPaused",
blockType: Scratch.BlockType.BOOLEAN,
@@ -103,10 +114,7 @@
blockType: Scratch.BlockType.COMMAND,
text: "pause [SPRITE]",
arguments: {
- SPRITE: {
- type: Scratch.ArgumentType.STRING,
- menu: "TARGETS"
- }
+ SPRITE: { type: Scratch.ArgumentType.STRING, menu: "TARGETS" }
}
},
{
@@ -114,10 +122,7 @@
blockType: Scratch.BlockType.COMMAND,
text: "unpause [SPRITE]",
arguments: {
- SPRITE: {
- type: Scratch.ArgumentType.STRING,
- menu: "TARGETS"
- }
+ SPRITE: { type: Scratch.ArgumentType.STRING, menu: "TARGETS" }
}
},
"---",
@@ -126,18 +131,9 @@
blockType: Scratch.BlockType.COMMAND,
text: "pause clones of [SPRITE] with [VAR] set to [NUM]",
arguments: {
- SPRITE: {
- type: Scratch.ArgumentType.STRING,
- menu: "TARGETS2"
- },
- VAR: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my variable"
- },
- NUM: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "0"
- }
+ SPRITE: { type: Scratch.ArgumentType.STRING, menu: "TARGETS2" },
+ VAR: { type: Scratch.ArgumentType.STRING, defaultValue: "my variable" },
+ NUM: { type: Scratch.ArgumentType.STRING, defaultValue: 0 }
}
},
{
@@ -145,18 +141,9 @@
blockType: Scratch.BlockType.COMMAND,
text: "unpause clones of [SPRITE] with [VAR] set to [NUM]",
arguments: {
- SPRITE: {
- type: Scratch.ArgumentType.STRING,
- menu: "TARGETS2"
- },
- VAR: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my variable"
- },
- NUM: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "0"
- }
+ SPRITE: { type: Scratch.ArgumentType.STRING, menu: "TARGETS2" },
+ VAR: { type: Scratch.ArgumentType.STRING, defaultValue: "my variable" },
+ NUM: { type: Scratch.ArgumentType.STRING, defaultValue: 0 }
}
},
{ blockType: Scratch.BlockType.LABEL, text: "Script Control" },
@@ -165,10 +152,7 @@
blockType: Scratch.BlockType.COMMAND,
text: "pause this script with ID [NAME]",
arguments: {
- NAME: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my script"
- }
+ NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
}
},
{
@@ -176,10 +160,7 @@
blockType: Scratch.BlockType.COMMAND,
text: "unpause script with ID [NAME]",
arguments: {
- NAME: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my script"
- }
+ NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
}
},
{
@@ -188,40 +169,12 @@
text: "unpause all scripts"
},
"---",
- {
- opcode: "pauseLoopCon",
- blockType: Scratch.BlockType.COMMAND,
- text: "if [CON] pause this script with ID [NAME]",
- arguments: {
- CON: { type: Scratch.ArgumentType.BOOLEAN },
- NAME: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my script"
- }
- }
- },
- {
- opcode: "breakLoopCon",
- blockType: Scratch.BlockType.COMMAND,
- text: "if [CON] unpause script with ID [NAME]",
- arguments: {
- CON: { type: Scratch.ArgumentType.BOOLEAN },
- NAME: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my script"
- }
- }
- },
- "---",
{
opcode: "isPaused",
blockType: Scratch.BlockType.BOOLEAN,
text: "is script with ID [NAME] paused?",
arguments: {
- NAME: {
- type: Scratch.ArgumentType.STRING,
- defaultValue: "my script"
- }
+ NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
}
},
{
@@ -230,6 +183,22 @@
text: "all paused scripts",
disableMonitor: true
},
+ {
+ opcode: "pauseLoopCon", blockType: Scratch.BlockType.COMMAND,
+ hideFromPalette: true, // Deprecated
+ text: "if [CON] pause this script with ID [NAME]",
+ arguments: {
+ CON: { type: Scratch.ArgumentType.BOOLEAN }, NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
+ }
+ },
+ {
+ opcode: "breakLoopCon", blockType: Scratch.BlockType.COMMAND,
+ hideFromPalette: true, // Deprecated
+ text: "if [CON] unpause script with ID [NAME]",
+ arguments: {
+ CON: { type: Scratch.ArgumentType.BOOLEAN }, NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
+ }
+ }
],
menus: {
TARGETS: { acceptReporters: true, items: this._getTargets(0) },
@@ -335,6 +304,5 @@
allPausedScripts() { return JSON.stringify(Object.keys(storedScripts)) }
}
- beginScan()
Scratch.extensions.register(new SPPause());
})(Scratch);
From 40ba33605ff65b43772bf3da5dc6b2ce7e24b2e3 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Thu, 23 May 2024 21:52:15 -0700
Subject: [PATCH 08/13] Pause-Utilities -- Add OG func Listener (I forgor)
---
extensions/SharkPool/Pause-Utilities.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index e536aab268..e9a1211ffd 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -20,9 +20,12 @@
"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzMS40NzcxNCIgaGVpZ2h0PSIzMS40NzcxNCIgdmlld0JveD0iMCwwLDMxLjQ3NzE0LDMxLjQ3NzE0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjI0LjI2MTQzLC0xNjQuMjYxNDMpIj48ZyBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGwtcnVsZT0ibm9uemVybyIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLWRhc2hhcnJheT0iIiBzdHJva2UtZGFzaG9mZnNldD0iMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjxwYXRoIGQ9Ik0yMjQuMjYxNDMsMTk1LjczODU3di0zMS40NzcxNGgzMS40NzcxNHYzMS40NzcxNHoiIGZpbGw9IiM1ZjViNDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+PHBhdGggZD0iTTIzMS41MjgxOSwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI2Nzl2MTcuMDQxMzV6TTI0NC4wNzE5NiwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI3ODJ2MTcuMDQxMzV6IiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGw9IiNmZmFlMDAiIHN0cm9rZT0iI2Q4OTQwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9nPjwvZz48L3N2Zz4=";
// Inject Pause Event
+ // Save original function if it exists
+ let ogPauseFunc = Object.getOwnPropertyDescriptor(runtime.ioDevices.clock, "_paused")?.set;
Object.defineProperty(runtime.ioDevices.clock, "_paused", {
set: function(value) {
this._pausedValue = value;
+ if (ogPauseFunc) ogPauseFunc.call(this, value);
if (value) this.SP_whilePaused();
else this.SP_unpaused();
},
@@ -54,6 +57,7 @@
for (let i = 0; i < runtime.threads.length; i++) {
const thread = runtime.threads[i];
if (thread.status === undefined) thread.status = 4;
+ if (thread.status === 5) thread.status = 0; // PenguinMod
}
});
@@ -69,6 +73,7 @@
}, 1);
}
});
+ if (Scratch.extensions.isPenguinMod && projectPaused) runtime._step();
});
class SPPause {
From 9a0cd167720ef8e8730446a720bc983cbc5fef71 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Thu, 11 Jul 2024 18:10:22 -0700
Subject: [PATCH 09/13] Pause-Utilities -- Rename Block for Clarity
---
extensions/SharkPool/Pause-Utilities.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index e9a1211ffd..6a3aa6fd35 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -3,7 +3,7 @@
// Description: Pause the Project and certain Scripts
// By: SharkPool
-// Version V.1.7.0
+// Version V.1.7.01
(function (Scratch) {
"use strict";
@@ -99,7 +99,7 @@
{
opcode: "whenProjectPaused",
blockType: Scratch.BlockType.EVENT,
- text: "when project is paused",
+ text: "while project is paused",
isEdgeActivated: false
},
{
From 5c7abc86eb7d5494a5a48f7b7c4aac43e265b844 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Sat, 3 Aug 2024 08:23:45 -0700
Subject: [PATCH 10/13] Pause-Utilities -- rewrite and fixes
---
extensions/SharkPool/Pause-Utilities.js | 100 +++++++++---------------
1 file changed, 38 insertions(+), 62 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index 6a3aa6fd35..5abb7af74b 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -3,7 +3,7 @@
// Description: Pause the Project and certain Scripts
// By: SharkPool
-// Version V.1.7.01
+// Version V.1.7.02
(function (Scratch) {
"use strict";
@@ -14,10 +14,15 @@
const Cast = Scratch.Cast;
const menuIconURI =
-"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTgiIHdpZHRoPSIxOCI+PHBhdGggZD0iTTIzMS40MjkgMTg4LjkyOVYxNzEuMDdoNC4yODV2MTcuODU4em0xMi4xNDIgMFYxNzEuMDdoNC4yODZ2MTcuODU4eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzMwOSAwIDAgLjk1NDI3IC0yMzguNTczIC0xNjIuNzY5KSIgZGF0YS1wYXBlci1kYXRhPSJ7JnF1b3Q7aXNQYWludGluZ0xheWVyJnF1b3Q7OnRydWV9IiBmaWxsPSIjZmZhZTAwIiBzdHJva2U9IiNkODk0MDAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOm5vcm1hbCIvPjwvc3ZnPg==";
-
+"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTgiIHdpZHRoPSIxOCI+PHBhdGggZD0iTTIzMS40MjkgMTg4LjkyOVYxNzEuMDdoNC4yODV2MTcuODU4em0xMi4xNDIgMFYxNzEuMDdoNC4yODZ2MTcuODU4eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzMwOSAwIDAgLjk1NDI3IC0yMzguNTczIC0xNjIuNzY5KSIgZmlsbD0iI2ZmYWUwMCIgc3Ryb2tlPSIjZDg5NDAwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiLz48L3N2Zz4=";
const blockIconURI =
-"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIzMS40NzcxNCIgaGVpZ2h0PSIzMS40NzcxNCIgdmlld0JveD0iMCwwLDMxLjQ3NzE0LDMxLjQ3NzE0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjI0LjI2MTQzLC0xNjQuMjYxNDMpIj48ZyBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGwtcnVsZT0ibm9uemVybyIgc3Ryb2tlLWxpbmVjYXA9ImJ1dHQiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLWRhc2hhcnJheT0iIiBzdHJva2UtZGFzaG9mZnNldD0iMCIgc3R5bGU9Im1peC1ibGVuZC1tb2RlOiBub3JtYWwiPjxwYXRoIGQ9Ik0yMjQuMjYxNDMsMTk1LjczODU3di0zMS40NzcxNGgzMS40NzcxNHYzMS40NzcxNHoiIGZpbGw9IiM1ZjViNDkiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIwIi8+PHBhdGggZD0iTTIzMS41MjgxOSwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI2Nzl2MTcuMDQxMzV6TTI0NC4wNzE5NiwxODguNDk5MTN2LTE3LjA0MjMxaDQuNDI3ODJ2MTcuMDQxMzV6IiBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGw9IiNmZmFlMDAiIHN0cm9rZT0iI2Q4OTQwMCIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9nPjwvZz48L3N2Zz4=";
+"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMS40NzciIGhlaWdodD0iMzEuNDc3IiB2aWV3Qm94PSIwIDAgMzEuNDc3IDMxLjQ3NyI+PGcgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIj48cGF0aCBkPSJNMCAzMS40NzhWLS4wMDFoMzEuNDc4djMxLjQ3OHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNNy4yNjcgMjQuMjM5VjcuMTk2aDQuNDI3djE3LjA0MXptMTIuNTQ0IDBWNy4xOTZoNC40Mjh2MTcuMDQxeiIgZmlsbD0iI2ZmYWUwMCIgc3Ryb2tlPSIjZDg5NDAwIi8+PC9nPjwvc3ZnPg==";
+
+ let storedScripts = {};
+ let paused = false;
+ let pausedThreadState = new WeakMap();
+ let pauseNewThreads = false, steppingThread = null;
+ let audioContextStateChange = Promise.resolve();
// Inject Pause Event
// Save original function if it exists
@@ -31,24 +36,24 @@
},
get: function() { return this._pausedValue; }
});
-
- runtime.ioDevices.clock.SP_whilePaused = function() {
+ runtime.ioDevices.clock.SP_whilePaused = function () {
if (this.pauseEventInterval) return;
this.pauseEventInterval = setInterval(() => {
if (this._pausedValue) runtime.emit("SP_PROJECT_PAUSED", true);
}, 10);
};
- runtime.ioDevices.clock.SP_unpaused = function() {
+ runtime.ioDevices.clock.SP_unpaused = function () {
if (this.pauseEventInterval) {
clearInterval(this.pauseEventInterval);
this.pauseEventInterval = null;
// Delayed to Prevent Started Threads while Paused (rare condition, Failsafe)
- setTimeout(function() { runtime.emit("SP_PROJECT_UNPAUSED", true) }, 10);
+ setTimeout(() => { runtime.emit("SP_PROJECT_UNPAUSED", true) }, 10);
}
};
- let storedScripts = {};
- let projectPaused = false;
+ // Inject Pause Module (minified)
+ // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js#L407
+ const isPaused=()=>paused,pauseThread=e=>{if(e.updateMonitor||pausedThreadState.has(e))return;let t={time:runtime.currentMSecs,status:e.status};pausedThreadState.set(e,t),e.status=1},ensurePausedThreadIsStillPaused=e=>{if(4===e.status)return;let t=pausedThreadState.get(e);t&&1!==e.status&&(t.status=e.status,e.status=1)},setSteppingThread=e=>{steppingThread=e},compensateForTimePassedWhilePaused=(e,t)=>{e.timer&&(e.timer.startTime+=runtime.currentMSecs-t.time),e.compatibilityStackFrame&&e.compatibilityStackFrame.timer&&(e.compatibilityStackFrame.timer.startTime+=runtime.currentMSecs-t.time);let r=e.peekStackFrame();r&&r.executionContext&&r.executionContext.timer&&(r.executionContext.timer.startTime+=runtime.currentMSecs-t.time)},stepUnsteppedThreads=e=>{let t=runtime.threads,r=getThreadIndex(e);if(-1!==r)for(let a=r;a{let t=paused!==e;if(t&&(paused=e),paused){audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.suspend()),runtime.ioDevices.clock._paused||runtime.ioDevices.clock.pause(),runtime.threads.forEach(pauseThread);let r=runtime.sequencer.activeThread;r&&setSteppingThread(r)}if(!paused&&t){for(let a of(audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.resume()),runtime.ioDevices.clock.resume(),runtime.threads)){let s=pausedThreadState.get(a);s&&(compensateForTimePassedWhilePaused(a,s),a.status=s.status)}pausedThreadState=new WeakMap;let i=steppingThread;stepUnsteppedThreads(i),steppingThread=null}},getRunningThread=()=>steppingThread,singleStepThread=e=>{if(4===e.status||e.isCompiled)return!1;let t=e.peekStack();if(!t&&(e.popStack(),0===e.stack.length))return e.status=4,!1;pauseNewThreads=!0,runtime.sequencer.activeThread=e;let r=["special error used by Scratch Addons for implementing single-stepping"];Object.defineProperty(e,"blockGlowInFrame",{set(e){throw r}});try{e.status=0,e.warpTimer&&e.warpTimer.start();try{runtime.sequencer.stepThread(e)}catch(a){if(a!==r)throw a}if(0!==e.status)return!1;for(e.peekStack()===t&&e.goToNextBlock();!e.peekStack();){if(e.popStack(),0===e.stack.length)return e.status=4,!1;let s=e.peekStackFrame();if(s.isLoop){if(e.peekStackFrame().warpMode)continue;return!1}if(s.waitingReporter)return!1;e.goToNextBlock()}return!0}finally{pauseNewThreads=!1,runtime.sequencer.activeThread=null,Object.defineProperty(e,"blockGlowInFrame",{value:t,configurable:!0,enumerable:!0,writable:!0}),4!==e.status&&(e.status=1)}},getRealStatus=e=>{let t=pausedThreadState.get(e);return t?t.status:e.status},getThreadIndex=e=>e?runtime.threads.findIndex(t=>t.target===e.target&&t.topBlock===e.topBlock&&t.stackClick===e.stackClick&&t.updateMonitor===e.updateMonitor):-1,findNewSteppingThread=e=>{let t=runtime.threads;for(let r=e;r{if(steppingThread){let e=pausedThreadState.get(steppingThread);compensateForTimePassedWhilePaused(steppingThread,e),e.time=runtime.currentMSecs;let t=singleStepThread(steppingThread);t||(steppingThread=findNewSteppingThread(getThreadIndex(steppingThread)+1))}if(!steppingThread){setSteppingThread(findNewSteppingThread(0)),runtime.ioDevices.clock._pausedTime+=runtime.currentStepTime;let r=runtime.audioEngine.audioContext;for(let a of runtime.targets)for(let s of Object.keys(a.sprite.soundBank.soundPlayers)){let i=a.sprite.soundBank.soundPlayers[s];i.outputNode&&(i.outputNode.stop(r.currentTime),i._createSource(),i.outputNode.start(r.currentTime,r.currentTime-i.startingUntil+runtime.currentStepTime/1e3),i.startingUntil-=runtime.currentStepTime/1e3)}for(let n of runtime.threads)pausedThreadState.has(n)&&(pausedThreadState.get(n).time+=runtime.currentStepTime);pauseNewThreads=!0;let u=runtime._hats;for(let o in u){if(!Object.prototype.hasOwnProperty.call(u,o))continue;let l=u[o];l.edgeActivated&&runtime.startHats(o)}pauseNewThreads=!1}},setup=()=>{let e=vm,t=e.runtime.sequencer.stepThreads;e.runtime.sequencer.stepThreads=function(){if(isPaused())for(let e of this.runtime.threads)ensurePausedThreadIsStillPaused(e);return t.call(this)};let r=e.runtime.greenFlag;e.runtime.greenFlag=function(){return setPaused(!1),r.call(this)};let a=e.runtime.startHats;e.runtime.startHats=function(...e){let t=e[0],r="event_whenbroadcastreceived"===t||"control_start_as_clone"===t;if(pauseNewThreads){if(!r&&!this.getIsEdgeActivatedHat(t))return[];let s=a.apply(this,e);for(let i of s)pauseThread(i);return s}return paused&&!r?[]:a.apply(this,e)};let s=e.runtime._getMonitorThreadCount;e.runtime._getMonitorThreadCount=function(e){let t=s.call(this,e);if(paused)for(let r of e)pausedThreadState.has(r)&&t++;return t}};
runtime.on("PROJECT_STOP_ALL", () => { storedScripts = {} });
runtime.on("SP_PROJECT_UNPAUSED", () => {
@@ -57,23 +62,20 @@
for (let i = 0; i < runtime.threads.length; i++) {
const thread = runtime.threads[i];
if (thread.status === undefined) thread.status = 4;
- if (thread.status === 5) thread.status = 0; // PenguinMod
+ if (thread.status === 5) thread.status = 0;
}
});
runtime.on("SP_PROJECT_PAUSED", () => {
- projectPaused = runtime.ioDevices.clock._paused;
+ paused = runtime.ioDevices.clock._paused;
runtime.allScriptsByOpcodeDo("SPPause_whenProjectPaused", (script, target) => {
const topBlockId = script.blockId;
const threadExists = runtime.threads.find(thread => thread.topBlock === topBlockId);
if (!threadExists) {
- setTimeout(function() {
- // Offset to not pause the generator
- runtime._pushThread(topBlockId, target);
- }, 1);
+ // Offset to not pause the generator, use Timeout as AFTER_EXECUTE isnt smooth
+ setTimeout(() => { runtime._pushThread(topBlockId, target) }, 1);
}
});
- if (Scratch.extensions.isPenguinMod && projectPaused) runtime._step();
});
class SPPause {
@@ -187,22 +189,6 @@
blockType: Scratch.BlockType.REPORTER,
text: "all paused scripts",
disableMonitor: true
- },
- {
- opcode: "pauseLoopCon", blockType: Scratch.BlockType.COMMAND,
- hideFromPalette: true, // Deprecated
- text: "if [CON] pause this script with ID [NAME]",
- arguments: {
- CON: { type: Scratch.ArgumentType.BOOLEAN }, NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
- }
- },
- {
- opcode: "breakLoopCon", blockType: Scratch.BlockType.COMMAND,
- hideFromPalette: true, // Deprecated
- text: "if [CON] unpause script with ID [NAME]",
- arguments: {
- CON: { type: Scratch.ArgumentType.BOOLEAN }, NAME: { type: Scratch.ArgumentType.STRING, defaultValue: "my script" }
- }
}
],
menus: {
@@ -214,7 +200,7 @@
_getTargets(ind) {
const spriteNames = [];
- const targets = Scratch.vm.runtime.targets;
+ const targets = runtime.targets;
for (let index = ind; index < targets.length; index++) {
const target = targets[index];
if (target.isOriginal) spriteNames.push(target.getName());
@@ -222,26 +208,29 @@
return spriteNames.length > 0 ? spriteNames : [""];
}
+ searchThreads(target, cntrl) {
+ const thread = runtime.threads;
+ thread.forEach(t => {
+ if (t.target.id === target && t.status !== cntrl) t.status = cntrl;
+ });
+ }
+
pause() {
- if (Scratch.extensions.isPenguinMod) {
- runtime.pause();
- } else {
- const pauseButton = document.querySelector(
- typeof scaffolding !== "undefined" ? `[class*="pause-button"]` :
- "img.pause-btn.addons-display-none-pause"
- );
- if (pauseButton) pauseButton.click();
- else console.log("Pause button not found");
- }
+ const btn = document.querySelector(typeof scaffolding !== "undefined" ? `[class*="pause-button"]` : "img.pause-btn.addons-display-none-pause");
+ if (btn) btn.click();
+ else setPaused(true);
}
unpause() {
- if (Scratch.extensions.isPenguinMod) runtime.play()
- else this.pause();
+ const btn = document.querySelector(typeof scaffolding !== "undefined" ? `[class*="pause-button"]` : "img.pause-btn.addons-display-none-pause");
+ // Ignore "generator is running" error. It lies :0
+ try {
+ if (btn) btn.click();
+ else setPaused(false);
+ } catch {}
}
- // by itself, the block is useless, but with the event block it is :D
- isProjectPaused() { return projectPaused }
+ isProjectPaused() { return paused }
pauseSprite(args) {
const target = args.SPRITE === "Stage" ? runtime.getTargetForStage() : runtime.getSpriteTargetByName(args.SPRITE);
@@ -254,12 +243,6 @@
pauseClones(args) { this.modifyClones.call(this, args, 1) }
unpauseClones(args) { this.modifyClones.call(this, args, 0) }
- searchThreads(target, cntrl) {
- const thread = runtime.threads;
- thread.forEach(t => {
- if (t.target.id === target && t.status !== cntrl) t.status = cntrl;
- });
- }
modifyClones(args, cntrl) {
const target = runtime.getSpriteTargetByName(args.SPRITE);
if (target) {
@@ -273,10 +256,6 @@
}
}
- pauseLoopCon(args, util) { if (Cast.toBoolean(args.CON)) this.pauseLoop(args, util) }
-
- breakLoopCon(args) { if (Cast.toBoolean(args.CON)) this.breakLoop(args) }
-
pauseLoop(args, util) {
const scriptName = Cast.toString(args.NAME);
const state = util.stackFrame.pausedScript;
@@ -301,10 +280,7 @@
}
}
- isPaused(args) {
- const scriptName = Cast.toString(args.NAME);
- return scriptName in storedScripts;
- }
+ isPaused(args) { return Cast.toString(args.NAME) in storedScripts }
allPausedScripts() { return JSON.stringify(Object.keys(storedScripts)) }
}
From 7de282c26f75f5fec7646977984a727ac76e2a67 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Sat, 3 Aug 2024 08:28:22 -0700
Subject: [PATCH 11/13] shut up prettier
---
extensions/SharkPool/Pause-Utilities.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index 5abb7af74b..42378bf146 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -52,7 +52,8 @@
};
// Inject Pause Module (minified)
- // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js#L407
+ // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js
+ // eslint-disable-next-line
const isPaused=()=>paused,pauseThread=e=>{if(e.updateMonitor||pausedThreadState.has(e))return;let t={time:runtime.currentMSecs,status:e.status};pausedThreadState.set(e,t),e.status=1},ensurePausedThreadIsStillPaused=e=>{if(4===e.status)return;let t=pausedThreadState.get(e);t&&1!==e.status&&(t.status=e.status,e.status=1)},setSteppingThread=e=>{steppingThread=e},compensateForTimePassedWhilePaused=(e,t)=>{e.timer&&(e.timer.startTime+=runtime.currentMSecs-t.time),e.compatibilityStackFrame&&e.compatibilityStackFrame.timer&&(e.compatibilityStackFrame.timer.startTime+=runtime.currentMSecs-t.time);let r=e.peekStackFrame();r&&r.executionContext&&r.executionContext.timer&&(r.executionContext.timer.startTime+=runtime.currentMSecs-t.time)},stepUnsteppedThreads=e=>{let t=runtime.threads,r=getThreadIndex(e);if(-1!==r)for(let a=r;a{let t=paused!==e;if(t&&(paused=e),paused){audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.suspend()),runtime.ioDevices.clock._paused||runtime.ioDevices.clock.pause(),runtime.threads.forEach(pauseThread);let r=runtime.sequencer.activeThread;r&&setSteppingThread(r)}if(!paused&&t){for(let a of(audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.resume()),runtime.ioDevices.clock.resume(),runtime.threads)){let s=pausedThreadState.get(a);s&&(compensateForTimePassedWhilePaused(a,s),a.status=s.status)}pausedThreadState=new WeakMap;let i=steppingThread;stepUnsteppedThreads(i),steppingThread=null}},getRunningThread=()=>steppingThread,singleStepThread=e=>{if(4===e.status||e.isCompiled)return!1;let t=e.peekStack();if(!t&&(e.popStack(),0===e.stack.length))return e.status=4,!1;pauseNewThreads=!0,runtime.sequencer.activeThread=e;let r=["special error used by Scratch Addons for implementing single-stepping"];Object.defineProperty(e,"blockGlowInFrame",{set(e){throw r}});try{e.status=0,e.warpTimer&&e.warpTimer.start();try{runtime.sequencer.stepThread(e)}catch(a){if(a!==r)throw a}if(0!==e.status)return!1;for(e.peekStack()===t&&e.goToNextBlock();!e.peekStack();){if(e.popStack(),0===e.stack.length)return e.status=4,!1;let s=e.peekStackFrame();if(s.isLoop){if(e.peekStackFrame().warpMode)continue;return!1}if(s.waitingReporter)return!1;e.goToNextBlock()}return!0}finally{pauseNewThreads=!1,runtime.sequencer.activeThread=null,Object.defineProperty(e,"blockGlowInFrame",{value:t,configurable:!0,enumerable:!0,writable:!0}),4!==e.status&&(e.status=1)}},getRealStatus=e=>{let t=pausedThreadState.get(e);return t?t.status:e.status},getThreadIndex=e=>e?runtime.threads.findIndex(t=>t.target===e.target&&t.topBlock===e.topBlock&&t.stackClick===e.stackClick&&t.updateMonitor===e.updateMonitor):-1,findNewSteppingThread=e=>{let t=runtime.threads;for(let r=e;r{if(steppingThread){let e=pausedThreadState.get(steppingThread);compensateForTimePassedWhilePaused(steppingThread,e),e.time=runtime.currentMSecs;let t=singleStepThread(steppingThread);t||(steppingThread=findNewSteppingThread(getThreadIndex(steppingThread)+1))}if(!steppingThread){setSteppingThread(findNewSteppingThread(0)),runtime.ioDevices.clock._pausedTime+=runtime.currentStepTime;let r=runtime.audioEngine.audioContext;for(let a of runtime.targets)for(let s of Object.keys(a.sprite.soundBank.soundPlayers)){let i=a.sprite.soundBank.soundPlayers[s];i.outputNode&&(i.outputNode.stop(r.currentTime),i._createSource(),i.outputNode.start(r.currentTime,r.currentTime-i.startingUntil+runtime.currentStepTime/1e3),i.startingUntil-=runtime.currentStepTime/1e3)}for(let n of runtime.threads)pausedThreadState.has(n)&&(pausedThreadState.get(n).time+=runtime.currentStepTime);pauseNewThreads=!0;let u=runtime._hats;for(let o in u){if(!Object.prototype.hasOwnProperty.call(u,o))continue;let l=u[o];l.edgeActivated&&runtime.startHats(o)}pauseNewThreads=!1}},setup=()=>{let e=vm,t=e.runtime.sequencer.stepThreads;e.runtime.sequencer.stepThreads=function(){if(isPaused())for(let e of this.runtime.threads)ensurePausedThreadIsStillPaused(e);return t.call(this)};let r=e.runtime.greenFlag;e.runtime.greenFlag=function(){return setPaused(!1),r.call(this)};let a=e.runtime.startHats;e.runtime.startHats=function(...e){let t=e[0],r="event_whenbroadcastreceived"===t||"control_start_as_clone"===t;if(pauseNewThreads){if(!r&&!this.getIsEdgeActivatedHat(t))return[];let s=a.apply(this,e);for(let i of s)pauseThread(i);return s}return paused&&!r?[]:a.apply(this,e)};let s=e.runtime._getMonitorThreadCount;e.runtime._getMonitorThreadCount=function(e){let t=s.call(this,e);if(paused)for(let r of e)pausedThreadState.has(r)&&t++;return t}};
runtime.on("PROJECT_STOP_ALL", () => { storedScripts = {} });
From da2e8f238f719b7f5b32d980e9612f0d7d3136b2 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Thu, 8 Aug 2024 21:54:40 -0700
Subject: [PATCH 12/13] Pause-Utilities -- Minor Fix
---
extensions/SharkPool/Pause-Utilities.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index 42378bf146..9eedb55f40 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -3,7 +3,7 @@
// Description: Pause the Project and certain Scripts
// By: SharkPool
-// Version V.1.7.02
+// Version V.1.7.03
(function (Scratch) {
"use strict";
@@ -52,12 +52,12 @@
};
// Inject Pause Module (minified)
- // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js
- // eslint-disable-next-line
+ // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js#L407
const isPaused=()=>paused,pauseThread=e=>{if(e.updateMonitor||pausedThreadState.has(e))return;let t={time:runtime.currentMSecs,status:e.status};pausedThreadState.set(e,t),e.status=1},ensurePausedThreadIsStillPaused=e=>{if(4===e.status)return;let t=pausedThreadState.get(e);t&&1!==e.status&&(t.status=e.status,e.status=1)},setSteppingThread=e=>{steppingThread=e},compensateForTimePassedWhilePaused=(e,t)=>{e.timer&&(e.timer.startTime+=runtime.currentMSecs-t.time),e.compatibilityStackFrame&&e.compatibilityStackFrame.timer&&(e.compatibilityStackFrame.timer.startTime+=runtime.currentMSecs-t.time);let r=e.peekStackFrame();r&&r.executionContext&&r.executionContext.timer&&(r.executionContext.timer.startTime+=runtime.currentMSecs-t.time)},stepUnsteppedThreads=e=>{let t=runtime.threads,r=getThreadIndex(e);if(-1!==r)for(let a=r;a{let t=paused!==e;if(t&&(paused=e),paused){audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.suspend()),runtime.ioDevices.clock._paused||runtime.ioDevices.clock.pause(),runtime.threads.forEach(pauseThread);let r=runtime.sequencer.activeThread;r&&setSteppingThread(r)}if(!paused&&t){for(let a of(audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.resume()),runtime.ioDevices.clock.resume(),runtime.threads)){let s=pausedThreadState.get(a);s&&(compensateForTimePassedWhilePaused(a,s),a.status=s.status)}pausedThreadState=new WeakMap;let i=steppingThread;stepUnsteppedThreads(i),steppingThread=null}},getRunningThread=()=>steppingThread,singleStepThread=e=>{if(4===e.status||e.isCompiled)return!1;let t=e.peekStack();if(!t&&(e.popStack(),0===e.stack.length))return e.status=4,!1;pauseNewThreads=!0,runtime.sequencer.activeThread=e;let r=["special error used by Scratch Addons for implementing single-stepping"];Object.defineProperty(e,"blockGlowInFrame",{set(e){throw r}});try{e.status=0,e.warpTimer&&e.warpTimer.start();try{runtime.sequencer.stepThread(e)}catch(a){if(a!==r)throw a}if(0!==e.status)return!1;for(e.peekStack()===t&&e.goToNextBlock();!e.peekStack();){if(e.popStack(),0===e.stack.length)return e.status=4,!1;let s=e.peekStackFrame();if(s.isLoop){if(e.peekStackFrame().warpMode)continue;return!1}if(s.waitingReporter)return!1;e.goToNextBlock()}return!0}finally{pauseNewThreads=!1,runtime.sequencer.activeThread=null,Object.defineProperty(e,"blockGlowInFrame",{value:t,configurable:!0,enumerable:!0,writable:!0}),4!==e.status&&(e.status=1)}},getRealStatus=e=>{let t=pausedThreadState.get(e);return t?t.status:e.status},getThreadIndex=e=>e?runtime.threads.findIndex(t=>t.target===e.target&&t.topBlock===e.topBlock&&t.stackClick===e.stackClick&&t.updateMonitor===e.updateMonitor):-1,findNewSteppingThread=e=>{let t=runtime.threads;for(let r=e;r{if(steppingThread){let e=pausedThreadState.get(steppingThread);compensateForTimePassedWhilePaused(steppingThread,e),e.time=runtime.currentMSecs;let t=singleStepThread(steppingThread);t||(steppingThread=findNewSteppingThread(getThreadIndex(steppingThread)+1))}if(!steppingThread){setSteppingThread(findNewSteppingThread(0)),runtime.ioDevices.clock._pausedTime+=runtime.currentStepTime;let r=runtime.audioEngine.audioContext;for(let a of runtime.targets)for(let s of Object.keys(a.sprite.soundBank.soundPlayers)){let i=a.sprite.soundBank.soundPlayers[s];i.outputNode&&(i.outputNode.stop(r.currentTime),i._createSource(),i.outputNode.start(r.currentTime,r.currentTime-i.startingUntil+runtime.currentStepTime/1e3),i.startingUntil-=runtime.currentStepTime/1e3)}for(let n of runtime.threads)pausedThreadState.has(n)&&(pausedThreadState.get(n).time+=runtime.currentStepTime);pauseNewThreads=!0;let u=runtime._hats;for(let o in u){if(!Object.prototype.hasOwnProperty.call(u,o))continue;let l=u[o];l.edgeActivated&&runtime.startHats(o)}pauseNewThreads=!1}},setup=()=>{let e=vm,t=e.runtime.sequencer.stepThreads;e.runtime.sequencer.stepThreads=function(){if(isPaused())for(let e of this.runtime.threads)ensurePausedThreadIsStillPaused(e);return t.call(this)};let r=e.runtime.greenFlag;e.runtime.greenFlag=function(){return setPaused(!1),r.call(this)};let a=e.runtime.startHats;e.runtime.startHats=function(...e){let t=e[0],r="event_whenbroadcastreceived"===t||"control_start_as_clone"===t;if(pauseNewThreads){if(!r&&!this.getIsEdgeActivatedHat(t))return[];let s=a.apply(this,e);for(let i of s)pauseThread(i);return s}return paused&&!r?[]:a.apply(this,e)};let s=e.runtime._getMonitorThreadCount;e.runtime._getMonitorThreadCount=function(e){let t=s.call(this,e);if(paused)for(let r of e)pausedThreadState.has(r)&&t++;return t}};
runtime.on("PROJECT_STOP_ALL", () => { storedScripts = {} });
runtime.on("SP_PROJECT_UNPAUSED", () => {
+ paused = runtime.ioDevices.clock._paused;
runtime.startHats("SPPause_whenProjectUnPaused");
// Fix Paused Threads (Rare and Shouldnt Happen, but Failsafe)
for (let i = 0; i < runtime.threads.length; i++) {
From f050b937c7b5f09eb1ac6d3e251ded11de333523 Mon Sep 17 00:00:00 2001
From: SharkPool <139097378+SharkPool-SP@users.noreply.github.com>
Date: Thu, 8 Aug 2024 21:56:53 -0700
Subject: [PATCH 13/13] shut up prettier
---
extensions/SharkPool/Pause-Utilities.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/extensions/SharkPool/Pause-Utilities.js b/extensions/SharkPool/Pause-Utilities.js
index 9eedb55f40..f2596c7ee2 100644
--- a/extensions/SharkPool/Pause-Utilities.js
+++ b/extensions/SharkPool/Pause-Utilities.js
@@ -52,7 +52,8 @@
};
// Inject Pause Module (minified)
- // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js#L407
+ // https://github.com/TurboWarp/scratch-gui/blob/develop/src/addons/addons/debugger/module.js
+ // eslint-disable-next-line
const isPaused=()=>paused,pauseThread=e=>{if(e.updateMonitor||pausedThreadState.has(e))return;let t={time:runtime.currentMSecs,status:e.status};pausedThreadState.set(e,t),e.status=1},ensurePausedThreadIsStillPaused=e=>{if(4===e.status)return;let t=pausedThreadState.get(e);t&&1!==e.status&&(t.status=e.status,e.status=1)},setSteppingThread=e=>{steppingThread=e},compensateForTimePassedWhilePaused=(e,t)=>{e.timer&&(e.timer.startTime+=runtime.currentMSecs-t.time),e.compatibilityStackFrame&&e.compatibilityStackFrame.timer&&(e.compatibilityStackFrame.timer.startTime+=runtime.currentMSecs-t.time);let r=e.peekStackFrame();r&&r.executionContext&&r.executionContext.timer&&(r.executionContext.timer.startTime+=runtime.currentMSecs-t.time)},stepUnsteppedThreads=e=>{let t=runtime.threads,r=getThreadIndex(e);if(-1!==r)for(let a=r;a{let t=paused!==e;if(t&&(paused=e),paused){audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.suspend()),runtime.ioDevices.clock._paused||runtime.ioDevices.clock.pause(),runtime.threads.forEach(pauseThread);let r=runtime.sequencer.activeThread;r&&setSteppingThread(r)}if(!paused&&t){for(let a of(audioContextStateChange=audioContextStateChange.then(()=>runtime.audioEngine.audioContext.resume()),runtime.ioDevices.clock.resume(),runtime.threads)){let s=pausedThreadState.get(a);s&&(compensateForTimePassedWhilePaused(a,s),a.status=s.status)}pausedThreadState=new WeakMap;let i=steppingThread;stepUnsteppedThreads(i),steppingThread=null}},getRunningThread=()=>steppingThread,singleStepThread=e=>{if(4===e.status||e.isCompiled)return!1;let t=e.peekStack();if(!t&&(e.popStack(),0===e.stack.length))return e.status=4,!1;pauseNewThreads=!0,runtime.sequencer.activeThread=e;let r=["special error used by Scratch Addons for implementing single-stepping"];Object.defineProperty(e,"blockGlowInFrame",{set(e){throw r}});try{e.status=0,e.warpTimer&&e.warpTimer.start();try{runtime.sequencer.stepThread(e)}catch(a){if(a!==r)throw a}if(0!==e.status)return!1;for(e.peekStack()===t&&e.goToNextBlock();!e.peekStack();){if(e.popStack(),0===e.stack.length)return e.status=4,!1;let s=e.peekStackFrame();if(s.isLoop){if(e.peekStackFrame().warpMode)continue;return!1}if(s.waitingReporter)return!1;e.goToNextBlock()}return!0}finally{pauseNewThreads=!1,runtime.sequencer.activeThread=null,Object.defineProperty(e,"blockGlowInFrame",{value:t,configurable:!0,enumerable:!0,writable:!0}),4!==e.status&&(e.status=1)}},getRealStatus=e=>{let t=pausedThreadState.get(e);return t?t.status:e.status},getThreadIndex=e=>e?runtime.threads.findIndex(t=>t.target===e.target&&t.topBlock===e.topBlock&&t.stackClick===e.stackClick&&t.updateMonitor===e.updateMonitor):-1,findNewSteppingThread=e=>{let t=runtime.threads;for(let r=e;r{if(steppingThread){let e=pausedThreadState.get(steppingThread);compensateForTimePassedWhilePaused(steppingThread,e),e.time=runtime.currentMSecs;let t=singleStepThread(steppingThread);t||(steppingThread=findNewSteppingThread(getThreadIndex(steppingThread)+1))}if(!steppingThread){setSteppingThread(findNewSteppingThread(0)),runtime.ioDevices.clock._pausedTime+=runtime.currentStepTime;let r=runtime.audioEngine.audioContext;for(let a of runtime.targets)for(let s of Object.keys(a.sprite.soundBank.soundPlayers)){let i=a.sprite.soundBank.soundPlayers[s];i.outputNode&&(i.outputNode.stop(r.currentTime),i._createSource(),i.outputNode.start(r.currentTime,r.currentTime-i.startingUntil+runtime.currentStepTime/1e3),i.startingUntil-=runtime.currentStepTime/1e3)}for(let n of runtime.threads)pausedThreadState.has(n)&&(pausedThreadState.get(n).time+=runtime.currentStepTime);pauseNewThreads=!0;let u=runtime._hats;for(let o in u){if(!Object.prototype.hasOwnProperty.call(u,o))continue;let l=u[o];l.edgeActivated&&runtime.startHats(o)}pauseNewThreads=!1}},setup=()=>{let e=vm,t=e.runtime.sequencer.stepThreads;e.runtime.sequencer.stepThreads=function(){if(isPaused())for(let e of this.runtime.threads)ensurePausedThreadIsStillPaused(e);return t.call(this)};let r=e.runtime.greenFlag;e.runtime.greenFlag=function(){return setPaused(!1),r.call(this)};let a=e.runtime.startHats;e.runtime.startHats=function(...e){let t=e[0],r="event_whenbroadcastreceived"===t||"control_start_as_clone"===t;if(pauseNewThreads){if(!r&&!this.getIsEdgeActivatedHat(t))return[];let s=a.apply(this,e);for(let i of s)pauseThread(i);return s}return paused&&!r?[]:a.apply(this,e)};let s=e.runtime._getMonitorThreadCount;e.runtime._getMonitorThreadCount=function(e){let t=s.call(this,e);if(paused)for(let r of e)pausedThreadState.has(r)&&t++;return t}};
runtime.on("PROJECT_STOP_ALL", () => { storedScripts = {} });