Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hacked Blocks - Support Argument Hacking #1030

Open
thisandagain opened this issue Apr 6, 2018 · 34 comments
Open

Hacked Blocks - Support Argument Hacking #1030

thisandagain opened this issue Apr 6, 2018 · 34 comments

Comments

@thisandagain
Copy link
Contributor

thisandagain commented Apr 6, 2018

There are many types of "hacked blocks" that are possible in Scratch 2.0. While prior discussions have grouped them all together, we have spent a bunch of time trying to tease apart this landscape so we can understand and hopefully work with the community to support these use cases.

While hacked blocks are uncommon (used by less than 0.01% of shared projects), they are used by some high-profile projects and are interesting to some Scratchers. By far the most common type of hacked block is what we are now referring to as "argument hacking". This issue attempts to break down this type of hacked block with the hope of soliciting support from the community if they wish for Scratch to continue to support these projects in the future.

Examples

Overriding Menu Options

[
    "keyPressed:",
    "\u0010"
]

image

Making "Non-Droppable" Menus "Droppable"

[
    "penColor:",
    [
        "readVariable",
        "tmp"
    ]
]

image

Overriding Custom Procedure Menu Options

[
    "call",
    "colour %c",
    -3384542
]

image

Use Cases

By far the most commonly seen types of "Argument Hacking" are "Overriding Menu Options" and "Making 'Non-Droppable' Menus 'Droppable'". In all cases the project JSON is modified to override the arguments for a given opcode. While specific use cases vary from project to project and block to block, we often see this type of modification performed to support applications such as supporting non-standard keyboard events and dynamically controlling "non-droppable" state.

Example Project

https://llk.github.io/scratch-gui/develop/#214566447

Uncaught Error: Serialized variable type with id '}o/;i5r,O`;[HD478%k?-readVariable,scratch' had type list, and does not match variable field that references it: <field xmlns="http://www.w3.org/1999/xhtml" name="VARIABLE" id="}o/;i5r,O`;[HD478%k?-readVariable,scratch" variabletype="">readVariable,scratch</field>.
    at Object.Blockly.Xml.domToFieldVariable_ (lib.min.js:90)
    at Object.Blockly.Xml.domToField_ (lib.min.js:90)
    at Object.Blockly.Xml.domToBlockHeadless_ (lib.min.js:90)
    at Object.Blockly.Xml.domToBlockHeadless_ (lib.min.js:90)
    at Object.Blockly.Xml.domToBlock (lib.min.js:90)
    at Object.Blockly.Xml.domToWorkspace (lib.min.js:90)
    at Object.Blockly.Xml.clearWorkspaceAndLoadFromXml (lib.min.js:90)
    at t.value (lib.min.js:90)
    at t.l (lib.min.js:1)
    at t.n.emit (lib.min.js:12)
    at t.value (lib.min.js:12)
    at t.value (lib.min.js:12)
    at t.value (lib.min.js:132)
    at Object.l [as onClick] (lib.min.js:1)
    at t.value (lib.min.js:90)
    at l (lib.min.js:1)
    at Object.u (lib.min.js:98)
    at Object.invokeGuardedCallback (lib.min.js:106)
    at Object.invokeGuardedCallbackAndCatchFirstError (lib.min.js:106)
    at f (lib.min.js:98)
    at m (lib.min.js:98)
    at b (lib.min.js:98)
    at Array.forEach (<anonymous>)
    at A (lib.min.js:98)
    at w (lib.min.js:98)
    at Jl (lib.min.js:106)
    at Se (lib.min.js:98)
    at batchedUpdates (lib.min.js:98)
    at $ (lib.min.js:98)
    at Te (lib.min.js:98)
    at HTMLDocument.d (raven.js:425)

/cc @kchadha

@towerofnix
Copy link
Contributor

I'd have a go at this, but I don't really know where to start - if I'm not mistaken, dropdown inputs that don't normally accept blocks fundamentally cannot accept blocks (i.e. they contain no slot for a block to exist in), and I'm not sure how to work around that. (Contrast this to Scratch 2.0, where the only difference between a droppable and not-droppable input is a simple flag!)

