From b6db1aa372ec382b928daec2950558903a16677a Mon Sep 17 00:00:00 2001 From: Hyper_ <40342021+NotHyper-474@users.noreply.github.com> Date: Tue, 30 Jun 2026 15:30:34 -0300 Subject: [PATCH 1/5] Good Coding Practices Guide --- .../Expert/-07.GoodCodingPractices.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 assets/content/cookbook/Expert/-07.GoodCodingPractices.md diff --git a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md new file mode 100644 index 00000000..b748e580 --- /dev/null +++ b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md @@ -0,0 +1,65 @@ +[tags]: / "expert,misc,hscript" + +# Good Coding Practices + +This article will go over practices that can be applied to your code, improving its quality. + +These are not mandatory, so it's up to the programmer whether to make use of them. + +# Be Fairly Local! + +A feature of many programming languages is local variables, which are variables that you define inside of functions. + +One advantage of using them is making the code cleaner, a topic we will address in this sub-article. Let's take this code snippet as an example of how local variables can be of use. + +```haxe +function foo() +{ + if (FlxG.state?.subState is FreeplayState) + { + if (FlxG.state.subState.ostName.length > 8) + { + FlxG.state.subState.ostName.size = 0.5; + } + } +} +``` + +At a first glance, we can see a lot of repetitive references to `FlxG.state.subState`. This doesn't hurt, but is not desirable. Now let's see the same snippet, but with a local variable being used instead. + +```haxe +function foo() +{ + var currentSubstate:FlxSubState = FlxG.state?.subState; + if (currentSubState is FreeplayState) + { + if (currentSubState.ostName.length > 8) + { + currentSubState.ostName.size = 0.5; + } + } +} +``` + +As it can be seen, we are now storing the result of `FlxG.state.subState` inside of a variable. You may notice we didn't do the same to `ostName`, since it's not really referenced a lot. In a real scenario, the current substate could be referenced much more depending on what the code needs, which is why we store it. + +This is actually more efficient too! For every instance of `FlxG.state.subState`, each field has to be obtained individually; a local variable essentially stores the result of that. + +Have in mind that storing a value (like a number or a text string) you got from an object in a variable, then assigning another value to it, will not affect the object. + +Below is an example of that. `titleText` is an `FlxText` whose `text` field contains the content. Modifying `text` will _not_ modify the contents of `titleText`. +```haxe +var text:String = FlxG.state.titleText.text; +text = 'My Awesome Mod'; +``` +# Explicit Types + +Unlike Haxe, in hscript there's usually no need to specify variables types, whether those are local variables, parameters, or even class-level fields, because as a scripting language it is dynamically typed. So they are simply ignored. + +However, it might be useful to do this if you decide to revisit your code later, as they can help you understand what the code is doing. + +A type is specified using the `:TypeName` syntax. For instance, a variable for a piece of text can be represented as `var text:String`. + +Since these are ignored, you can put pretty anything for the type name... except for `Map`, which does get interpreted, however it's a bit unreliable. + +> Author: [NotHyper-474](https://github.com/NotHyper-474) \ No newline at end of file From 28d0cfe0a52441858c1db2e3263939f3246abf4e Mon Sep 17 00:00:00 2001 From: Hyper_ <40342021+NotHyper-474@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:28:27 -0300 Subject: [PATCH 2/5] move some stuff around --- assets/content/cookbook/Expert/-07.GoodCodingPractices.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md index b748e580..51164edb 100644 --- a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md +++ b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md @@ -54,12 +54,10 @@ text = 'My Awesome Mod'; ``` # Explicit Types -Unlike Haxe, in hscript there's usually no need to specify variables types, whether those are local variables, parameters, or even class-level fields, because as a scripting language it is dynamically typed. So they are simply ignored. +Unlike Haxe, in hscript there's usually no need at all to specify variables types, whether those are local variables, parameters, or even class-level fields, because, as a scripting language, it is dynamically typed. So they are simply ignored, except for `Map<..., ...>`, which does get interpreted, however it's a bit unreliable. -However, it might be useful to do this if you decide to revisit your code later, as they can help you understand what the code is doing. +Nonetheless, it might be useful to do this if you decide to revisit your code later, as they can help you understand what the code is doing. -A type is specified using the `:TypeName` syntax. For instance, a variable for a piece of text can be represented as `var text:String`. - -Since these are ignored, you can put pretty anything for the type name... except for `Map`, which does get interpreted, however it's a bit unreliable. +A type is specified using the `:TypeName` syntax. For instance, a variable for a piece of text can be represented as `var text:String`. Since these are ignored in nearly all cases, you can put pretty much anything for the type name. > Author: [NotHyper-474](https://github.com/NotHyper-474) \ No newline at end of file From 5436693484968ddc3edb4c49256541b7be245832 Mon Sep 17 00:00:00 2001 From: Hyper_ <40342021+NotHyper-474@users.noreply.github.com> Date: Tue, 30 Jun 2026 23:15:23 -0300 Subject: [PATCH 3/5] unfinished stuff I'd rather continue tomorrow --- .../Expert/-07.GoodCodingPractices.md | 81 +++++++++++++++++-- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md index 51164edb..afd1a6d8 100644 --- a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md +++ b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md @@ -2,9 +2,7 @@ # Good Coding Practices -This article will go over practices that can be applied to your code, improving its quality. - -These are not mandatory, so it's up to the programmer whether to make use of them. +This article will go over practices that can be applied to your code, improving its quality. These are not mandatory, so it's up to you whether to make use of them. # Be Fairly Local! @@ -13,7 +11,7 @@ A feature of many programming languages is local variables, which are variables One advantage of using them is making the code cleaner, a topic we will address in this sub-article. Let's take this code snippet as an example of how local variables can be of use. ```haxe -function foo() +function foo():Void { if (FlxG.state?.subState is FreeplayState) { @@ -28,7 +26,7 @@ function foo() At a first glance, we can see a lot of repetitive references to `FlxG.state.subState`. This doesn't hurt, but is not desirable. Now let's see the same snippet, but with a local variable being used instead. ```haxe -function foo() +function foo():Void { var currentSubstate:FlxSubState = FlxG.state?.subState; if (currentSubState is FreeplayState) @@ -48,6 +46,7 @@ This is actually more efficient too! For every instance of `FlxG.state.subState` Have in mind that storing a value (like a number or a text string) you got from an object in a variable, then assigning another value to it, will not affect the object. Below is an example of that. `titleText` is an `FlxText` whose `text` field contains the content. Modifying `text` will _not_ modify the contents of `titleText`. + ```haxe var text:String = FlxG.state.titleText.text; text = 'My Awesome Mod'; @@ -60,4 +59,76 @@ Nonetheless, it might be useful to do this if you decide to revisit your code la A type is specified using the `:TypeName` syntax. For instance, a variable for a piece of text can be represented as `var text:String`. Since these are ignored in nearly all cases, you can put pretty much anything for the type name. +## Function Return Types + +Functions can also have **return types**, and the syntax is pretty much identical to variables. +```haxe +override function getPipis():Array +{ + if (scene == null) + { + return super.getPipis(); + } + return scene.pipisList; +} + +function spareEnemy(?enemy:Enemy):Void +{ + if (enemy == null) + { + enemy = scene.enemies[0] ?? return; + } + + enemy.performSpareAnimation(); + scene.remove(enemy); + // ... +} +``` + +Just like with variables, these types don't actually do anything, but they make it clearer what each function may do and whether to expect them to return something. + +# Formatting Rules + +Formatting rules are a set of standardized guidelines for structuring code. In this article, we'll go over two common styles for styling your code. + +## Allman Style + +```haxe +function foo(params:FooParams):Void +{ + if (condition) + { + // Pretend this does something. + } + else + { + // Ditto. + } + + var validatedParams:FooParams = { + bar: params.bar ?? new Bar() + // ... + }; +} +``` + +## K&R Style + +```haxe +function foo(params:FooParams):Void { + if (condition) { + // Pretend this does something. + } else { + // Ditto. + } + + var validatedParams:FooParams = { + bar: params.bar ?? new Bar() + // ... + }; +} +``` + + + > Author: [NotHyper-474](https://github.com/NotHyper-474) \ No newline at end of file From b6b5e9cf93be3bd8542feca4242762ec542ebd25 Mon Sep 17 00:00:00 2001 From: Hyper_ <40342021+NotHyper-474@users.noreply.github.com> Date: Mon, 27 Jul 2026 22:11:24 -0300 Subject: [PATCH 4/5] I am back with not much to write --- .../Expert/-07.GoodCodingPractices.md | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md index afd1a6d8..081ebbbb 100644 --- a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md +++ b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md @@ -53,17 +53,17 @@ text = 'My Awesome Mod'; ``` # Explicit Types -Unlike Haxe, in hscript there's usually no need at all to specify variables types, whether those are local variables, parameters, or even class-level fields, because, as a scripting language, it is dynamically typed. So they are simply ignored, except for `Map<..., ...>`, which does get interpreted, however it's a bit unreliable. +Unlike Haxe, in HScript there's usually no need at all to specify variables types, whether those are local variables, parameters, or even class-level fields, because, as a scripting language, it is dynamically typed. So they are simply ignored, except for `Map<..., ...>`, which does get interpreted, however it's a bit unreliable. Nonetheless, it might be useful to do this if you decide to revisit your code later, as they can help you understand what the code is doing. A type is specified using the `:TypeName` syntax. For instance, a variable for a piece of text can be represented as `var text:String`. Since these are ignored in nearly all cases, you can put pretty much anything for the type name. -## Function Return Types +## Explicit Function Return Types Functions can also have **return types**, and the syntax is pretty much identical to variables. ```haxe -override function getPipis():Array +override function getPipis():Array // Array is the return type. { if (scene == null) { @@ -87,9 +87,25 @@ function spareEnemy(?enemy:Enemy):Void Just like with variables, these types don't actually do anything, but they make it clearer what each function may do and whether to expect them to return something. +# Explicit Access Modifiers + +Haxe provides a set of access modifiers you can apply to class fields, and so does HScript. However, at the time of writing, only `static` will actually be interpreted, making the field part of the class and not of an instance of it. + +Even so, it is a good practice to use them whenever applicable, and this sub-article will go over this regarding the `override`, `public` and `private` modifiers. + +## Override + +This access modifier is only allowed on non-static functions for methods that also exist in the parent class. As the name suggests, it signifies the field of same name in the parent class had its implementation replaced by this class. + +## Public and Private (Visibility Modifiers) + +These access modifiers are allowed for any class field, whether static or not. The `public` modifier is used to denote that the field can be freely accessed by another class, whereas `private` fields can only be accessed by the class defining them and by its sub-classes. + +This currently has no effect in HScript, since fields are public by default, even for non-scripted classes due to how Reflection works. + # Formatting Rules -Formatting rules are a set of standardized guidelines for structuring code. In this article, we'll go over two common styles for styling your code. +Formatting rules are a set of standardized guidelines for structuring code. In this sub-article, we'll go over two common styles for styling your code. ## Allman Style From cfa7121aa1ddede0d786d76f811cd595a64b9f04 Mon Sep 17 00:00:00 2001 From: Hyper_ <40342021+NotHyper-474@users.noreply.github.com> Date: Tue, 28 Jul 2026 17:10:01 -0300 Subject: [PATCH 5/5] I'm not in the right state of mind to continue this --- .../cookbook/Expert/-07.GoodCodingPractices.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md index 081ebbbb..89bd807d 100644 --- a/assets/content/cookbook/Expert/-07.GoodCodingPractices.md +++ b/assets/content/cookbook/Expert/-07.GoodCodingPractices.md @@ -99,13 +99,23 @@ This access modifier is only allowed on non-static functions for methods that al ## Public and Private (Visibility Modifiers) -These access modifiers are allowed for any class field, whether static or not. The `public` modifier is used to denote that the field can be freely accessed by another class, whereas `private` fields can only be accessed by the class defining them and by its sub-classes. +These access modifiers are allowed for any class field, whether static or not. -This currently has no effect in HScript, since fields are public by default, even for non-scripted classes due to how Reflection works. +The `public` modifier is used to denote that the field can be freely accessed by another class, whereas `private` fields can only be accessed by the class defining them and by its sub-classes. When no modifier is specified, the field is implicitly `private`; due to this, the checkstyle used by Friday Night Funkin's source code considers the use of `private` to be redundant. + +This currently has no effect in HScript, and fields are public by default, even for non-scripted classes due to how Reflection works. # Formatting Rules -Formatting rules are a set of standardized guidelines for structuring code. In this sub-article, we'll go over two common styles for styling your code. +Formatting rules are a set of standardized guidelines for structuring code, making it easier to read. The key rules include indentation, line length limits and spacing. + +For reference, some of the Friday Night Funkin' source code's formatting rules consist of: + +* Indentation using 2-character-wide spaces. +* Maximum line length of 160 characters. +* One line of space between functions and variables. + +A JSON file can be used to ensure the formatting is applied to files automatically, and can be used with an [online tool](https://abnormalpoof.github.io/haxe-web-formatter/). Other types of checkstyle files can be checked out [here](https://haxecheckstyle.github.io/haxe-formatter-docs/#codesamples.CommonSamples.allman_curlies). ## Allman Style