(@thisandagain, I wonder if the eleventh slide, "Gallery of the Bizarre", should have a less flashy animation? It was a bit surprising to me when it popped up, and I can imagining it have worse effects on anybody who's more affected by flashing images!)

@djsrv
Copy link

djsrv commented Apr 6, 2018

As someone who's worked with hacked blocks extensively in the past, I can say that most of these have few real use case besides being curiosities.

I think instead of (or in addition to) supporting these hacks, it would be better to provide official methods of doing the things they enable. Hacked blocks have the disadvantage of being difficult to understand and impossible for a regular user to replicate.

Here are two common use cases for argument hacking and how they could be eliminated.

Non-standard key events

Common non-standard key events are shift, backspace, and escape. This could be eliminated by simply adding the keys to the key menu. :) Since they wouldn't be used as often as the existing options, maybe they could be added to the bottom of the menu?

Variable variables

This hack is used to set/get arbitrary variables, similar to PHP's variable variables.
screen shot 2018-04-06 at 15 46 22
The need for this hack could be eliminated by adding dictionaries in addition to lists.
screen shot 2018-04-06 at 15 47 17
This would be easier to understand than the hack, and it's almost certainly a better programming practice. Maybe this could be added as an extension similar to pen?

@thisandagain
Copy link
Contributor Author

thisandagain commented Apr 7, 2018

@towerofnix

I'd have a go at this, but I don't really know where to start - if I'm not mistaken, dropdown inputs that don't normally accept blocks fundamentally cannot accept blocks (i.e. they contain no slot for a block to exist in), and I'm not sure how to work around that. (Contrast this to Scratch 2.0, where the only difference between a droppable and not-droppable input is a simple flag!)

We are in the middle of migrating all blocks to be "extensions" this month and I think that may help provide a more simple / flexible entry point. Stay tuned, I think some of this may become easier to approach soon.

"Gallery of the Bizarre", should have a less flashy animation

Whoops. Yup. Fixed.

@thisandagain
Copy link
Contributor Author

thisandagain commented Apr 7, 2018

As someone who's worked with hacked blocks extensively in the past, I can say that most of these have few real use case besides being curiosities.

Yup. I agree.

I think instead of (or in addition to) supporting these hacks, it would be better to provide official methods of doing the things they enable. Hacked blocks have the disadvantage of being difficult to understand and impossible for a regular user to replicate.

Also agreed.


For the "non-standard key events" stuff we are tracking that here:
scratchfoundation/scratch-gui#1384
#980

For the "variable variables" I think we'd also be open to a proposal for making those inputs droppable (for both variables and lists).

@Mr-Dave2
Copy link

Mr-Dave2 commented Apr 7, 2018

I liked what thisandagain said in his original post about reaching out to the community. I’ve looked at a number hacked block projects and forum posts and I’d guess many Scratchers believe hacked blocks to be an assumed right. And I’d be a little concerned if on the day you release Scratch 3.0 it unexpectedly breaks a number of popular and formally featured projects. Now might be a good time to have a respected Scratcher sort of sit down with us and explain the realities of using undocumented software features. I sure many people won’t need this but I believe that it would be a kindness to the community to give us a heads up.

@joker314
Copy link
Contributor

joker314 commented Apr 8, 2018

Some users tried to create a "pop" block for list manipulation.

(join (item (last v) of (list v)) (letter (0) of {delete (last v) of (list v)})

I think that this feature is useful enough that a new block could be added that does the same thing.

delete and report item (1) of (list)

Having said that, I do not feel that backwards-compatibility is necessary with these sorts of hacked blocks (ones which use stack blocks as reporters), as these types of hacked blocks are incredibly infrequent.

Of course, if custom reporters are implemented, then not only will the above block be easy to implement by a user, it'll also teach a lot more about how the block works, and will prepare them for programming in functional languages

@TheLogFather
Copy link

I'l just say that I agree with @djsrv above that a handful of the current block 'hacks' should be considered for official support (rather than having them remain as 'hacked' blocks).

The main ones I'd suggest would be "(var) of [sprite v]", as well as "key (var) pressed". –Most of the others are probably not that worthwhile.

One issue with first of above (apart from a potential initial lack of realisation that the left item will refer to the value of var rather than the var itself – which I think is inherent in some other blocks anyway) is that it only allows access to the local vars of the original sprite, and not local vars for any of its clones. –Still think that's not a good enough reason to reject it, though.

The second one above does raise a number of implementation questions (how it behaves when var contains a multi-character string – including strings that actually correspond to menu entries, such as "left arrow", etc.) My suggestion would be that it should check for matching known strings first, and then, if there is no match, just take the first character (probably ignoring case).

I'd also consider allowing "when I receive (var)".
This does still seem to be relatively intuitive to me, as well as having a potential use-case that makes script a bit neater: scratchfoundation/scratch-flash#1162 (comment)


Finally, and for a bit of fun, I'll note that your "Gallery of the Bizarre" missed a case that does actually have a (vague) use-case (if you squint a bit).
See here for some fun with a hacked-block method to perform a sequence of block operations and then actually return a value, all 'inline' (so it's a bit like a 'custom script' with return value): https://scratch.mit.edu/discuss/post/1979829/ :)

@AmazingMech2418
Copy link
Contributor

A lot of these problems could be fixed with extensions too, but the problem is you can't load experimental extensions without forking the gui and using command line tools not everyone has to get GH pages to build.

@Mr-Dave2
Copy link

Mr-Dave2 commented Apr 8, 2018

I wonder if Thisandagain could give us a little clarification. It sounded to me like he was asking about the future of the current set of projects that use hacked blocks. Unless he directs his army of programmers to provide support for the hacked blocks now used in these existing projects, they will stop working after the transition to Scratch 3.0. I thought he was asking if there was a category of hacked blocks that developer time should be spent on to ensure that the most popular of these exiting projects will still work in the future.

I suppose that the other way is to just tell the community that only projects that were 100% coded in a Scratch editor will be supported in the next release and that going forward the large army of developers will attempt to implement the best of the hacked-block-features as official Scratch features.

@thisandagain
Copy link
Contributor Author

thisandagain commented Apr 8, 2018

@Mr-Dave2 I certainly wouldn't describe the Scratch Team as an "army of programmers" ... perhaps a "merry band of programmers"? Point is our team is quite small given the size of product we support (each engineer on the Scratch Team supports ~25 million kids each year). While the most common use case for argument hacking is scheduled to be resolved (the "when key pressed" hat block and "key pressed" boolean reporter) many others are not.

I do not believe it is reasonable to expect the Scratch Team to support all forms of hacked blocks. Those projects which are not supported may not work in Scratch 3.0 and I believe that is a reasonable expectation for projects that were created outside of the Scratch editor. To your point I do think we'll need to communicate this clearly to the community as we get closer to launch.

That said, I understand that some of these use cases matter deeply to the community (and for the record I think many of them are really neat!). For many of those – as discussed by others in this thread – I'd be more than happy to discuss proposals for how to resolve them and review pull requests which extend support. I hope that helps clarify. 😄

@mrjacobbloom
Copy link

While we're on the topic of of "variable variables," I'd like to bring up @towerofnix's idea for a "myself" option on the right side of the [property v] of [sprite v] block. If (variable) of [myself v] was officially supported down the line, that'd make this kind of "dynamic getter" a little more readable and generalizable.

That said, if you guys pursued this as the official way to do dynamic getters, it feels weird to have them in a different category than the rest of the data blocks. You could add a mostly-redundant get [variable v] block to data, but that feels like a waste and potentially confusing.

I agree with @djsrv that it'd be better to just have a dictionaries extension. Would it be possible to automatically import projects that use this hacked block to use a dictionary (for all local variables?) instead of the hacked sensing block? That'd certainly be more complicated than what 3.0 does with pen since one instance of the hacked block could affect (all?) previously-loaded getters and setters.

@TheLogFather
Copy link

TheLogFather commented Apr 9, 2018

@mrjacobbloom: Yes, I'd forgotten about "(var) of [myself v]" – allows a clone to reference its vars.

The other really useful one that I forgot about is referencing a list's name through a variable (so dropping a var into a dropdown of list names).

E.g: "item [1 v] of (var)"

I think that doesn't have the same potential for confusion as compared to "set (var) to [value]" (which is certainly very useful, but may well be too easily misunderstood by inexperienced Scratchers?)

@ZenithRogue
Copy link

Like @TheLogFather was saying, "item [1 v] of (var)" is extraordinarily useful. I often use it when I write list-based map rendering systems. I also have used it in conjunction with a pen based text system (it also used hacked custom blocks) to select fonts.

@AmazingMech2418
Copy link
Contributor

A few suggestions: Operators to convert types (stack - reporter, reporter - boolean, boolean - number reporter, boolean - string reporter, text reporter - string reporter, string reporter - stack, etc.), make all menus droppable, and reporters with stacks in them. Then, block "hacking" wouldn't be needed.

@AmazingMech2418
Copy link
Contributor

I'm working on an extension for conversions right now.

@mrjacobbloom
Copy link

Operators to convert types

I like the idea, and it'd definitely work, but I'd prefer a solution where Scratch was less restrictive in the first place (or at least could handle most cases of JSON hacking as-is and in sb3) instead of adding extra features to circumvent restrictions that are in there on purpose. Idk

Another concern: it'd need text, because <[]> isn't that readable or intuitive. I think I'm against label-less reporters as a paradigm -- the function of "rings" in Snap! isn't super obvious on first glance, and the meaning of variable blocks being droppable also isn't obvious:
droppable variable
-- not to mention that with reporters inside them they'd be a hecka pain to try to drag with a cursor, let alone a finger

@CatsAreFluffy
Copy link

Don't forget about <key (item (var) of [list]) pressed?>. With the <key (var) pressed?> block that would require command blocks to workaround.

@AmazingMech2418
Copy link
Contributor

Is there a way to get the JS code from a stack block. Also, can there be a new stack block input option?

@towerofnix
Copy link
Contributor

towerofnix commented Jun 9, 2018

I'd have a go at this, but I don't really know where to start - if I'm not mistaken, dropdown inputs that don't normally accept blocks fundamentally cannot accept blocks (i.e. they contain no slot for a block to exist in), and I'm not sure how to work around that. (Contrast this to Scratch 2.0, where the only difference between a droppable and not-droppable input is a simple flag!)

We are in the middle of migrating all blocks to be "extensions" this month and I think that may help provide a more simple / flexible entry point. Stay tuned, I think some of this may become easier to approach soon.

@thisandagain Is it still planned for the remaining 2.0 categories - events, control, sensing, operators, etc - to be made into (loaded-by-default) extensions? I've noticed that absolutely no current extensions (out of music, pen, Google translate, and video motion) have any dropdown inputs that don't accept blocks.

(cleared the rest of this post that's not relevant)

@mrjacobbloom
Copy link

Per #709, extensions can only make droppable menus right now

@AmazingMech2418
Copy link
Contributor

If all menus were droppable, most hacked blocks wouldn't be needed. Also, if a stack input option was allowed for extensions, many more would also not need hacked blocks.

@joker314
Copy link
Contributor

joker314 commented Oct 13, 2018

Scratch 3.0 has heavy validation on its JSON format. However, if we don't allow 'hacked' Scratch 3.0 files, we make it hard for users to remix projects in the Scratch 3.0 editor, if the projects they are remixing are using hacked blocks.

Should Scratch 3.0 validation be relaxed to match Scratch 2.0?


I propose an additional mode, differing from the regular one, where reporters can be dragged into any slot, regardless of shape (a bit like Snap!'s behaviour, where the slot shapes are guides rather than restrictions). This mode would be automatically enabled (with a notice provided to the user to explain what the mode does and the risks associated with it), when one attempts to enter the editor of a 'hacked' project; but it could also be enabled manually somehow. (Name of mode; text to use for mode; or how to access it manually--up for discussion too).

This would also resolve the issue of validation: it could be very very relaxed, and we'd just need to show the notice.

What are the thoughts on such a mode?

@apple502j
Copy link
Contributor

I am working on the "Overriding Custom Procedure Menu Options" one. Hopefully some fixes on sb2.js seems working.

@apple502j
Copy link
Contributor

This is still wip, but:
https://github.com/apple502j/scratch-vm/tree/hacked-semi

@Alzter
Copy link

Alzter commented Jan 2, 2019

I took a glance at the "Gallery of the bizzare" section of the hacked blocks powerpoint and I think that these ideas uncover a goldmine of creative potential. Imagine if some stack blocks could be placed into string, number or even boolean inputs and would "ringify"! It's a bit complex, so I made some mockups below.

20190102_193758
20190102_193324

I also had an idea for an if else reporter that can evaluate a test and have given results for if it returns true or false.

20190102_193034
20190102_193108

@joker314
Copy link
Contributor

joker314 commented Jan 2, 2019

Hi @Alzter. Thanks for these suggestions. I think I understand the use case of the conditional operator you describe (I assume it's meant to be a reporter shape?), and it'd be a really cool addition... though I think Python's word order seems more intuitive:

trueValue if true else falseValue

I think it deserves some more discussion in its own issue, as it isn't directly related to hacked blocks.

As for your first suggestion, I don't really understand the use case. What would picking a random number between the outputs of two say blocks mean?

I find the idea of dragging a hat block into a wait until block super cool... but it does make it a lot harder to discover. Some Scratchers learn by copying the projects of others. It's not massively obvious how to roundify a block, or even to know that roundification has occurred, without being told about it. This could easily lead to confusion as users scour the pallete for predicates when they should be looking for a hat block.

@griffpatch
Copy link
Contributor

The new "item # of list" goes some way to removing the need for a few hacked blocks (thank you for that!), but it still remains a real pain not to be able to detect case of letters (as item # of list has no distinction between a & A). Even just a block for "Is uppercase (var)?" would be excellent :)

@mrjacobbloom
Copy link

There's some discussion of case detection blocks in #536

@ghost
Copy link

ghost commented Jan 25, 2019

Ok. I'm @Helixable from Scratch. I left because 3.0 broke every one of my projects execept 2. One huge issue was key detection. The enter, tab, shift, and backspace key detection dont work anymore. Anybody know some somple workarounds? or somwthing?

@towerofnix
Copy link
Contributor

@Helixable that's the "overriding menu options" example here (aka it doesn't work in 3.0, yeah). I'm not sure anybody's figured out a workaround. I made #1892 discussing some more keys that would be useful; if you want to discuss more keys that would be handy, you should comment there.

@griffpatch
Copy link
Contributor

griffpatch commented Jan 25, 2019 via email

@kchadha
Copy link
Contributor

kchadha commented Jan 26, 2019

@griffpatch, thanks for pointing to that project and reporting this bug. I believe that most instances of "blocks missing" are caused by #1077 (and some of the related issues linked to it). We are actively working to fix that issue.

With the projects affected by #1077, the blocks aren't actually gone, they just aren't getting displayed properly, which means that these project should hopefully recover when the bug is fixed.

While I haven't confirmed if the project you linked is affected by that bug, I was able to confirm that the sprites that look like they're missing scripts (e.g. 'game') do actually have blocks in the saved json.

I hope this helps! Please let me know if you have any questions!

@kchadha kchadha closed this as completed Jan 26, 2019
@kchadha kchadha reopened this Jan 26, 2019
@TheLogFather
Copy link

Since this is still open, maybe I should've put this 'hacked'-block load-failure comment/question here, rather than in that closed issue? (Even though it looks like a regression of that one)...
#1704 (comment)

Also, see comment/question that follows the one above (about another case with invisible script)...
#1704 (comment)

@traincrisis
Copy link

I took a glance at the "Gallery of the bizzare" section of the hacked blocks powerpoint and I think that these ideas uncover a goldmine of creative potential. Imagine if some stack blocks could be placed into string, number or even boolean inputs and would "ringify"! It's a bit complex, so I made some mockups below.

20190102_193758 20190102_193324

I also had an idea for an if else reporter that can evaluate a test and have given results for if it returns true or false.

20190102_193034 20190102_193108

Receive not recieve

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests