From 697c75193afe212a6daa2114930ea4707d2c8db3 Mon Sep 17 00:00:00 2001 From: Homura Date: Wed, 25 Mar 2026 01:57:54 +0300 Subject: [PATCH 01/24] start --- source/engine/backend/BaseStage.hx | 1 + source/engine/backend/ClientPrefs.hx | 4 +- source/engine/backend/Conductor.hx | 25 ++- source/engine/backend/Controls.hx | 48 ++++-- source/engine/backend/CoolUtil.hx | 46 ++--- source/engine/backend/CrashHandler.hx | 1 + source/engine/backend/CustomFadeTransition.hx | 7 +- source/engine/backend/Difficulty.hx | 8 +- source/engine/backend/Discord.hx | 27 +-- source/engine/backend/EaseUtil.hx | 1 + source/engine/backend/FunkinPreloader.hx | 1 + source/engine/backend/Highscore.hx | 20 ++- source/engine/backend/IMusicState.hx | 9 +- source/engine/backend/InputFormatter.hx | 1 + source/engine/backend/Main.hx | 7 +- source/engine/backend/Mods.hx | 3 +- source/engine/backend/MusicBeatState.hx | 40 +++-- source/engine/backend/MusicBeatSubstate.hx | 40 +++-- source/engine/backend/Native.hx | 1 + source/engine/backend/NoteTypesConfig.hx | 13 +- source/engine/backend/Paths.hx | 158 +++++++++++++----- source/engine/backend/Rating.hx | 1 + source/engine/backend/Section.hx | 1 + source/engine/backend/Song.hx | 31 ++-- source/engine/backend/StageData.hx | 29 +++- source/engine/backend/WeekData.hx | 39 ++--- source/engine/backend/io/FileSystem.hx | 1 + .../engine/backend/rendering/PsychCamera.hx | 8 +- .../engine/backend/rendering/ShadowCamera.hx | 30 ++-- source/engine/objects/Alphabet.hx | 5 +- source/engine/objects/Ana.hx | 1 + source/engine/objects/AttachedSprite.hx | 36 ++-- source/engine/objects/AttachedText.hx | 22 ++- source/engine/objects/BGSprite.hx | 38 +++-- source/engine/objects/Bar.hx | 129 +++++++------- source/engine/objects/Character.hx | 47 ++++-- source/engine/objects/CheckboxThingie.hx | 24 ++- source/engine/objects/CustomSoundTray.hx | 83 +++++---- source/engine/objects/HealthIcon.hx | 60 ++++--- source/engine/objects/MenuCharacter.hx | 60 ++++--- source/engine/objects/MenuItem.hx | 7 +- source/engine/objects/MusicPlayer.hx | 3 +- source/engine/objects/Note.hx | 87 ++++++---- source/engine/objects/NoteSplash.hx | 85 ++++++---- source/engine/objects/OpenFLSprite.hx | 17 +- source/engine/objects/StrumNote.hx | 45 +++-- source/engine/objects/SustainSplash.hx | 72 +++++--- source/engine/objects/TypedAlphabet.hx | 15 +- source/engine/objects/VideoSprite.hx | 74 +++++--- source/engine/options/Option.hx | 69 ++++---- source/engine/psychlua/Convert.hx | 1 + source/engine/psychlua/ReflectionFunctions.hx | 18 +- source/engine/psychlua/ShaderFunctions.hx | 85 +++++----- source/engine/psychlua/TextFunctions.hx | 46 ++--- source/engine/shaders/AdjustColorShader.hx | 9 +- source/engine/shaders/BlendModeEffect.hx | 1 + source/engine/shaders/ColorSwap.hx | 1 + source/engine/shaders/PixelSplashShader.hx | 1 + source/engine/shaders/RGBPalette.hx | 9 +- .../shaders/RuntimeCustomBlendShader.hx | 6 +- source/engine/shaders/WiggleEffect.hx | 1 + .../haxe/format/JsonParser.hx | 4 +- 62 files changed, 1095 insertions(+), 667 deletions(-) diff --git a/source/engine/backend/BaseStage.hx b/source/engine/backend/BaseStage.hx index 7d9b667a..463c696b 100644 --- a/source/engine/backend/BaseStage.hx +++ b/source/engine/backend/BaseStage.hx @@ -14,6 +14,7 @@ enum Countdown START; } +@:nullSafety class BaseStage extends FlxBasic { private var game(get, never):Dynamic; diff --git a/source/engine/backend/ClientPrefs.hx b/source/engine/backend/ClientPrefs.hx index b34ad042..979dbe1f 100644 --- a/source/engine/backend/ClientPrefs.hx +++ b/source/engine/backend/ClientPrefs.hx @@ -6,7 +6,9 @@ import flixel.input.gamepad.FlxGamepadInputID; import states.TitleState; // Add a variable here and it will get automatically saved -@:structInit class SaveVariables +@:structInit +@:nullSafety +class SaveVariables { // Mobile and Mobile Controls Releated public var extraButtons:String = "NONE"; // mobile extra button option diff --git a/source/engine/backend/Conductor.hx b/source/engine/backend/Conductor.hx index dace4c25..c8639a31 100644 --- a/source/engine/backend/Conductor.hx +++ b/source/engine/backend/Conductor.hx @@ -12,6 +12,7 @@ typedef BPMChangeEvent = @:optional var stepCrochet:Float; } +@:nullSafety class Conductor { public static var bpm(default, set):Float = 100; @@ -25,10 +26,12 @@ class Conductor public static var bpmChangeMap:Array = []; - public static function getCrotchetAtTime(time:Float) + public static function getCrotchetAtTime(time:Float):Float { var lastChange = getBPMFromSeconds(time); - return lastChange.stepCrochet * 4; + var sc = lastChange.stepCrochet; + if (sc == null) sc = stepCrochet; + return sc * 4; } public static function getBPMFromSeconds(time:Float) @@ -69,19 +72,25 @@ class Conductor { var step = beat * 4; var lastChange = getBPMFromStep(step); - return lastChange.songTime + (step - lastChange.stepTime) * (lastChange.stepCrochet / 1000); + var sc = lastChange.stepCrochet; + if (sc == null) sc = stepCrochet; + return lastChange.songTime + (step - lastChange.stepTime) * (sc / 1000); } - public static function getStep(time:Float) + public static function getStep(time:Float):Float { var lastChange = getBPMFromSeconds(time); - return lastChange.stepTime + (time - lastChange.songTime) / lastChange.stepCrochet; + var sc = lastChange.stepCrochet; + if (sc == null) sc = stepCrochet; + return lastChange.stepTime + (time - lastChange.songTime) / sc; } - public static function getStepRounded(time:Float) + public static function getStepRounded(time:Float):Float { var lastChange = getBPMFromSeconds(time); - return lastChange.stepTime + Math.floor(time - lastChange.songTime) / lastChange.stepCrochet; + var sc = lastChange.stepCrochet; + if (sc == null) sc = stepCrochet; + return lastChange.stepTime + Math.floor(time - lastChange.songTime) / sc; } public static function getBeat(time:Float) @@ -122,7 +131,7 @@ class Conductor //trace("new BPM map BUDDY " + bpmChangeMap); } - static function getSectionBeats(song:SwagSong, section:Int) + static function getSectionBeats(song:SwagSong, section:Int):Float { var val:Null = null; if (song.notes[section] != null) diff --git a/source/engine/backend/Controls.hx b/source/engine/backend/Controls.hx index 5d681958..37717222 100644 --- a/source/engine/backend/Controls.hx +++ b/source/engine/backend/Controls.hx @@ -5,6 +5,7 @@ import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.mappings.FlxGamepadMapping; import flixel.input.keyboard.FlxKey; +@:nullSafety class Controls { // Keeping same use cases on stuff for it to be easier to understand/use @@ -143,36 +144,57 @@ class Controls public function justPressed(key:String) { - var result:Bool = (FlxG.keys.anyJustPressed(keyboardBinds[key]) == true); - if (result) + var keyboardResult:Bool = false; + var kbBind:Null> = keyboardBinds[key]; + if (kbBind != null) + keyboardResult = FlxG.keys.anyJustPressed(kbBind) == true; + if (keyboardResult) controllerMode = false; - return result - || _myGamepadJustPressed(gamepadBinds[key]) == true + var gpResult:Bool = false; + var gpBind:Null> = gamepadBinds[key]; + if (gpBind != null) + gpResult = _myGamepadJustPressed(gpBind) == true; + + return keyboardResult || gpResult #if FEATURE_MOBILE_CONTROLS || mobileCJustPressed(mobileBinds[key]) == true || touchPadJustPressed(mobileBinds[key]) == true #end; } public function pressed(key:String) { - var result:Bool = (FlxG.keys.anyPressed(keyboardBinds[key]) == true); - if (result) + var keyboardResult:Bool = false; + var kbBind:Null> = keyboardBinds[key]; + if (kbBind != null) + keyboardResult = FlxG.keys.anyPressed(kbBind) == true; + if (keyboardResult) controllerMode = false; - return result - || _myGamepadPressed(gamepadBinds[key]) == true + var gpResult:Bool = false; + var gpBind:Null> = gamepadBinds[key]; + if (gpBind != null) + gpResult = _myGamepadPressed(gpBind) == true; + + return keyboardResult || gpResult #if FEATURE_MOBILE_CONTROLS || mobileCPressed(mobileBinds[key]) == true || touchPadPressed(mobileBinds[key]) == true #end; } public function justReleased(key:String) { - var result:Bool = (FlxG.keys.anyJustReleased(keyboardBinds[key]) == true); - if (result) + var keyboardResult:Bool = false; + var kbBind:Null> = keyboardBinds[key]; + if (kbBind != null) + keyboardResult = FlxG.keys.anyJustReleased(kbBind) == true; + if (keyboardResult) controllerMode = false; - return result - || _myGamepadJustReleased(gamepadBinds[key]) == true + var gpResult:Bool = false; + var gpBind:Null> = gamepadBinds[key]; + if (gpBind != null) + gpResult = _myGamepadJustReleased(gpBind) == true; + + return keyboardResult || gpResult #if FEATURE_MOBILE_CONTROLS || mobileCJustReleased(mobileBinds[key]) == true || touchPadJustReleased(mobileBinds[key]) == true #end; } @@ -316,7 +338,7 @@ class Controls #end // IGNORE THESE - public static var instance:Controls; + public static var instance:Null = null; public function new() { diff --git a/source/engine/backend/CoolUtil.hx b/source/engine/backend/CoolUtil.hx index 0c1483c2..41d25e31 100644 --- a/source/engine/backend/CoolUtil.hx +++ b/source/engine/backend/CoolUtil.hx @@ -6,6 +6,7 @@ import openfl.utils.Assets; import sys.io.Process; #end +@:nullSafety class CoolUtil { public static function quantize(f:Float, snap:Float) @@ -21,7 +22,7 @@ class CoolUtil public static function coolTextFile(path:String):Array { - var daList:String = null; + var daList:Null = null; var formatted:Array = path.split(':'); // prevent "shared:", "preload:" and other library names on file path path = formatted[formatted.length - 1]; if (FileSystem.exists(path)) @@ -80,21 +81,25 @@ class CoolUtil if (colorOfThisPixel != 0) { if (countByColor.exists(colorOfThisPixel)) - countByColor[colorOfThisPixel] = countByColor[colorOfThisPixel] + 1; + { + var currentCount:Null = countByColor[colorOfThisPixel]; + countByColor[colorOfThisPixel] = (currentCount == null) ? 1 : currentCount + 1; + } else if (countByColor[colorOfThisPixel] != 13520687 - (2 * 13520687)) countByColor[colorOfThisPixel] = 1; } } } - var maxCount = 0; + var maxCount:Int = 0; var maxKey:Int = 0; // after the loop this will store the max color countByColor[FlxColor.BLACK] = 0; for (key in countByColor.keys()) { - if (countByColor[key] >= maxCount) + var count = countByColor[key]; + if (count != null && count >= maxCount) { - maxCount = countByColor[key]; + maxCount = count; maxKey = key; } } @@ -102,10 +107,11 @@ class CoolUtil return maxKey; } - public static function numberArray(max:Int, ?min = 0):Array + public static function numberArray(max:Int, ?min:Int = 0):Array { var dumbArray:Array = []; - for (i in min...max) + var minVal:Int = (min == null) ? 0 : min; + for (i in minVal...max) dumbArray.push(i); return dumbArray; @@ -154,22 +160,22 @@ class CoolUtil @:access(flixel.util.FlxSave.validate) public static function getSavePath():String { - final company:String = FlxG.stage.application.meta.get('company'); + final company:Null = FlxG.stage.application.meta.get('company'); + final companyVal:String = (company != null) ? company : ''; // #if (flixel < "5.0.0") return company; #else - return '${company}/${flixel.util.FlxSave.validate(FlxG.stage.application.meta.get('file'))}'; + final fileVal:Null = FlxG.stage.application.meta.get('file'); + return '$companyVal/${flixel.util.FlxSave.validate((fileVal != null) ? fileVal : '')}'; // #end } public static function loadSong(?name:String = null, ?difficultyNum:Int = -1) { - if (name == null || name.length < 1) - name = PlayState.SONG.song; - if (difficultyNum == -1) - difficultyNum = PlayState.storyDifficulty; - - var poop:String = Highscore.formatSong(name, difficultyNum); - PlayState.SONG = Song.loadFromJson(poop, name); - PlayState.storyDifficulty = difficultyNum; + var finalName:String = (name == null || name.length < 1) ? PlayState.SONG.song : name; + var finalDiff:Int = (difficultyNum == null || difficultyNum == -1) ? PlayState.storyDifficulty : difficultyNum; + + var poop:String = Highscore.formatSong(finalName, finalDiff); + PlayState.SONG = Song.loadFromJson(poop, finalName); + PlayState.storyDifficulty = finalDiff; LoadingState.prepareToSong(); LoadingState.loadAndSwitchState(new PlayState()); @@ -258,7 +264,8 @@ class CoolUtil return 0.0; if (x >= 1.0) return 1.0; - return (1 + c) * x * x * x - c * x * x; + var cVal:Float = (c == null) ? 1.70158 : c; + return (1 + cVal) * x * x * x - cVal * x * x; } public static function easeOutBack(x:Float, ?c:Float = 1.70158):Float @@ -267,7 +274,8 @@ class CoolUtil return 0.0; if (x >= 1.0) return 1.0; - return 1 + (c + 1) * Math.pow(x - 1, 3) + c * Math.pow(x - 1, 2); + var cVal:Float = (c == null) ? 1.70158 : c; + return 1 + (cVal + 1) * Math.pow(x - 1, 3) + cVal * Math.pow(x - 1, 2); } public static function priorityBool(a:Bool, ?b:Null):Bool diff --git a/source/engine/backend/CrashHandler.hx b/source/engine/backend/CrashHandler.hx index cd846150..f7613686 100644 --- a/source/engine/backend/CrashHandler.hx +++ b/source/engine/backend/CrashHandler.hx @@ -11,6 +11,7 @@ using flixel.util.FlxArrayUtil; * Crash Handler. * @author MAJigsaw77 and Homura Akemi (HomuHomu833) */ +@:nullSafety class CrashHandler { public static function init():Void diff --git a/source/engine/backend/CustomFadeTransition.hx b/source/engine/backend/CustomFadeTransition.hx index 565b602b..d59a1d49 100644 --- a/source/engine/backend/CustomFadeTransition.hx +++ b/source/engine/backend/CustomFadeTransition.hx @@ -2,13 +2,14 @@ package backend; import flixel.util.FlxGradient; +@:nullSafety class CustomFadeTransition extends MusicBeatSubstate { - public static var finishCallback:Void->Void; + public static var finishCallback:NullVoid> = null; var isTransIn:Bool = false; - var transBlack:FlxSprite; - var transGradient:FlxSprite; + var transBlack:FlxSprite = new FlxSprite(); + var transGradient:FlxSprite = new FlxSprite(); var duration:Float; diff --git a/source/engine/backend/Difficulty.hx b/source/engine/backend/Difficulty.hx index 5d4f003a..7253c087 100644 --- a/source/engine/backend/Difficulty.hx +++ b/source/engine/backend/Difficulty.hx @@ -1,5 +1,6 @@ package backend; +@:nullSafety class Difficulty { public static var defaultList(default, never):Array = ['Easy', 'Normal', 'Hard']; @@ -28,7 +29,7 @@ class Difficulty if (week == null) week = WeekData.getCurrentWeek(); - var diffStr:String = week.difficulties; + var diffStr:Null = (week != null) ? week.difficulties : null; if (diffStr != null && diffStr.length > 0) { var diffs:Array = diffStr.trim().split(','); @@ -70,12 +71,13 @@ class Difficulty { final idx:Int = num ?? PlayState.storyDifficulty; final raw:String = list[idx]; - final dash:String = includeDash ? "-" : ""; + final includeVal:Bool = (includeDash == null) ? true : includeDash; + final dash:String = includeVal ? "-" : ""; if (raw.toLowerCase() == "erect" || raw.toLowerCase() == "nightmare") return dash + "Erect"; - return includeDash ? "" : null; + return includeVal ? "" : null; } inline public static function getDefault():String diff --git a/source/engine/backend/Discord.hx b/source/engine/backend/Discord.hx index 5c846559..22df10bc 100644 --- a/source/engine/backend/Discord.hx +++ b/source/engine/backend/Discord.hx @@ -6,6 +6,7 @@ import lime.app.Application; import hxdiscord_rpc.Discord; import hxdiscord_rpc.Types; +@:nullSafety class DiscordClient { public static var isInitialized:Bool = false; @@ -42,11 +43,13 @@ class DiscordClient private static function onReady(request:cpp.RawConstPointer):Void { var requestPtr:cpp.Star = cpp.ConstPointer.fromRaw(request).ptr; + var username:String = (requestPtr != null && requestPtr.username != null) ? requestPtr.username : ''; + var discriminator:String = (requestPtr != null && requestPtr.discriminator != null) ? requestPtr.discriminator : '0'; - if (Std.parseInt(cast(requestPtr.discriminator, String)) != 0) // New Discord IDs/Discriminator system - trace('(Discord) Connected to User (${cast (requestPtr.username, String)}#${cast (requestPtr.discriminator, String)})'); + if (Std.parseInt(discriminator) != 0) // New Discord IDs/Discriminator system + trace('(Discord) Connected to User ($username#$discriminator)'); else // Old discriminators - trace('(Discord) Connected to User (${cast (requestPtr.username, String)})'); + trace('(Discord) Connected to User ($username)'); changePresence(); } @@ -67,7 +70,7 @@ class DiscordClient discordHandlers.ready = cpp.Function.fromStaticFunction(onReady); discordHandlers.disconnected = cpp.Function.fromStaticFunction(onDisconnected); discordHandlers.errored = cpp.Function.fromStaticFunction(onError); - Discord.Initialize(clientID, cpp.RawPointer.addressOf(discordHandlers), #if (hxdiscord_rpc > "1.2.4") false #else 1 #end, null); + Discord.Initialize(clientID, cpp.RawPointer.addressOf(discordHandlers), #if (hxdiscord_rpc > "1.2.4") false #else 1 #end, ""); if (!isInitialized) trace("(Discord) Client initialized"); @@ -93,19 +96,21 @@ class DiscordClient ?endTimestamp:Float) { var startTimestamp:Float = 0; - if (hasStartTimestamp) + var hasTimestamp:Bool = (hasStartTimestamp == true); + var endTime:Float = (endTimestamp == null) ? 0 : endTimestamp; + if (hasTimestamp) startTimestamp = Date.now().getTime(); - if (endTimestamp > 0) - endTimestamp = startTimestamp + endTimestamp; + if (endTime > 0) + endTime = startTimestamp + endTime; - presence.details = details; - presence.state = state; + presence.details = (details != null) ? details : 'In the Menus'; + presence.state = (state != null) ? state : ''; presence.largeImageKey = 'icon'; presence.largeImageText = "Version: " + states.MainMenuState.shadowEngineVersion; - presence.smallImageKey = smallImageKey; + presence.smallImageKey = (smallImageKey != null) ? smallImageKey : ''; // Obtained times are in milliseconds so they are divided so Discord can use it presence.startTimestamp = Std.int(startTimestamp / 1000); - presence.endTimestamp = Std.int(endTimestamp / 1000); + presence.endTimestamp = Std.int(endTime / 1000); updatePresence(); // trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp'); diff --git a/source/engine/backend/EaseUtil.hx b/source/engine/backend/EaseUtil.hx index 5716020d..376937ad 100644 --- a/source/engine/backend/EaseUtil.hx +++ b/source/engine/backend/EaseUtil.hx @@ -2,6 +2,7 @@ package backend; +@:nullSafety class EaseUtil { public static inline function stepped(steps:Int):Float->Float diff --git a/source/engine/backend/FunkinPreloader.hx b/source/engine/backend/FunkinPreloader.hx index b24c6f3a..59c88251 100644 --- a/source/engine/backend/FunkinPreloader.hx +++ b/source/engine/backend/FunkinPreloader.hx @@ -20,6 +20,7 @@ import backend.Paths; using StringTools; // @:bitmap("assets/preloader/banner.png") +@:nullSafety class LogoImage extends BitmapData { } diff --git a/source/engine/backend/Highscore.hx b/source/engine/backend/Highscore.hx index 4a5bdc20..8742c79d 100644 --- a/source/engine/backend/Highscore.hx +++ b/source/engine/backend/Highscore.hx @@ -1,5 +1,6 @@ package backend; +@:nullSafety class Highscore { public static var weekScores:Map = new Map(); @@ -19,7 +20,7 @@ class Highscore setWeekScore(daWeek, 0); } - public static function saveScore(song:String, score:Int = 0, ?diff:Int = 0, ?rating:Float = -1):Void + public static function saveScore(song:String, score:Int = 0, diff:Int = 0, rating:Float = -1):Void { if (song == null) return; @@ -27,7 +28,8 @@ class Highscore if (songScores.exists(daSong)) { - if (songScores.get(daSong) < score) + var existingScore = songScores.get(daSong); + if (existingScore != null && existingScore < score) { setScore(daSong, score); if (rating >= 0) @@ -42,13 +44,14 @@ class Highscore } } - public static function saveWeekScore(week:String, score:Int = 0, ?diff:Int = 0):Void + public static function saveWeekScore(week:String, score:Int = 0, diff:Int = 0):Void { var daWeek:String = formatSong(week, diff); if (weekScores.exists(daWeek)) { - if (weekScores.get(daWeek) < score) + var existingScore = weekScores.get(daWeek); + if (existingScore != null && existingScore < score) setWeekScore(daWeek, score); } else @@ -93,7 +96,8 @@ class Highscore if (!songScores.exists(daSong)) setScore(daSong, 0); - return songScores.get(daSong); + var result = songScores.get(daSong); + return result != null ? result : 0; } public static function getRating(song:String, diff:Int):Float @@ -102,7 +106,8 @@ class Highscore if (!songRating.exists(daSong)) setRating(daSong, 0); - return songRating.get(daSong); + var result = songRating.get(daSong); + return result != null ? result : 0; } public static function getWeekScore(week:String, diff:Int):Int @@ -111,7 +116,8 @@ class Highscore if (!weekScores.exists(daWeek)) setWeekScore(daWeek, 0); - return weekScores.get(daWeek); + var result = weekScores.get(daWeek); + return result != null ? result : 0; } public static function load():Void diff --git a/source/engine/backend/IMusicState.hx b/source/engine/backend/IMusicState.hx index b0acf4e0..56c405f6 100644 --- a/source/engine/backend/IMusicState.hx +++ b/source/engine/backend/IMusicState.hx @@ -5,9 +5,10 @@ import flixel.addons.transition.FlxTransitionableState; import flixel.util.FlxSave; import backend.rendering.PsychCamera; +@:nullSafety interface IMusicState { - public var stateInstance:FlxState; + public var stateInstance:Null; public var members(default, null):Array; @@ -90,13 +91,13 @@ interface IMusicState public function stepHit():Void; public function beatHit():Void; public function sectionHit():Void; - function getBeatsOnSection():Null; + function getBeatsOnSection():Float; #if (FEATURE_LUA || FEATURE_HSCRIPT) public function addTextToDebug(text:String, color:FlxColor):Void; #end - public function getLuaObject(tag:String, text:Bool = true):FlxSprite; + public function getLuaObject(tag:String, text:Bool = true):Null; #if FEATURE_LUA public function startLuasNamed(luaFile:String):Bool; @@ -113,7 +114,7 @@ interface IMusicState public function callOnLuas(funcToCall:String, args:Array = null, ignoreStops:Bool = false, exclusions:Array = null, excludeValues:Array = null):Dynamic; - public function callOnHScript(funcToCall:String, args:Array = null, ?ignoreStops:Bool = false, exclusions:Array = null, + public function callOnHScript(funcToCall:String, args:Array = null, ignoreStops:Bool = false, exclusions:Array = null, excludeValues:Array = null):Dynamic; public function setOnScripts(variable:String, arg:Dynamic, exclusions:Array = null):Void; diff --git a/source/engine/backend/InputFormatter.hx b/source/engine/backend/InputFormatter.hx index 7b1f0dd4..872b14a8 100644 --- a/source/engine/backend/InputFormatter.hx +++ b/source/engine/backend/InputFormatter.hx @@ -5,6 +5,7 @@ import flixel.input.gamepad.FlxGamepad; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.FlxGamepadManager; +@:nullSafety class InputFormatter { public static function getKeyName(key:FlxKey):String diff --git a/source/engine/backend/Main.hx b/source/engine/backend/Main.hx index 2ac66508..5af9b38e 100644 --- a/source/engine/backend/Main.hx +++ b/source/engine/backend/Main.hx @@ -21,6 +21,7 @@ import lime.ui.WindowVSyncMode; import states.TitleState; import openfl.events.KeyboardEvent; +@:nullSafety class Main extends Sprite { public static final game = { @@ -33,7 +34,7 @@ class Main extends Sprite startFullscreen: false // if the game should start at fullscreen mode }; - public static var fpsVar:Framerate; + public static var fpsVar:Null = null; public static function main():Void { @@ -164,7 +165,7 @@ class Main extends Sprite static function resetSpriteCache(sprite:Sprite):Void { - @:privateAccess + @:privateAccess @:nullSafety(Off) { sprite.__cacheBitmap = null; sprite.__cacheBitmapData = null; @@ -173,7 +174,7 @@ class Main extends Sprite function toggleFullScreen(event:KeyboardEvent):Void { - if (Controls.instance.justReleased('fullscreen')) + if (Controls.instance != null && Controls.instance.justReleased('fullscreen')) FlxG.fullscreen = !FlxG.fullscreen; } diff --git a/source/engine/backend/Mods.hx b/source/engine/backend/Mods.hx index 9995c6a9..8d989336 100644 --- a/source/engine/backend/Mods.hx +++ b/source/engine/backend/Mods.hx @@ -7,6 +7,7 @@ typedef ModsList = all:Array }; +@:nullSafety class Mods { static public var currentModDirectory:String = ''; @@ -144,7 +145,7 @@ class Mods { try { - var rawJson:String = File.getContent(path); + var rawJson:Null = File.getContent(path); if (rawJson != null && rawJson.length > 0) return Json.parse(rawJson, path); } diff --git a/source/engine/backend/MusicBeatState.hx b/source/engine/backend/MusicBeatState.hx index 4261971c..8459d218 100644 --- a/source/engine/backend/MusicBeatState.hx +++ b/source/engine/backend/MusicBeatState.hx @@ -5,9 +5,10 @@ import flixel.util.FlxSave; import backend.rendering.PsychCamera; import haxe.io.Path; +@:nullSafety class MusicBeatState extends FlxTransitionableState implements IMusicState { - public var stateInstance:FlxState = null; + public var stateInstance:Null = null; private var curSection:Int = 0; private var stepsToDo:Int = 0; @@ -37,27 +38,27 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState #end #if (FEATURE_LUA || FEATURE_HSCRIPT) - private var luaDebugGroup:FlxTypedGroup; - private var luaDebugCam:ShadowCamera; - private var currentClassName:String; + private var luaDebugGroup:Null> = null; + private var luaDebugCam:Null = null; + private var currentClassName:String = ''; #end public var variables:Map = new Map(); public var controls(get, never):Controls; - private function get_controls() + private function get_controls():Controls { - return Controls.instance; + return Controls.instance != null ? Controls.instance : new Controls(); } #if FEATURE_MOBILE_CONTROLS - public var touchPad:TouchPad; - public var touchPadCam:ShadowCamera; - public var luaTouchPad:TouchPad; - public var luaTouchPadCam:ShadowCamera; - public var mobileControls:IMobileControls; - public var mobileControlsCam:ShadowCamera; + public var touchPad:Null = null; + public var touchPadCam:Null = null; + public var luaTouchPad:Null = null; + public var luaTouchPadCam:Null = null; + public var mobileControls:Null = null; + public var mobileControlsCam:Null = null; public function addTouchPad(DPad:String, Action:String) { @@ -457,8 +458,10 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState private function updateCurStep():Void { var lastChange = Conductor.getBPMFromSeconds(Conductor.songPosition); + var sc = lastChange.stepCrochet; + if (sc == null) sc = Conductor.stepCrochet; - var shit = ((Conductor.songPosition - ClientPrefs.data.noteOffset) - lastChange.songTime) / lastChange.stepCrochet; + var shit = ((Conductor.songPosition - ClientPrefs.data.noteOffset) - lastChange.songTime) / sc; curDecStep = lastChange.stepTime + shit; curStep = lastChange.stepTime + Math.floor(shit); } @@ -559,7 +562,7 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState func(stage); } - public function getBeatsOnSection() + public function getBeatsOnSection():Float { var val:Null = 4; if (PlayState.SONG != null && PlayState.SONG.notes[curSection] != null) @@ -593,7 +596,7 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState } #end - public function getLuaObject(tag:String, text:Bool = true):FlxSprite + public function getLuaObject(tag:String, text:Bool = true):Null { #if FEATURE_LUA if (modchartSprites.exists(tag)) @@ -720,9 +723,10 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState if (len <= 0) len = e.message.length; addTextToDebug('ERROR - ' + e.message.substr(0, len), FlxColor.RED); - var newScript:HScript = cast(SScript.global.get(file), HScript); - if (newScript != null) + var scriptFromGlobal = SScript.global.get(file); + if (scriptFromGlobal != null) { + var newScript:HScript = cast scriptFromGlobal; newScript.destroy(); hscriptArray.remove(newScript); } @@ -794,7 +798,7 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState return returnVal; } - public function callOnHScript(funcToCall:String, args:Array = null, ?ignoreStops:Bool = false, exclusions:Array = null, + public function callOnHScript(funcToCall:String, args:Array = null, ignoreStops:Bool = false, exclusions:Array = null, excludeValues:Array = null):Dynamic { var returnVal:Dynamic = LuaUtils.Function_Continue; diff --git a/source/engine/backend/MusicBeatSubstate.hx b/source/engine/backend/MusicBeatSubstate.hx index 66409a96..8e1595b1 100644 --- a/source/engine/backend/MusicBeatSubstate.hx +++ b/source/engine/backend/MusicBeatSubstate.hx @@ -3,10 +3,11 @@ package backend; import flixel.util.FlxSave; import haxe.io.Path; +@:nullSafety class MusicBeatSubstate extends FlxSubState implements IMusicState { - public var stateInstance:FlxState = null; - public static var instance:MusicBeatSubstate; + public var stateInstance:Null = null; + public static var instance:Null = null; private var curSection:Int = 0; private var stepsToDo:Int = 0; @@ -39,9 +40,9 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState #end #if (FEATURE_LUA || FEATURE_HSCRIPT) - private var luaDebugGroup:FlxTypedGroup; - private var luaDebugCam:ShadowCamera; - private var currentClassName:String; + private var luaDebugGroup:Null> = null; + private var luaDebugCam:Null = null; + private var currentClassName:String = ''; #end public var variables:Map = new Map(); @@ -49,15 +50,15 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState public var controls(get, never):Controls; private function get_controls():Controls - return Controls.instance; + return Controls.instance != null ? Controls.instance : new Controls(); #if FEATURE_MOBILE_CONTROLS - public var touchPad:TouchPad; - public var touchPadCam:ShadowCamera; - public var luaTouchPad:TouchPad; - public var luaTouchPadCam:ShadowCamera; - public var mobileControls:IMobileControls; - public var mobileControlsCam:ShadowCamera; + public var touchPad:Null = null; + public var touchPadCam:Null = null; + public var luaTouchPad:Null = null; + public var luaTouchPadCam:Null = null; + public var mobileControls:Null = null; + public var mobileControlsCam:Null = null; public function addTouchPad(DPad:String, Action:String) { @@ -424,8 +425,10 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState private function updateCurStep():Void { var lastChange = Conductor.getBPMFromSeconds(Conductor.songPosition); + var sc = lastChange.stepCrochet; + if (sc == null) sc = Conductor.stepCrochet; - var shit = ((Conductor.songPosition - ClientPrefs.data.noteOffset) - lastChange.songTime) / lastChange.stepCrochet; + var shit = ((Conductor.songPosition - ClientPrefs.data.noteOffset) - lastChange.songTime) / sc; curDecStep = lastChange.stepTime + shit; curStep = lastChange.stepTime + Math.floor(shit); } @@ -449,7 +452,7 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState callOnScripts('onSectionHit'); } - public function getBeatsOnSection() + public function getBeatsOnSection():Float { var val:Null = 4; if (PlayState.SONG != null && PlayState.SONG.notes[curSection] != null) @@ -483,7 +486,7 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState } #end - public function getLuaObject(tag:String, text:Bool = true):FlxSprite + public function getLuaObject(tag:String, text:Bool = true):Null { #if FEATURE_LUA if (modchartSprites.exists(tag)) @@ -609,9 +612,10 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState if (len <= 0) len = e.message.length; addTextToDebug('ERROR - ' + e.message.substr(0, len), FlxColor.RED); - var newScript:HScript = cast(SScript.global.get(file), HScript); - if (newScript != null) + var scriptFromGlobal = SScript.global.get(file); + if (scriptFromGlobal != null) { + var newScript:HScript = cast scriptFromGlobal; newScript.destroy(); hscriptArray.remove(newScript); } @@ -683,7 +687,7 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState return returnVal; } - public function callOnHScript(funcToCall:String, args:Array = null, ?ignoreStops:Bool = false, exclusions:Array = null, + public function callOnHScript(funcToCall:String, args:Array = null, ignoreStops:Bool = false, exclusions:Array = null, excludeValues:Array = null):Dynamic { var returnVal:Dynamic = LuaUtils.Function_Continue; diff --git a/source/engine/backend/Native.hx b/source/engine/backend/Native.hx index 6aab072f..81c7e09e 100644 --- a/source/engine/backend/Native.hx +++ b/source/engine/backend/Native.hx @@ -20,6 +20,7 @@ package backend; #if cpp @:headerCode('#include ') #end +@:nullSafety class Native { public static function disableErrorReporting():Void diff --git a/source/engine/backend/NoteTypesConfig.hx b/source/engine/backend/NoteTypesConfig.hx index 58cd9bd4..a8f69f8a 100644 --- a/source/engine/backend/NoteTypesConfig.hx +++ b/source/engine/backend/NoteTypesConfig.hx @@ -8,6 +8,7 @@ typedef NoteTypeProperty = value:Dynamic } +@:nullSafety class NoteTypesConfig { private static var noteTypesData:Map> = new Map>(); @@ -20,9 +21,12 @@ class NoteTypesConfig if (noteTypesData.exists(name)) return noteTypesData.get(name); - var str:String = Paths.getTextFromFile('custom_notetypes/$name.txt'); + var str:Null = Paths.getTextFromFile('custom_notetypes/$name.txt'); if (str == null || !str.contains(':') || !str.contains('=')) + { noteTypesData.set(name, null); + return null; + } var parsed:Array = []; var lines:Array = CoolUtil.listFromString(str); @@ -53,7 +57,7 @@ class NoteTypesConfig public static function applyNoteTypeData(note:Note, name:String) { - var data:Array = loadNoteTypeData(name); + var data:Null> = loadNoteTypeData(name); if (data == null || data.length < 1) return; @@ -99,7 +103,8 @@ class NoteTypesConfig for (i in 0...propArray.length) { var str:Dynamic = propArray[i]; - var id:Int = Std.parseInt(str.substr(0, str.length - 1).trim()); + var id:Null = Std.parseInt(str.substr(0, str.length - 1).trim()); + if (id == null) id = 0; if (i < propArray.length - 1) obj = obj[id]; // middles else if (setProp) @@ -117,7 +122,7 @@ class NoteTypesConfig return Reflect.getProperty(obj, slice); } - private static function _interpretValue(value:String):Any + private static function _interpretValue(value:String):Null { if (value.charAt(0) == "'" || value.charAt(0) == '"') { diff --git a/source/engine/backend/Paths.hx b/source/engine/backend/Paths.hx index 92c7a516..c142e472 100644 --- a/source/engine/backend/Paths.hx +++ b/source/engine/backend/Paths.hx @@ -14,6 +14,7 @@ import openfl.geom.Rectangle; import openfl.media.Sound; import animate.FlxAnimateFrames; +@:nullSafety class Paths { public static final IMAGE_EXT:String = "png"; @@ -108,7 +109,7 @@ class Paths openfl.Assets.cache.clear("songs"); } - public static function getPath(file:String, ?type:AssetType = TEXT, ?library:Null = null, ?modsAllowed:Bool = false):String + public static function getPath(file:String, ?type:AssetType = TEXT, ?library:Null = null, modsAllowed:Bool = false):String { #if USING_GPU_TEXTURES if (file.endsWith(IMAGE_EXT) && FileSystem.exists(haxe.io.Path.withoutExtension(file) + '.$GPU_IMAGE_EXT')) @@ -211,7 +212,7 @@ class Paths return 'assets/fonts/$key'; } - public static function fileExists(key:String, type:AssetType, ?ignoreMods:Bool = false, ?library:String = null):Bool + public static function fileExists(key:String, type:AssetType, ignoreMods:Bool = false, ?library:String = null):Bool { var path:String = getPath(key, type, library, false); @@ -259,21 +260,24 @@ class Paths } } - public static function image(key:String, ?library:String = null):FlxGraphic + public static function image(key:String, ?library:String = null):Null { - var bitmap:BitmapData = null; - var file:String = null; + var bitmap:Null = null; + var file:String = ''; #if FEATURE_MODS file = modsImages(key); if (currentTrackedAssets.exists(file)) { localTrackedAssets.push(file); - return currentTrackedAssets.get(file); + var asset = currentTrackedAssets.get(file); + if (asset != null) return asset; } else if (FileSystem.exists(file)) { - bitmap = BitmapData.fromBytes(File.getBytes(file)); + var bytes = File.getBytes(file); + if (bytes != null) + bitmap = BitmapData.fromBytes(bytes); } else #end @@ -284,10 +288,15 @@ class Paths if (currentTrackedAssets.exists(file)) { localTrackedAssets.push(file); - return currentTrackedAssets.get(file); + var asset = currentTrackedAssets.get(file); + if (asset != null) return asset; } else if (FileSystem.exists(file)) - bitmap = BitmapData.fromBytes(File.getBytes(file)); + { + var bytes = File.getBytes(file); + if (bytes != null) + bitmap = BitmapData.fromBytes(bytes); + } if (bitmap != null) break; } @@ -305,18 +314,27 @@ class Paths if (currentTrackedAssets.exists('__flixel_logo')) { localTrackedAssets.push('__flixel_logo'); - return currentTrackedAssets.get('__flixel_logo'); + var logo = currentTrackedAssets.get('__flixel_logo'); + if (logo != null) return logo; } - return cacheBitmap('__flixel_logo', FlxAssets.getBitmapFromClass(GraphicLogo)); + var fallback = cacheBitmap('__flixel_logo', FlxAssets.getBitmapFromClass(GraphicLogo)); + if (fallback != null) return fallback; + + trace("Failed to load fallback image"); + return null; } - public static function cacheBitmap(file:String, ?bitmap:BitmapData = null):FlxGraphic + public static function cacheBitmap(file:String, ?bitmap:Null = null):Null { if (bitmap == null) { if (FileSystem.exists(file)) - bitmap = BitmapData.fromBytes(File.getBytes(file)); + { + var bytes = File.getBytes(file); + if (bytes != null) + bitmap = BitmapData.fromBytes(bytes); + } if (bitmap == null) return null; @@ -339,7 +357,7 @@ class Paths return newGraphic; } - public static function getTextFromFile(key:String, ?ignoreMods:Bool = false):String + public static function getTextFromFile(key:String, ignoreMods:Bool = false):Null { #if FEATURE_MODS if (!ignoreMods) @@ -357,34 +375,34 @@ class Paths return null; } - public static function sound(key:String, ?library:String):Sound + public static function sound(key:String, ?library:String):Null { return returnSound('sounds', key, library); } - inline public static function soundRandom(key:String, min:Int, max:Int, ?library:String):Sound + inline public static function soundRandom(key:String, min:Int, max:Int, ?library:String):Null { return sound(key + FlxG.random.int(min, max), library); } - inline public static function music(key:String, ?library:String):Sound + inline public static function music(key:String, ?library:String):Null { return returnSound('music', key, library); } - inline public static function voices(song:String, postfix:String = null):Any + inline public static function voices(song:String, postfix:String = null):Null { var songKey:String = 'songs/${formatToSongPath(song)}/Voices${postfix != null ? '-$postfix' : ''}${LOADOLD ? "-Old" : ""}'; return returnSound(null, songKey); } - inline public static function inst(song:String, postfix:String = null):Sound + inline public static function inst(song:String, postfix:String = null):Null { var songKey:String = 'songs/${formatToSongPath(song)}/Inst${postfix != null ? '-$postfix' : ''}${LOADOLD ? "-Old" : ""}'; return returnSound(null, songKey); } - public static function returnSound(path:Null, key:String, ?library:String):Sound + public static function returnSound(path:Null, key:String, ?library:String):Null { #if FEATURE_MODS var modLibPath:String = ''; @@ -399,7 +417,8 @@ class Paths if (!currentTrackedSounds.exists(file)) currentTrackedSounds.set(file, Sound.fromFile(file)); localTrackedAssets.push(file); - return currentTrackedSounds.get(file); + var snd = currentTrackedSounds.get(file); + if (snd != null) return snd; } #end @@ -415,80 +434,137 @@ class Paths var retKey:String = (path != null) ? '$path/$key' : key; retKey = getPath('$retKey.ogg', SOUND, library); if (FileSystem.exists(retKey)) - currentTrackedSounds.set(gottenPath, Sound.fromBytes(File.getBytes(retKey))); + { + var bytes = File.getBytes(retKey); + if (bytes != null) + currentTrackedSounds.set(gottenPath, Sound.fromBytes(bytes)); + } } localTrackedAssets.push(gottenPath); - return currentTrackedSounds.get(gottenPath); + var result = currentTrackedSounds.get(gottenPath); + if (result != null) return result; + trace("Failed to load sound: " + gottenPath); + return null; } - public static function getAtlas(key:String, ?library:String = null):FlxAtlasFrames + public static function getAtlas(key:String, ?library:String = null):Null { - var imageLoaded:FlxGraphic = image(key, library); + var imageLoaded = image(key, library); + if (imageLoaded == null) + { + trace("Failed to load image for atlas: " + key); + return null; + } var xmlPath:String = getPath('images/$key.xml', TEXT, library, true); #if FEATURE_MODS var modXml:String = modsXml(key); if (FileSystem.exists(modXml)) - return FlxAtlasFrames.fromSparrow(imageLoaded, File.getContent(modXml)); + { + var content = File.getContent(modXml); + if (content != null) return FlxAtlasFrames.fromSparrow(imageLoaded, content); + } #end if (FileSystem.exists(xmlPath)) - return FlxAtlasFrames.fromSparrow(imageLoaded, File.getContent(xmlPath)); + { + var content = File.getContent(xmlPath); + if (content != null) return FlxAtlasFrames.fromSparrow(imageLoaded, content); + } var jsonPath:String = getPath('images/$key.json', TEXT, library, true); #if FEATURE_MODS var modJson:String = modsImagesJson(key); if (FileSystem.exists(modJson)) - return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, File.getContent(modJson)); + { + var content = File.getContent(modJson); + if (content != null) return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, content); + } #end if (FileSystem.exists(jsonPath)) - return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, File.getContent(jsonPath)); + { + var content = File.getContent(jsonPath); + if (content != null) return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, content); + } return getPackerAtlas(key, library); } - public static function getSparrowAtlas(key:String, ?library:String = null):FlxAtlasFrames + public static function getSparrowAtlas(key:String, ?library:String = null):Null { - var imageLoaded:FlxGraphic = image(key, library); + var imageLoaded = image(key, library); + if (imageLoaded == null) + { + trace("Failed to load image for sparrow atlas: " + key); + return null; + } #if FEATURE_MODS var modXml:String = modsXml(key); if (FileSystem.exists(modXml)) - return FlxAtlasFrames.fromSparrow(imageLoaded, File.getContent(modXml)); + { + var content = File.getContent(modXml); + if (content != null) return FlxAtlasFrames.fromSparrow(imageLoaded, content); + } #end var xmlPath:String = getPath('images/$key.xml', library); - return FlxAtlasFrames.fromSparrow(imageLoaded, File.getContent(xmlPath)); + var content = File.getContent(xmlPath); + if (content != null) return FlxAtlasFrames.fromSparrow(imageLoaded, content); + trace("Failed to load sparrow atlas: " + key); + return null; } - public static function getPackerAtlas(key:String, ?library:String = null):FlxAtlasFrames + public static function getPackerAtlas(key:String, ?library:String = null):Null { - var imageLoaded:FlxGraphic = image(key, library); + var imageLoaded = image(key, library); + if (imageLoaded == null) + { + trace("Failed to load image for packer atlas: " + key); + return null; + } #if FEATURE_MODS var modTxt:String = modsTxt(key); if (FileSystem.exists(modTxt)) - return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, File.getContent(modTxt)); + { + var content = File.getContent(modTxt); + if (content != null) return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, content); + } #end var txtPath:String = getPath('images/$key.txt', library); - return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, File.getContent(txtPath)); + var content = File.getContent(txtPath); + if (content != null) return FlxAtlasFrames.fromSpriteSheetPacker(imageLoaded, content); + trace("Failed to load packer atlas: " + key); + return null; } - public static function getAsepriteAtlas(key:String, ?library:String = null):FlxAtlasFrames + public static function getAsepriteAtlas(key:String, ?library:String = null):Null { - var imageLoaded:FlxGraphic = image(key, library); + var imageLoaded = image(key, library); + if (imageLoaded == null) + { + trace("Failed to load image for aseprite atlas: " + key); + return null; + } #if FEATURE_MODS var modJson:String = modsImagesJson(key); if (FileSystem.exists(modJson)) - return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, File.getContent(modJson)); + { + var content = File.getContent(modJson); + if (content != null) return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, content); + } #end var jsonPath:String = getPath('images/$key.json', library); - return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, File.getContent(jsonPath)); + var content = File.getContent(jsonPath); + if (content != null) return FlxAtlasFrames.fromTexturePackerJson(imageLoaded, content); + trace("Failed to load aseprite atlas: " + key); + return null; } public static function getTextureAtlas(key:String, ?library:String = null, ?settings:FlxAnimateSettings):FlxAnimateFrames diff --git a/source/engine/backend/Rating.hx b/source/engine/backend/Rating.hx index 2a03d58a..c780366e 100644 --- a/source/engine/backend/Rating.hx +++ b/source/engine/backend/Rating.hx @@ -1,5 +1,6 @@ package backend; +@:nullSafety class Rating { public var name:String = ''; diff --git a/source/engine/backend/Section.hx b/source/engine/backend/Section.hx index 66707217..1c2bb823 100644 --- a/source/engine/backend/Section.hx +++ b/source/engine/backend/Section.hx @@ -11,6 +11,7 @@ typedef SwagSection = var altAnim:Bool; } +@:nullSafety class Section { public var sectionNotes:Array = []; diff --git a/source/engine/backend/Song.hx b/source/engine/backend/Song.hx index a7ebd49c..1e35555e 100644 --- a/source/engine/backend/Song.hx +++ b/source/engine/backend/Song.hx @@ -32,24 +32,25 @@ typedef SwagSong = @:optional var format:String; } +@:nullSafety class Song { public var song:String; public var notes:Array; - public var events:Array; + public var events:Array = []; public var bpm:Float; public var needsVoices:Bool = true; - public var playerArrowSkin:String; - public var opponentArrowSkin:String; - public var splashSkin:String; - public var gameOverChar:String; - public var gameOverSound:String; - public var gameOverLoop:String; - public var gameOverEnd:String; + public var playerArrowSkin:String = ''; + public var opponentArrowSkin:String = ''; + public var splashSkin:String = ''; + public var gameOverChar:String = ''; + public var gameOverSound:String = ''; + public var gameOverLoop:String = ''; + public var gameOverEnd:String = ''; public var disableNoteRGB(get, set):Bool; public var disableNoteCustomColor:Bool = false; public var speed:Float = 1; - public var stage:String; + public var stage:String = ''; public var player1:String = 'bf'; public var player2:String = 'dad'; public var gfVersion:String = 'gf'; @@ -116,23 +117,23 @@ class Song public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong { - var formattedFolder:String = Paths.formatToSongPath(folder); + var formattedFolder:String = Paths.formatToSongPath(folder ?? ''); var formattedSong:String = Paths.formatToSongPath(jsonInput); var path:String = ""; - var rawJson:String = null; + var rawJson:Null = null; #if FEATURE_MODS var modPath:String = Paths.modsJson(formattedFolder + '/' + formattedSong); if (FileSystem.exists(modPath)) { path = modPath; - rawJson = File.getContent(modPath).trim(); + rawJson = File.getContent(modPath)?.trim(); } #end if (rawJson == null) { path = Paths.json(formattedFolder + '/' + formattedSong); - rawJson = File.getContent(path).trim(); + rawJson = File.getContent(path)?.trim(); } // LOL GOING THROUGH THE BULLSHIT TO CLEAN IDK WHATS STRANGE @@ -140,7 +141,7 @@ class Song while (!rawJson.endsWith("}")) rawJson = rawJson.substr(0, rawJson.length - 1); - var songJson:Dynamic = parseJSONshit(rawJson, path); + var songJson:Dynamic = parseJSONshit(rawJson ?? '', path); if (!jsonInput.startsWith("events")) StageData.loadDirectory(songJson); @@ -151,7 +152,7 @@ class Song public static function parseJSONshit(rawJson:String, ?file:String):SwagSong { - final parsed:Dynamic = Json.parse(rawJson, file); + final parsed:Dynamic = Json.parse(rawJson, file ?? null); if (parsed.song != null) { diff --git a/source/engine/backend/StageData.hx b/source/engine/backend/StageData.hx index c42e028c..03bd2854 100644 --- a/source/engine/backend/StageData.hx +++ b/source/engine/backend/StageData.hx @@ -35,6 +35,7 @@ enum abstract LoadFilters(Int) from Int from UInt to Int to UInt var FREEPLAY:Int = (1 << 3); } +@:nullSafety class StageData { public static function dummy():StageFile @@ -57,7 +58,7 @@ class StageData }; } - public static var forceNextDirectory:String = null; + public static var forceNextDirectory:Null = null; public static function loadDirectory(SONG:SwagSong) { @@ -79,7 +80,7 @@ class StageData stage = 'stage'; } - var stageFile:StageFile = getStageFile(stage); + var stageFile:Null = getStageFile(stage); if (stageFile == null) // preventing crashes { forceNextDirectory = ''; @@ -90,10 +91,10 @@ class StageData } } - public static function getStageFile(stage:String):StageFile + public static function getStageFile(stage:String):Null { var path:String = Paths.getSharedPath('stages/' + stage + '.json'); - var rawJson:String = null; + var rawJson:Null = null; #if FEATURE_MODS var modPath:String = Paths.modFolders('stages/' + stage + '.json'); if (FileSystem.exists(modPath)) @@ -106,7 +107,9 @@ class StageData if (FileSystem.exists(path)) rawJson = File.getContent(path); - return cast Json.parse(rawJson, path); + if (rawJson != null) + return cast Json.parse(rawJson, path); + return null; } public static function vanillaSongStage(songName):String @@ -114,8 +117,8 @@ class StageData public static var reservedNames:Array = ['gf', 'gfGroup', 'dad', 'dadGroup', 'boyfriend', 'boyfriendGroup']; // blocks these names from being used on stage editor's name input text - public static function addObjectsToState(objectList:Array, gf:FlxSprite, dad:FlxSprite, boyfriend:FlxSprite, ?group:Dynamic = null, - ?ignoreFilters:Bool = false) + public static function addObjectsToState(objectList:Array, gf:FlxSprite, dad:FlxSprite, boyfriend:FlxSprite, group:Dynamic = null, + ignoreFilters:Bool = false) { var addedObjects:Map = []; for (num => data in objectList) @@ -159,9 +162,17 @@ class StageData if (data.type != 'square') { if (data.type == 'sprite') - spr.loadGraphic(Paths.image(data.image)); + { + var graphic = Paths.image(data.image); + if (graphic != null) + spr.loadGraphic(graphic); + } else - spr.frames = Paths.getAtlas(data.image); + { + var atlas = Paths.getAtlas(data.image); + if (atlas != null) + spr.frames = atlas; + } if (data.type == 'animatedSprite' && data.animations != null) { diff --git a/source/engine/backend/WeekData.hx b/source/engine/backend/WeekData.hx index 9e848af3..a4824cd4 100644 --- a/source/engine/backend/WeekData.hx +++ b/source/engine/backend/WeekData.hx @@ -19,6 +19,7 @@ typedef WeekFile = var difficulties:String; } +@:nullSafety class WeekData { public static var weeksLoaded:Map = new Map(); @@ -27,20 +28,20 @@ class WeekData public var folder:String = ''; // JSON variables - public var songs:Array; - public var weekCharacters:Array; - public var weekBackground:String; - public var weekBefore:String; - public var storyName:String; - public var weekName:String; - public var freeplayColor:Array; - public var startUnlocked:Bool; - public var hiddenUntilUnlocked:Bool; - public var hideStoryMode:Bool; - public var hideFreeplay:Bool; - public var difficulties:String; - - public var fileName:String; + public var songs:Array = []; + public var weekCharacters:Array = []; + public var weekBackground:String = ''; + public var weekBefore:String = ''; + public var storyName:String = ''; + public var weekName:String = ''; + public var freeplayColor:Array = [146, 113, 253]; + public var startUnlocked:Bool = true; + public var hiddenUntilUnlocked:Bool = false; + public var hideStoryMode:Bool = false; + public var hideFreeplay:Bool = false; + public var difficulties:String = ''; + + public var fileName:String = ''; public static function createWeekFile():WeekFile { @@ -110,7 +111,7 @@ class WeekData var fileToCheck:String = directories[j] + 'weeks/' + sexList[i] + '.json'; if (!weeksLoaded.exists(sexList[i])) { - var week:WeekFile = getWeekFile(fileToCheck); + var week:Null = getWeekFile(fileToCheck); if (week != null) { var weekFile:WeekData = new WeekData(week, sexList[i]); @@ -185,7 +186,7 @@ class WeekData { if (!weeksLoaded.exists(weekToCheck)) { - var week:WeekFile = getWeekFile(path); + var week:Null = getWeekFile(path); if (week != null) { var weekFile:WeekData = new WeekData(week, weekToCheck); @@ -204,9 +205,9 @@ class WeekData } } - private static function getWeekFile(path:String):WeekFile + private static function getWeekFile(path:String):Null { - var rawJson:String = null; + var rawJson:Null = null; if (FileSystem.exists(path)) { rawJson = File.getContent(path); @@ -234,7 +235,7 @@ class WeekData } // Used on LoadingState, nothing really too relevant - public static function getCurrentWeek():WeekData + public static function getCurrentWeek():Null { return weeksLoaded.get(weeksList[PlayState.storyWeek]); } diff --git a/source/engine/backend/io/FileSystem.hx b/source/engine/backend/io/FileSystem.hx index 1b6c6b40..2e3180e9 100644 --- a/source/engine/backend/io/FileSystem.hx +++ b/source/engine/backend/io/FileSystem.hx @@ -12,6 +12,7 @@ using StringTools; * Unified file system class that works with both native file access and OpenFL assets. * @see https://github.com/Psych-Slice/P-Slice/blob/master/source/mikolka/funkin/custom/NativeFileSystem.hx */ +@:nullSafety class FileSystem { inline static function cwd(path:String):String diff --git a/source/engine/backend/rendering/PsychCamera.hx b/source/engine/backend/rendering/PsychCamera.hx index 2bb75ac0..dabe7dc8 100644 --- a/source/engine/backend/rendering/PsychCamera.hx +++ b/source/engine/backend/rendering/PsychCamera.hx @@ -2,6 +2,7 @@ package backend.rendering; // PsychCamera handles followLerp based on elapsed // and stops camera from snapping at higher framerates +@:nullSafety class PsychCamera extends ShadowCamera { override public function update(elapsed:Float):Void @@ -16,7 +17,10 @@ class PsychCamera extends ShadowCamera updateFlash(elapsed); updateFade(elapsed); - flashSprite.filters = filtersEnabled ? filters : null; + if (filtersEnabled && filters != null) + flashSprite.filters = filters; + else + flashSprite.filters = []; updateFlashSpritePosition(); updateShake(elapsed); @@ -100,7 +104,7 @@ class PsychCamera extends ShadowCamera } } - var mult:Float = 1 - Math.exp(-elapsed * followLerp); + var mult:Float = 1 - Math.exp(-(elapsed ?? 0) * followLerp); scroll.x += (_scrollTarget.x - scroll.x) * mult; scroll.y += (_scrollTarget.y - scroll.y) * mult; // trace('lerp on this frame: $mult'); diff --git a/source/engine/backend/rendering/ShadowCamera.hx b/source/engine/backend/rendering/ShadowCamera.hx index 02ee9102..f521444f 100644 --- a/source/engine/backend/rendering/ShadowCamera.hx +++ b/source/engine/backend/rendering/ShadowCamera.hx @@ -18,6 +18,8 @@ import flixel.graphics.tile.FlxDrawTrianglesItem; using backend.BitmapDataUtil; +@:nullSafety + /** * A FlxCamera with additional powerful features: * - Added the ability to grab the camera screen as a `BitmapData` and use it as a texture. @@ -98,7 +100,7 @@ class ShadowCamera extends FlxCamera public var id:String; var _blendShader:RuntimeCustomBlendShader; - var _backgroundFrame:FlxFrame; + var _backgroundFrame:Null; var _blendRenderTexture:RenderTexture; var _backgroundRenderTexture:RenderTexture; @@ -112,8 +114,9 @@ class ShadowCamera extends FlxCamera this.id = id; - _backgroundFrame = new FlxFrame(new FlxGraphic('', null)); - _backgroundFrame.frame = new FlxRect(); + @:privateAccess var emptyBitmap:BitmapData = new BitmapData(1, 1, true, 0); + @:privateAccess _backgroundFrame = new FlxFrame(new FlxGraphic('', emptyBitmap)); + if (_backgroundFrame != null) _backgroundFrame.frame = new FlxRect(); _blendShader = new RuntimeCustomBlendShader(); @@ -133,7 +136,7 @@ class ShadowCamera extends FlxCamera if (shouldUseShader) { _cameraTexture.drawCameraScreen(this); - _backgroundFrame.frame.set(0, 0, this.width, this.height); + if (_backgroundFrame != null) _backgroundFrame.frame.set(0, 0, this.width, this.height); // Clear the camera's graphics // It'll get redrawn anyway @@ -160,14 +163,14 @@ class ShadowCamera extends FlxCamera _blendShader.blendSwag = blend; _blendShader.updateViewInfo(width, height, this); - _backgroundFrame.parent.bitmap = _blendRenderTexture.graphic.bitmap; + if (_backgroundFrame != null) _backgroundFrame.parent.bitmap = _blendRenderTexture.graphic.bitmap; _backgroundRenderTexture.init(Std.int(this.width * Lib.current.stage.window.scale), Std.int(this.height * Lib.current.stage.window.scale)); _backgroundRenderTexture.drawToCamera((camera, matrix) -> { camera.zoom = this.zoom; matrix.scale(Lib.current.stage.window.scale, Lib.current.stage.window.scale); - camera.drawPixels(_backgroundFrame, null, matrix, canvas.transform.colorTransform, null, false, _blendShader); + if (_backgroundFrame != null) camera.drawPixels(_backgroundFrame, null, matrix, canvas.transform.colorTransform, null, false, _blendShader); }); _backgroundRenderTexture.render(); @@ -190,19 +193,18 @@ class ShadowCamera extends FlxCamera // Can't batch complex non-coherent blends, so always force a new batch if (hasKhronosExtension && !(OpenGLRenderer.__coherentBlendsSupported ?? false) && KHR_BLEND_MODES.contains(blend)) { - var itemToReturn = null; - - if (FlxCamera._storageTilesHead != null) + var itemToReturn:FlxDrawQuadsItem = if (FlxCamera._storageTilesHead != null) { - itemToReturn = FlxCamera._storageTilesHead; + var item = FlxCamera._storageTilesHead; var newHead = FlxCamera._storageTilesHead.nextTyped; - itemToReturn.reset(); + item.reset(); FlxCamera._storageTilesHead = newHead; + item; } else { - itemToReturn = new FlxDrawQuadsItem(); - } + new FlxDrawQuadsItem(); + }; // TODO: catch this error when the dev actually messes up, not in the draw phase if (graphic.isDestroyed) @@ -213,7 +215,7 @@ class ShadowCamera extends FlxCamera itemToReturn.colored = colored; itemToReturn.hasColorOffsets = hasColorOffsets; itemToReturn.blend = blend; - itemToReturn.shader = shader; + if (shader != null) itemToReturn.shader = shader; itemToReturn.nextTyped = _headTiles; _headTiles = itemToReturn; diff --git a/source/engine/objects/Alphabet.hx b/source/engine/objects/Alphabet.hx index 22ad1b6b..266b481f 100644 --- a/source/engine/objects/Alphabet.hx +++ b/source/engine/objects/Alphabet.hx @@ -7,9 +7,10 @@ enum Alignment RIGHT; } +@:nullSafety class Alphabet extends FlxSpriteGroup { - public var text(default, set):String; + public var text(default, set):String = ""; public var bold:Bool = false; public var letters:Array = []; @@ -33,7 +34,7 @@ class Alphabet extends FlxSpriteGroup this.startPosition.x = x; this.startPosition.y = y; - this.bold = bold; + this.bold = (bold == null) ? false : bold; this.text = text; moves = false; diff --git a/source/engine/objects/Ana.hx b/source/engine/objects/Ana.hx index d5107f8a..dbd0aa08 100644 --- a/source/engine/objects/Ana.hx +++ b/source/engine/objects/Ana.hx @@ -1,6 +1,7 @@ // for results screen I have no fucking idea package objects; +@:nullSafety class Ana { public var hitTime:Float; diff --git a/source/engine/objects/AttachedSprite.hx b/source/engine/objects/AttachedSprite.hx index 5930f2ca..cf2535ed 100644 --- a/source/engine/objects/AttachedSprite.hx +++ b/source/engine/objects/AttachedSprite.hx @@ -1,8 +1,12 @@ package objects; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.graphics.FlxGraphic; + +@:nullSafety(Strict) class AttachedSprite extends FlxSprite { - public var sprTracker:FlxSprite; + public var sprTracker:Null = null; public var xAdd:Float = 0; public var yAdd:Float = 0; public var angleAdd:Float = 0; @@ -15,15 +19,22 @@ class AttachedSprite extends FlxSprite public function new(?file:String = null, ?anim:String = null, ?library:String = null, ?loop:Bool = false) { super(); - if (anim != null) + if (anim != null && file != null) { - frames = Paths.getSparrowAtlas(file, library); - animation.addByPrefix('idle', anim, 24, loop); - animation.play('idle'); + var frames:Null = Paths.getSparrowAtlas(file, library); + if (frames != null) + { + var animName:String = anim; + this.frames = frames; + animation.addByPrefix('idle', animName, 24, loop); + animation.play('idle'); + } } else if (file != null) { - loadGraphic(Paths.image(file)); + var img:Null = Paths.image(file); + if (img != null) + loadGraphic(img); } antialiasing = ClientPrefs.data.antialiasing; scrollFactor.set(); @@ -33,19 +44,20 @@ class AttachedSprite extends FlxSprite { super.update(elapsed); - if (sprTracker != null) + var tracker = sprTracker; + if (tracker != null) { - setPosition(sprTracker.x + xAdd, sprTracker.y + yAdd); - scrollFactor.set(sprTracker.scrollFactor.x, sprTracker.scrollFactor.y); + setPosition(tracker.x + xAdd, tracker.y + yAdd); + scrollFactor.set(tracker.scrollFactor.x, tracker.scrollFactor.y); if (copyAngle) - angle = sprTracker.angle + angleAdd; + angle = tracker.angle + angleAdd; if (copyAlpha) - alpha = sprTracker.alpha * alphaMult; + alpha = tracker.alpha * alphaMult; if (copyVisible) - visible = sprTracker.visible; + visible = tracker.visible; } } diff --git a/source/engine/objects/AttachedText.hx b/source/engine/objects/AttachedText.hx index 7c86914e..98c0369b 100644 --- a/source/engine/objects/AttachedText.hx +++ b/source/engine/objects/AttachedText.hx @@ -1,33 +1,39 @@ package objects; +@:nullSafety(Strict) class AttachedText extends Alphabet { public var offsetX:Float = 0; public var offsetY:Float = 0; - public var sprTracker:FlxSprite; + public var sprTracker:Null = null; public var copyVisible:Bool = true; public var copyAlpha:Bool = false; public function new(text:String = "", ?offsetX:Float = 0, ?offsetY:Float = 0, ?bold = false, ?scale:Float = 1) { + var ox:Float = offsetX != null ? offsetX : 0; + var oy:Float = offsetY != null ? offsetY : 0; + var s:Float = scale != null ? scale : 1; + super(0, 0, text, bold); - this.setScale(scale); + this.setScale(s); this.isMenuItem = false; - this.offsetX = offsetX; - this.offsetY = offsetY; + this.offsetX = ox; + this.offsetY = oy; } override function update(elapsed:Float) { - if (sprTracker != null) + var tracker = sprTracker; + if (tracker != null) { - setPosition(sprTracker.x + offsetX, sprTracker.y + offsetY); + setPosition(tracker.x + offsetX, tracker.y + offsetY); if (copyVisible) - visible = sprTracker.visible; + visible = tracker.visible; if (copyAlpha) - alpha = sprTracker.alpha; + alpha = tracker.alpha; } super.update(elapsed); diff --git a/source/engine/objects/BGSprite.hx b/source/engine/objects/BGSprite.hx index 125ecae1..7b01b96c 100644 --- a/source/engine/objects/BGSprite.hx +++ b/source/engine/objects/BGSprite.hx @@ -1,24 +1,35 @@ package objects; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.graphics.FlxGraphic; + +@:nullSafety class BGSprite extends FlxSprite { - private var idleAnim:String; + private var idleAnim:Null = null; public function new(image:String, x:Float = 0, y:Float = 0, ?scrollX:Float = 1, ?scrollY:Float = 1, ?animArray:Array = null, ?loop:Bool = false) { super(x, y); - if (animArray != null) + var sx:Float = scrollX != null ? scrollX : 1; + var sy:Float = scrollY != null ? scrollY : 1; + + if (animArray != null && image != null) { - frames = Paths.getSparrowAtlas(image); - for (i in 0...animArray.length) + var atlas:Null = Paths.getSparrowAtlas(image); + if (atlas != null) { - var anim:String = animArray[i]; - animation.addByPrefix(anim, anim, 24, loop); - if (idleAnim == null) + frames = atlas; + for (i in 0...animArray.length) { - idleAnim = anim; - animation.play(anim); + var anim:String = animArray[i]; + animation.addByPrefix(anim, anim, 24, loop); + if (idleAnim == null) + { + idleAnim = anim; + animation.play(anim); + } } } } @@ -26,11 +37,13 @@ class BGSprite extends FlxSprite { if (image != null) { - loadGraphic(Paths.image(image)); + var img:Null = Paths.image(image); + if (img != null) + loadGraphic(img); } active = false; } - scrollFactor.set(scrollX, scrollY); + scrollFactor.set(sx, sy); antialiasing = ClientPrefs.data.antialiasing; } @@ -38,7 +51,8 @@ class BGSprite extends FlxSprite { if (idleAnim != null) { - animation.play(idleAnim, forceplay); + var fp:Bool = forceplay != null ? forceplay : false; + animation.play(idleAnim, fp); } } } diff --git a/source/engine/objects/Bar.hx b/source/engine/objects/Bar.hx index 316d4e32..60727df0 100644 --- a/source/engine/objects/Bar.hx +++ b/source/engine/objects/Bar.hx @@ -1,49 +1,57 @@ package objects; import flixel.math.FlxRect; +import flixel.graphics.FlxGraphic; +@:nullSafety class Bar extends FlxSpriteGroup { - public var leftBar:FlxSprite; - public var rightBar:FlxSprite; - public var bg:FlxSprite; - public var valueFunction:Void->Float = null; + public var leftBar:Null = null; + public var rightBar:Null = null; + public var bg:Null = null; + public var valueFunction:NullFloat> = null; public var percent(default, set):Float = 0; public var bounds:Dynamic = {min: 0, max: 1}; public var leftToRight(default, set):Bool = true; public var barCenter(default, null):Float = 0; - // you might need to change this if you want to use a custom bar public var barWidth(default, set):Int = 1; public var barHeight(default, set):Int = 1; public var barOffset:FlxPoint = FlxPoint.get(3, 3); - private var percentTween:FlxTween = null; + private var percentTween:Null = null; - public function new(x:Float, y:Float, image:String = 'healthBar', valueFunction:Void->Float = null, boundX:Float = 0, boundY:Float = 1) + public function new(x:Float, y:Float, image:String = 'healthBar', ?valueFunction:Void->Float, boundX:Float = 0, boundY:Float = 1) { super(x, y); this.valueFunction = valueFunction; - setBounds(boundX, boundY); + bounds.min = boundX; + bounds.max = boundY; - bg = new FlxSprite().loadGraphic(Paths.image(image)); - bg.antialiasing = ClientPrefs.data.antialiasing; - barWidth = Std.int(bg.width - 6); - barHeight = Std.int(bg.height - 6); - - leftBar = new FlxSprite().makeGraphic(Std.int(bg.width), Std.int(bg.height), FlxColor.WHITE); - // leftBar.color = FlxColor.WHITE; - leftBar.antialiasing = antialiasing = ClientPrefs.data.antialiasing; - - rightBar = new FlxSprite().makeGraphic(Std.int(bg.width), Std.int(bg.height), FlxColor.WHITE); - rightBar.color = FlxColor.BLACK; - rightBar.antialiasing = ClientPrefs.data.antialiasing; - - add(leftBar); - add(rightBar); - add(bg); - regenerateClips(); + var img:Null = Paths.image(image); + if (img != null) + { + bg = new FlxSprite(); + bg.loadGraphic(img); + bg.antialiasing = ClientPrefs.data.antialiasing; + barWidth = Std.int(bg.width - 6); + barHeight = Std.int(bg.height - 6); + + leftBar = new FlxSprite(); + leftBar.makeGraphic(Std.int(bg.width), Std.int(bg.height), FlxColor.WHITE); + leftBar.antialiasing = ClientPrefs.data.antialiasing; + + rightBar = new FlxSprite(); + rightBar.makeGraphic(Std.int(bg.width), Std.int(bg.height), FlxColor.WHITE); + rightBar.color = FlxColor.BLACK; + rightBar.antialiasing = ClientPrefs.data.antialiasing; + + if (leftBar != null) add(leftBar); + if (rightBar != null) add(rightBar); + if (bg != null) add(bg); + regenerateClips(); + } moves = false; immovable = true; @@ -59,10 +67,12 @@ class Bar extends FlxSpriteGroup return; } - if (valueFunction != null) + var vf = valueFunction; + if (vf != null) { - var value:Null = FlxMath.remapToRange(FlxMath.bound(valueFunction(), bounds.min, bounds.max), bounds.min, bounds.max, 0, 100); - percent = set_percent(value != null ? value : 0); + var rawValue:Float = vf(); + var value:Float = FlxMath.remapToRange(FlxMath.bound(rawValue, bounds.min, bounds.max), bounds.min, bounds.max, 0, 100); + percent = set_percent(value); } else percent = 0; @@ -75,21 +85,26 @@ class Bar extends FlxSpriteGroup bounds.max = max; } - public function setColors(left:FlxColor = null, right:FlxColor = null) + public function setColors(?left:FlxColor, ?right:FlxColor) { - if (left != null) - leftBar.color = left; - if (right != null) - rightBar.color = right; + var lb = leftBar; + var rb = rightBar; + if (left != null && lb != null) + lb.color = left; + if (right != null && rb != null) + rb.color = right; } public function updateBar() { - if (leftBar == null || rightBar == null) + var lb = leftBar; + var rb = rightBar; + var bgSprite = bg; + if (lb == null || rb == null || bgSprite == null) return; - leftBar.setPosition(bg.x, bg.y); - rightBar.setPosition(bg.x, bg.y); + lb.setPosition(bgSprite.x, bgSprite.y); + rb.setPosition(bgSprite.x, bgSprite.y); var leftSize:Float = 0; if (leftToRight) @@ -97,36 +112,38 @@ class Bar extends FlxSpriteGroup else leftSize = FlxMath.lerp(0, barWidth, 1 - percent / 100); - leftBar.clipRect.width = leftSize; - leftBar.clipRect.height = barHeight; - leftBar.clipRect.x = barOffset.x; - leftBar.clipRect.y = barOffset.y; + lb.clipRect.width = leftSize; + lb.clipRect.height = barHeight; + lb.clipRect.x = barOffset.x; + lb.clipRect.y = barOffset.y; - rightBar.clipRect.width = barWidth - leftSize; - rightBar.clipRect.height = barHeight; - rightBar.clipRect.x = barOffset.x + leftSize; - rightBar.clipRect.y = barOffset.y; + rb.clipRect.width = barWidth - leftSize; + rb.clipRect.height = barHeight; + rb.clipRect.x = barOffset.x + leftSize; + rb.clipRect.y = barOffset.y; - barCenter = leftBar.x + leftSize + barOffset.x; + barCenter = lb.x + leftSize + barOffset.x; - // flixel is restarted - leftBar.clipRect = leftBar.clipRect; - rightBar.clipRect = rightBar.clipRect; + lb.clipRect = lb.clipRect; + rb.clipRect = rb.clipRect; } public function regenerateClips() { - if (leftBar != null) + var lb = leftBar; + var rb = rightBar; + var bgSprite = bg; + if (lb != null && bgSprite != null) { - leftBar.setGraphicSize(Std.int(bg.width), Std.int(bg.height)); - leftBar.updateHitbox(); - leftBar.clipRect = new FlxRect(0, 0, Std.int(bg.width), Std.int(bg.height)); + lb.setGraphicSize(Std.int(bgSprite.width), Std.int(bgSprite.height)); + lb.updateHitbox(); + lb.clipRect = new FlxRect(0, 0, Std.int(bgSprite.width), Std.int(bgSprite.height)); } - if (rightBar != null) + if (rb != null && bgSprite != null) { - rightBar.setGraphicSize(Std.int(bg.width), Std.int(bg.height)); - rightBar.updateHitbox(); - rightBar.clipRect = new FlxRect(0, 0, Std.int(bg.width), Std.int(bg.height)); + rb.setGraphicSize(Std.int(bgSprite.width), Std.int(bgSprite.height)); + rb.updateHitbox(); + rb.clipRect = new FlxRect(0, 0, Std.int(bgSprite.width), Std.int(bgSprite.height)); } updateBar(); } diff --git a/source/engine/objects/Character.hx b/source/engine/objects/Character.hx index 97e28d93..85eaed79 100644 --- a/source/engine/objects/Character.hx +++ b/source/engine/objects/Character.hx @@ -47,6 +47,7 @@ enum CharacterSpriteType TEXTURE_ATLAS; } +@:nullSafety class Character extends FlxAnimate { /** @@ -97,12 +98,10 @@ class Character extends FlxAnimate super(x, y); animOffsets = new Map>(); - curCharacter = character; - this.isPlayer = isPlayer; + curCharacter = character != null ? character : DEFAULT_CHARACTER; + this.isPlayer = isPlayer != null ? isPlayer : false; switch (curCharacter) { - // case 'your character name in case you want to hardcode them instead': - default: var characterPath:String = 'characters/$curCharacter.json'; @@ -110,14 +109,19 @@ class Character extends FlxAnimate if (!FileSystem.exists(path)) { path = Paths.getSharedPath('characters/' + DEFAULT_CHARACTER + - '.json'); // If a character couldn't be found, change him to BF just to prevent a crash + '.json'); color = FlxColor.BLACK; alpha = 0.6; } try { - loadCharacterFile(Json.parse(File.getContent(path), path)); + var jsonStr:Null = File.getContent(path); + if (jsonStr != null) + { + var jsonContent:Dynamic = Json.parse(jsonStr, path); + loadCharacterFile(jsonContent); + } } catch (e:Dynamic) { @@ -152,8 +156,11 @@ class Character extends FlxAnimate spriteType = MULTI_ATLAS; isAnimateAtlas = false; isMultiAtlas = true; - frames = Paths.getAtlas(json.image[0]); - final split:Array = json.image; + var imgArray:Array = json.image; + var atlas:Null = Paths.getAtlas(imgArray[0]); + if (atlas != null) + frames = atlas; + final split:Array = imgArray; if (frames != null) for (imgFile in split) { @@ -161,24 +168,29 @@ class Character extends FlxAnimate if (daAtlas != null) cast(frames, flixel.graphics.frames.FlxAtlasFrames).addAtlas(daAtlas); } - imageFile = json.image[0]; + imageFile = imgArray[0]; } else { - if (!Paths.fileExists('images/${haxe.io.Path.withExtension(json.image, 'png')}', IMAGE)) + var imgPath:String = json.image; + if (!Paths.fileExists('images/${haxe.io.Path.withExtension(imgPath, 'png')}', IMAGE)) { spriteType = TEXTURE_ATLAS; isAnimateAtlas = true; isMultiAtlas = false; - frames = Paths.getTextureAtlas(json.image); + var texAtlas:Null = Paths.getTextureAtlas(imgPath); + if (texAtlas != null) + frames = texAtlas; } else { spriteType = SPRITE; isMultiAtlas = isAnimateAtlas = false; - frames = Paths.getAtlas(json.image); + var sprAtlas:Null = Paths.getAtlas(imgPath); + if (sprAtlas != null) + frames = sprAtlas; } - imageFile = json.image; + imageFile = imgPath; } jsonScale = json.scale; @@ -220,7 +232,8 @@ class Character extends FlxAnimate switch (spriteType) { case TEXTURE_ATLAS: - if (anim.isFrameLabel) + var isFrameLabel:Bool = anim.isFrameLabel != null ? anim.isFrameLabel : false; + if (isFrameLabel) { if (animIndices != null && animIndices.length > 0) this.anim.addByFrameLabelIndices(animAnim, animName, animIndices, animFps, animLoop); @@ -381,10 +394,10 @@ class Character extends FlxAnimate if (animOffsets.exists(AnimName)) { - var daOffset = animOffsets.get(AnimName); - offset.set(daOffset[0], daOffset[1]); + var daOffset:Null> = animOffsets.get(AnimName); + if (daOffset != null) + offset.set(daOffset[0], daOffset[1]); } - // else offset.set(0, 0); if (curCharacter.startsWith('gf-') || curCharacter == 'gf') { diff --git a/source/engine/objects/CheckboxThingie.hx b/source/engine/objects/CheckboxThingie.hx index 2b63ab77..08998749 100644 --- a/source/engine/objects/CheckboxThingie.hx +++ b/source/engine/objects/CheckboxThingie.hx @@ -1,9 +1,12 @@ package objects; +import flixel.graphics.frames.FlxAtlasFrames; + +@:nullSafety class CheckboxThingie extends FlxSprite { - public var sprTracker:FlxSprite; - public var daValue(default, set):Bool; + public var sprTracker:Null = null; + public var daValue(default, set):Bool = false; public var copyAlpha:Bool = true; public var offsetX:Float = 0; public var offsetY:Float = 0; @@ -12,11 +15,12 @@ class CheckboxThingie extends FlxSprite { super(x, y); - // why would we need velocity for this?? moves = false; immovable = true; - frames = Paths.getSparrowAtlas('checkboxanim'); + var atlas:Null = Paths.getSparrowAtlas('checkboxanim'); + if (atlas != null) + frames = atlas; animation.addByPrefix("unchecked", "checkbox0", 24, false); animation.addByPrefix("unchecking", "checkbox anim reverse", 24, false); animation.addByPrefix("checking", "checkbox anim0", 24, false); @@ -26,19 +30,21 @@ class CheckboxThingie extends FlxSprite setGraphicSize(Std.int(0.9 * width)); updateHitbox(); - animationFinished(checked ? 'checking' : 'unchecking'); + var c:Bool = checked != null ? checked : false; + animationFinished(c ? 'checking' : 'unchecking'); animation.onFinish.add(animationFinished); - daValue = checked; + daValue = c; } override function update(elapsed:Float) { - if (sprTracker != null) + var tracker = sprTracker; + if (tracker != null) { - setPosition(sprTracker.x - 130 + offsetX, sprTracker.y + 30 + offsetY); + setPosition(tracker.x - 130 + offsetX, tracker.y + 30 + offsetY); if (copyAlpha) { - alpha = sprTracker.alpha; + alpha = tracker.alpha; } } super.update(elapsed); diff --git a/source/engine/objects/CustomSoundTray.hx b/source/engine/objects/CustomSoundTray.hx index eee032cc..4f9ee239 100644 --- a/source/engine/objects/CustomSoundTray.hx +++ b/source/engine/objects/CustomSoundTray.hx @@ -7,31 +7,29 @@ import openfl.display.Bitmap; import openfl.display.BitmapData; import openfl.media.Sound; +@:nullSafety class CustomSoundTray extends FlxSoundTray { var graphicScale:Float = 0.3; var lerpYPos:Float = 0; var alphaTarget:Float = 0; - var volumeMaxSound:String; + var volumeMaxSound:String = ""; var _lastVolume:Int = -1; - var bg:Bitmap; - var backingBar:Bitmap; - var bgPath:String; - var backingPath:String; + var bg:Null = null; + var backingBar:Null = null; + var bgPath:String = ""; + var backingPath:String = ""; var barPaths:Array = []; public function new() { super(); - removeChildren(); - + bg = new Bitmap(); backingBar = new Bitmap(); - bgPath = ""; - backingPath = ""; - barPaths = []; + removeChildren(); loadImages(); y = -height; @@ -48,24 +46,32 @@ class CustomSoundTray extends FlxSoundTray bgPath = getImagePath('soundtray/volumebox'); if (FileSystem.exists(bgPath)) { - bg = new Bitmap(BitmapData.fromBytes(File.getBytes(bgPath))); - bg.scaleX = graphicScale; - bg.scaleY = graphicScale; - bg.smoothing = true; - addChild(bg); + var bgBytes:Null = File.getBytes(bgPath); + if (bgBytes != null) + { + bg = new Bitmap(BitmapData.fromBytes(bgBytes)); + bg.scaleX = graphicScale; + bg.scaleY = graphicScale; + bg.smoothing = true; + addChild(bg); + } } backingPath = getImagePath('soundtray/bars_10'); if (FileSystem.exists(backingPath)) { - backingBar = new Bitmap(BitmapData.fromBytes(File.getBytes(backingPath))); - backingBar.x = 9; - backingBar.y = 5; - backingBar.scaleX = graphicScale; - backingBar.scaleY = graphicScale; - backingBar.smoothing = true; - addChild(backingBar); - backingBar.alpha = 0.4; + var backingBytes:Null = File.getBytes(backingPath); + if (backingBytes != null) + { + backingBar = new Bitmap(BitmapData.fromBytes(backingBytes)); + backingBar.x = 9; + backingBar.y = 5; + backingBar.scaleX = graphicScale; + backingBar.scaleY = graphicScale; + backingBar.smoothing = true; + addChild(backingBar); + backingBar.alpha = 0.4; + } } _bars = []; @@ -78,14 +84,23 @@ class CustomSoundTray extends FlxSoundTray if (FileSystem.exists(barPath)) { - var bar:Bitmap = new Bitmap(BitmapData.fromBytes(File.getBytes(barPath))); - bar.x = 9; - bar.y = 5; - bar.scaleX = graphicScale; - bar.scaleY = graphicScale; - bar.smoothing = true; - addChild(bar); - _bars.push(bar); + var barBytes:Null = File.getBytes(barPath); + if (barBytes != null) + { + var bar:Bitmap = new Bitmap(BitmapData.fromBytes(barBytes)); + bar.x = 9; + bar.y = 5; + bar.scaleX = graphicScale; + bar.scaleY = graphicScale; + bar.smoothing = true; + addChild(bar); + _bars.push(bar); + } + else + { + var emptyBar:Bitmap = new Bitmap(); + _bars.push(emptyBar); + } } else { @@ -178,7 +193,11 @@ class CustomSoundTray extends FlxSoundTray sound = volumeMaxSound; if (sound != null) - FlxG.sound.play(Sound.fromBytes(File.getBytes(sound))); + { + var soundBytes:Null = File.getBytes(sound); + if (soundBytes != null) + FlxG.sound.play(Sound.fromBytes(soundBytes)); + } } _lastVolume = globalVolume; diff --git a/source/engine/objects/HealthIcon.hx b/source/engine/objects/HealthIcon.hx index f2fa466c..b837807e 100644 --- a/source/engine/objects/HealthIcon.hx +++ b/source/engine/objects/HealthIcon.hx @@ -1,8 +1,11 @@ package objects; +import flixel.graphics.FlxGraphic; + +@:nullSafety class HealthIcon extends FlxSprite { - public var sprTracker:FlxSprite; + public var sprTracker:Null = null; private var isOldIcon:Bool = false; private var isPlayer:Bool = false; @@ -21,8 +24,9 @@ class HealthIcon extends FlxSprite { super.update(elapsed); - if (sprTracker != null) - setPosition(sprTracker.x + sprTracker.width + 12, sprTracker.y - 30); + var tracker = sprTracker; + if (tracker != null) + setPosition(tracker.x + tracker.width + 12, tracker.y - 30); } private var iconOffsets:Array = [0, 0]; @@ -33,31 +37,33 @@ class HealthIcon extends FlxSprite { var name:String = 'icons/' + char; if (!Paths.fileExists('images/' + name + '.${Paths.IMAGE_EXT}', Paths.getImageAssetType(Paths.IMAGE_EXT))) - name = 'icons/icon-' + char; // Older versions of psych engine's support + name = 'icons/icon-' + char; if (!Paths.fileExists('images/' + name + '.${Paths.IMAGE_EXT}', Paths.getImageAssetType(Paths.IMAGE_EXT))) - name = 'icons/icon-face'; // Prevents crash from missing icon - - var graphic = Paths.image(name); - - var frames = Math.floor(graphic.width / 150); - loadGraphic(graphic, true, Math.floor(graphic.width / frames), Math.floor(graphic.height)); - - iconOffsets[0] = (width - 150) / 2; - iconOffsets[1] = (height - 150) / 2; - updateHitbox(); - - var frameIndices:Array = []; - for (i in 0...frames) - frameIndices.push(i); - - animation.add(char, frameIndices, 0, false, isPlayer); - animation.play(char); - this.char = char; - - if (char.endsWith('-pixel')) - antialiasing = false; - else - antialiasing = ClientPrefs.data.antialiasing; + name = 'icons/icon-face'; + + var graphic:Null = Paths.image(name); + if (graphic != null) + { + var frames = Math.floor(graphic.width / 150); + loadGraphic(graphic, true, Math.floor(graphic.width / frames), Math.floor(graphic.height)); + + iconOffsets[0] = (width - 150) / 2; + iconOffsets[1] = (height - 150) / 2; + updateHitbox(); + + var frameIndices:Array = []; + for (i in 0...frames) + frameIndices.push(i); + + animation.add(char, frameIndices, 0, false, isPlayer); + animation.play(char); + this.char = char; + + if (char.endsWith('-pixel')) + antialiasing = false; + else + antialiasing = ClientPrefs.data.antialiasing; + } } } diff --git a/source/engine/objects/MenuCharacter.hx b/source/engine/objects/MenuCharacter.hx index e9c35768..54022c9b 100644 --- a/source/engine/objects/MenuCharacter.hx +++ b/source/engine/objects/MenuCharacter.hx @@ -1,6 +1,7 @@ package objects; import openfl.utils.Assets; +import flixel.graphics.frames.FlxAtlasFrames; typedef MenuCharacterFile = { @@ -12,9 +13,10 @@ typedef MenuCharacterFile = var flipX:Bool; } +@:nullSafety class MenuCharacter extends FlxSprite { - public var character:String; + public var character:String = ""; public var hasConfirmAnimation:Bool = false; private static var DEFAULT_CHARACTER:String = 'bf'; @@ -57,32 +59,36 @@ class MenuCharacter extends FlxSprite path = modPath; #end - if (!FileSystem.exists(path)) - path = Paths.getSharedPath(defaultPath); - - var rawJson:String = File.getContent(path); - - var charFile:MenuCharacterFile = cast Json.parse(rawJson, path); - frames = Paths.getSparrowAtlas('menucharacters/' + charFile.image); - animation.addByPrefix('idle', charFile.idle_anim, 24); - - var confirmAnim:String = charFile.confirm_anim; - if (confirmAnim != null && confirmAnim.length > 0 && confirmAnim != charFile.idle_anim) - { - animation.addByPrefix('confirm', confirmAnim, 24, false); - if (animation.getByName('confirm') != null) // check for invalid animation - hasConfirmAnimation = true; - } - - flipX = (charFile.flipX == true); - - if (charFile.scale != 1) - { - scale.set(charFile.scale, charFile.scale); - updateHitbox(); - } - offset.set(charFile.position[0], charFile.position[1]); - animation.play('idle'); + if (!FileSystem.exists(path)) + path = Paths.getSharedPath(defaultPath); + + var rawJson:Null = File.getContent(path); + if (rawJson == null) + return; + + var charFile:MenuCharacterFile = cast Json.parse(rawJson, path); + var atlas:Null = Paths.getSparrowAtlas('menucharacters/' + charFile.image); + if (atlas != null) + frames = atlas; + animation.addByPrefix('idle', charFile.idle_anim, 24); + + var confirmAnim:String = charFile.confirm_anim; + if (confirmAnim != null && confirmAnim.length > 0 && confirmAnim != charFile.idle_anim) + { + animation.addByPrefix('confirm', confirmAnim, 24, false); + if (animation.getByName('confirm') != null) + hasConfirmAnimation = true; + } + + flipX = (charFile.flipX == true); + + if (charFile.scale != 1) + { + scale.set(charFile.scale, charFile.scale); + updateHitbox(); + } + offset.set(charFile.position[0], charFile.position[1]); + animation.play('idle'); } } } diff --git a/source/engine/objects/MenuItem.hx b/source/engine/objects/MenuItem.hx index 60c76ea6..21442451 100644 --- a/source/engine/objects/MenuItem.hx +++ b/source/engine/objects/MenuItem.hx @@ -1,5 +1,8 @@ package objects; +import flixel.graphics.FlxGraphic; + +@:nullSafety class MenuItem extends FlxSprite { public var targetY:Float = 0; @@ -7,7 +10,9 @@ class MenuItem extends FlxSprite public function new(x:Float, y:Float, weekName:String = '') { super(x, y); - loadGraphic(Paths.image('storymenu/' + weekName)); + var img:Null = Paths.image('storymenu/' + weekName); + if (img != null) + loadGraphic(img); antialiasing = ClientPrefs.data.antialiasing; } diff --git a/source/engine/objects/MusicPlayer.hx b/source/engine/objects/MusicPlayer.hx index fcd0937e..871ef57e 100644 --- a/source/engine/objects/MusicPlayer.hx +++ b/source/engine/objects/MusicPlayer.hx @@ -8,6 +8,7 @@ import states.FreeplayState; /** * Music player used for Freeplay */ +@:nullSafety(Off) @:access(states.FreeplayState) class MusicPlayer extends FlxGroup { @@ -17,7 +18,7 @@ class MusicPlayer extends FlxGroup public var paused(get, never):Bool; public var playingMusic:Bool = false; - public var curTime:Float; + public var curTime:Float = 0; var songBG:FlxSprite; var songTxt:FlxText; diff --git a/source/engine/objects/Note.hx b/source/engine/objects/Note.hx index ee12e8ba..4e909f9d 100644 --- a/source/engine/objects/Note.hx +++ b/source/engine/objects/Note.hx @@ -38,6 +38,7 @@ typedef NoteSplashData = * * If you want to make a custom note type, you should search for: "function set_noteType" **/ +@:nullSafety class Note extends FlxSkewedSprite { public var extraData:Map = new Map(); @@ -51,26 +52,26 @@ class Note extends FlxSkewedSprite public var ignoreNote:Bool = false; public var hitByOpponent:Bool = false; public var noteWasHit:Bool = false; - public var prevNote:Note; - public var nextNote:Note; + public var prevNote:Null = null; + public var nextNote:Null = null; public var spawned:Bool = false; public var tail:Array = []; // for sustains - public var parent:Note; + public var parent:Null = null; public var blockHit:Bool = false; // only works for player public var sustainLength:Float = 0; public var isSustainNote:Bool = false; - public var noteType(default, set):String = null; + public var noteType(default, set):Null = null; public var eventName:String = ''; public var eventLength:Int = 0; public var eventVal1:String = ''; public var eventVal2:String = ''; - public var colorSwap:ColorSwap; - public var rgbShader:RGBShaderReference; + public var colorSwap:Null = null; + public var rgbShader:Null = null; public static var globalRgbShaders:Array = []; @@ -123,7 +124,7 @@ class Note extends FlxSkewedSprite public var ratingMod:Float = 0; // 9 = unknown, 0.25 = shit, 0.5 = bad, 0.75 = good, 1 = sick public var ratingDisabled:Bool = false; - public var texture(default, set):String = null; + public var texture(default, set):Null = null; public var noAnimation:Bool = false; public var noMissAnimation:Bool = false; @@ -180,7 +181,7 @@ class Note extends FlxSkewedSprite if (PlayState.isPixelStage.priorityBool(usePixelTextures)) arr = ClientPrefs.data.arrowRGBPixel[noteData]; - if (noteData > -1 && noteData <= arr.length) + if (noteData > -1 && noteData <= arr.length && rgbShader != null) { rgbShader.r = arr[0]; rgbShader.g = arr[1]; @@ -190,9 +191,9 @@ class Note extends FlxSkewedSprite private function set_noteType(value:String):String { - noteSplashData.texture = PlayState.SONG != null ? PlayState.SONG.splashSkin : 'noteSplashes'; + noteSplashData.texture = (PlayState.SONG != null && PlayState.SONG.splashSkin != null) ? PlayState.SONG.splashSkin : 'noteSplashes'; if (ClientPrefs.data.disableRGBNotes) - if (noteData > -1 && noteData < ClientPrefs.data.arrowHSV.length) + if (noteData > -1 && noteData < ClientPrefs.data.arrowHSV.length && colorSwap != null) { colorSwap.hue = noteSplashHue = ClientPrefs.data.arrowHSV[noteData][0] / 360; colorSwap.saturation = noteSplashSaturation = ClientPrefs.data.arrowHSV[noteData][1] / 100; @@ -212,18 +213,24 @@ class Note extends FlxSkewedSprite { reloadNote('HURTNOTE_assets'); // note and splash data colors - colorSwap.hue = noteSplashHue = 0; - colorSwap.saturation = noteSplashSaturation = 0; - colorSwap.brightness = noteSplashBrightness = 0; + if (colorSwap != null) + { + colorSwap.hue = noteSplashHue = 0; + colorSwap.saturation = noteSplashSaturation = 0; + colorSwap.brightness = noteSplashBrightness = 0; + } noteSplashData.texture = 'HURTnoteSplashes'; } else { // note colors - rgbShader.r = 0xFF101010; - rgbShader.g = 0xFFFF0000; - rgbShader.b = 0xFF990022; + if (rgbShader != null) + { + rgbShader.r = 0xFF101010; + rgbShader.g = 0xFFFF0000; + rgbShader.b = 0xFF990022; + } // splash data and colors noteSplashData.r = 0xFFFF0000; @@ -269,15 +276,15 @@ class Note extends FlxSkewedSprite prevNote = this; this.prevNote = prevNote; - isSustainNote = sustainNote; - this.inEditor = inEditor; + isSustainNote = (sustainNote == null) ? false : sustainNote; + this.inEditor = (inEditor == null) ? false : inEditor; this.moves = false; x += (ClientPrefs.data.middleScroll ? PlayState.STRUM_X_MIDDLESCROLL : PlayState.STRUM_X) + 50; // MAKE SURE ITS DEFINITELY OFF SCREEN? y -= 2000; this.strumTime = strumTime; - if (!inEditor) + if (inEditor == null || !inEditor) this.strumTime += ClientPrefs.data.noteOffset; this.noteData = noteData; @@ -293,7 +300,7 @@ class Note extends FlxSkewedSprite else { rgbShader = new RGBShaderReference(this, initializeGlobalRGBShader(noteData)); - if (PlayState.SONG != null && PlayState.SONG.disableNoteCustomColor) + if (PlayState.SONG != null && PlayState.SONG.disableNoteCustomColor && rgbShader != null) rgbShader.enabled = false; } @@ -391,15 +398,13 @@ class Note extends FlxSkewedSprite if (postfix == null) postfix = ''; - var skin:String = texture; - if (texture.length < 1) + var skin:String = (texture != null) ? texture : ''; + if (texture == null || texture.length < 1) { - skin = PlayState.SONG != null ? PlayState.SONG.playerArrowSkin : null; - if (skin == null || skin.length < 1) - skin = defaultNoteSkin; + skin = (PlayState.SONG != null && PlayState.SONG.playerArrowSkin != null) ? PlayState.SONG.playerArrowSkin : defaultNoteSkin; } - var animName:String = null; + var animName:Null = null; if (animation.curAnim != null) { animName = animation.curAnim.name; @@ -423,14 +428,22 @@ class Note extends FlxSkewedSprite var imgPath = 'pixelUI/' + skinPixel + (skinPostfix != '' ? skinPostfix : ''); if (isSustainNote) { - graphic = Paths.image(imgPath + 'ENDS'); - loadGraphic(graphic, true, Math.floor(graphic.width / 4), Math.floor(graphic.height / 2)); - originalHeight = graphic.height / 2; + var endGraphic:Null = Paths.image(imgPath + 'ENDS'); + if (endGraphic != null) + { + graphic = endGraphic; + loadGraphic(graphic, true, Math.floor(graphic.width / 4), Math.floor(graphic.height / 2)); + originalHeight = graphic.height / 2; + } } else { - graphic = Paths.image(imgPath); - loadGraphic(graphic, true, Math.floor(graphic.width / 4), Math.floor(graphic.height / 5)); + var pixelGraphic:Null = Paths.image(imgPath); + if (pixelGraphic != null) + { + graphic = pixelGraphic; + loadGraphic(graphic, true, Math.floor(graphic.width / 4), Math.floor(graphic.height / 5)); + } } setGraphicSize(Std.int(width * PlayState.daPixelZoom)); @@ -446,7 +459,9 @@ class Note extends FlxSkewedSprite } else { - frames = Paths.getSparrowAtlas(skin); + var sparrowFrames = Paths.getSparrowAtlas(skin); + if (sparrowFrames != null) + frames = sparrowFrames; loadNoteAnims(); if (!isSustainNote) { @@ -527,7 +542,9 @@ class Note extends FlxSkewedSprite if (strumTime < Conductor.songPosition + (Conductor.safeZoneOffset * earlyHitMult)) { - if ((isSustainNote && prevNote.wasGoodHit) || strumTime <= Conductor.songPosition) + var prevNoteCheck:Null = prevNote; + var prevWasGoodHit:Bool = (prevNoteCheck != null && prevNoteCheck.wasGoodHit); + if ((isSustainNote && prevWasGoodHit) || strumTime <= Conductor.songPosition) wasGoodHit = true; } } @@ -578,7 +595,9 @@ class Note extends FlxSkewedSprite public function clipToStrumNote(myStrum:StrumNote) { var center:Float = myStrum.y + offsetY + Note.swagWidth / 2; - if (isSustainNote && (mustPress || !ignoreNote) && (!mustPress || (wasGoodHit || (prevNote.wasGoodHit && !canBeHit)))) + var prevNoteClip:Null = prevNote; + var prevClipWasGoodHit:Bool = (prevNoteClip != null && prevNoteClip.wasGoodHit); + if (isSustainNote && (mustPress || !ignoreNote) && (!mustPress || (wasGoodHit || (prevClipWasGoodHit && !canBeHit)))) { var swagRect:FlxRect = clipRect; if (swagRect == null) diff --git a/source/engine/objects/NoteSplash.hx b/source/engine/objects/NoteSplash.hx index e1c466e5..61dbedf8 100644 --- a/source/engine/objects/NoteSplash.hx +++ b/source/engine/objects/NoteSplash.hx @@ -7,6 +7,7 @@ import flixel.graphics.frames.FlxFrame; using backend.CoolUtil; +@:nullSafety typedef NoteSplashConfig = { anim:String, @@ -15,27 +16,28 @@ typedef NoteSplashConfig = offsets:Array> } +@:nullSafety class NoteSplash extends FlxSprite { - public var colorSwap:ColorSwap = null; - public var rgbShader:PixelSplashShaderRef; + public var colorSwap:Null = null; + public var rgbShader:Null = null; - private var idleAnim:String; - private var _textureLoaded:String = null; - private var _configLoaded:String = null; + private var idleAnim:String = ''; + private var _textureLoaded:Null = null; + private var _configLoaded:Null = null; public static var usePixelTextures(default, set):Null; public static var defaultNoteSplash(get, never):String; public static var configs:Map = new Map(); - public static var mainGroup:FlxTypedGroup; + public static var mainGroup:Null> = null; public function new(x:Float = 0, y:Float = 0) { super(x, y); - var skin:String = null; + var skin:Null = null; if (PlayState.SONG.splashSkin != null && PlayState.SONG.splashSkin.length > 0) skin = PlayState.SONG.splashSkin; else @@ -71,7 +73,7 @@ class NoteSplash extends FlxSprite setPosition(x - Note.swagWidth * 0.95, y - Note.swagWidth); aliveTime = 0; - var texture:String = null; + var texture:Null = null; if (note != null && note.noteSplashData.texture != null) texture = note.noteSplashData.texture; else if (PlayState.SONG.splashSkin != null && PlayState.SONG.splashSkin.length > 0) @@ -79,13 +81,13 @@ class NoteSplash extends FlxSprite else texture = defaultNoteSplash + getSplashSkinPostfix(); - var config:NoteSplashConfig = null; + var config:Null = null; if (_textureLoaded != texture) config = loadAnims((PlayState.isPixelStage.priorityBool(usePixelTextures) ? 'pixelUI/' : '') + texture); - else + else if (_configLoaded != null) config = precacheConfig(_configLoaded); - var tempShader:RGBPalette = null; + var tempShader:Null = null; if (ClientPrefs.data.disableRGBNotes) { var hue:Float = 0; @@ -106,34 +108,43 @@ class NoteSplash extends FlxSprite } } - colorSwap.hue = hue; - colorSwap.saturation = saturation; - colorSwap.brightness = brightness; + if (colorSwap != null) + { + colorSwap.hue = hue; + colorSwap.saturation = saturation; + colorSwap.brightness = brightness; + } } else { - if ((note == null || note.noteSplashData.useRGBShader) && (PlayState.SONG == null || !PlayState.SONG.disableNoteCustomColor)) + if ((note == null || note.noteSplashData.useRGBShader) && (PlayState.SONG == null || PlayState.SONG.disableNoteCustomColor == false)) { if (note != null && !note.noteSplashData.useGlobalShader) { - if (note.noteSplashData.r != -1) + if (note.noteSplashData.r != -1 && note.rgbShader != null) note.rgbShader.r = note.noteSplashData.r; - if (note.noteSplashData.g != -1) + if (note.noteSplashData.g != -1 && note.rgbShader != null) note.rgbShader.g = note.noteSplashData.g; - if (note.noteSplashData.b != -1) + if (note.noteSplashData.b != -1 && note.rgbShader != null) note.rgbShader.b = note.noteSplashData.b; - tempShader = note.rgbShader.parent; + if (note.rgbShader != null) + tempShader = note.rgbShader.parent; } else - tempShader = Note.globalRgbShaders[direction]; + tempShader = Note.initializeGlobalRGBShader(direction); } } alpha = ClientPrefs.data.splashAlpha; if (note != null) alpha = note.noteSplashData.a; - if (!ClientPrefs.data.disableRGBNotes) - rgbShader.copyValues(tempShader); + if (!ClientPrefs.data.disableRGBNotes && rgbShader != null) + { + if (tempShader != null) + rgbShader.copyValues(tempShader); + else + rgbShader.copyValues(new RGBPalette()); + } if (note != null) antialiasing = note.noteSplashData.antialiasing; @@ -179,16 +190,22 @@ class NoteSplash extends FlxSprite function loadAnims(skin:String, ?animName:String = null):NoteSplashConfig { maxAnims = 0; - frames = Paths.getSparrowAtlas(skin); - var config:NoteSplashConfig = null; + var sparrowFrames = Paths.getSparrowAtlas(skin); + if (sparrowFrames != null) + frames = sparrowFrames; + var config:Null = null; if (frames == null) { skin = defaultNoteSplash + getSplashSkinPostfix(); - frames = Paths.getSparrowAtlas(skin); + sparrowFrames = Paths.getSparrowAtlas(skin); + if (sparrowFrames != null) + frames = sparrowFrames; if (frames == null) // if you really need this, you really fucked something up { skin = defaultNoteSplash; - frames = Paths.getSparrowAtlas(skin); + sparrowFrames = Paths.getSparrowAtlas(skin); + if (sparrowFrames != null) + frames = sparrowFrames; } } config = precacheConfig(skin); @@ -205,7 +222,7 @@ class NoteSplash extends FlxSprite if (!addAnimAndCheck('note$i-$animID', '$animName ${Note.colArray[i]} $animID', 24, false)) { // trace('maxAnims: $maxAnims'); - return config; + return config != null ? config : defaultConfig(); } } maxAnims++; @@ -233,14 +250,24 @@ class NoteSplash extends FlxSprite var config:NoteSplashConfig = { anim: configFile[0], - minFps: Std.parseInt(framerates[0]), - maxFps: Std.parseInt(framerates[1]), + minFps: Std.parseInt(framerates[0]) != null ? Std.parseInt(framerates[0]) : 24, + maxFps: Std.parseInt(framerates[1]) != null ? Std.parseInt(framerates[1]) : 30, offsets: offs }; configs.set(skin, config); return config; } + function defaultConfig():NoteSplashConfig + { + return { + anim: 'note splash', + minFps: 24, + maxFps: 30, + offsets: [[0, 0], [0, 0], [0, 0], [0, 0]] + }; + } + function addAnimAndCheck(name:String, anim:String, ?framerate:Int = 24, ?loop:Bool = false) { var animFrames = []; diff --git a/source/engine/objects/OpenFLSprite.hx b/source/engine/objects/OpenFLSprite.hx index 8623d0d0..6eb7824b 100644 --- a/source/engine/objects/OpenFLSprite.hx +++ b/source/engine/objects/OpenFLSprite.hx @@ -5,17 +5,18 @@ import openfl.display.Sprite; /** * Designed to draw a OpenFL Sprite as a FlxSprite (To allow layering and auto sizing for haxe flixel cameras) */ +@:nullSafety class OpenFLSprite extends FlxSprite { - public var flSprite:Sprite; + public var flSprite:Null = null; - public function new(x, y, width, height, Sprite:Sprite) + public function new(x:Float, y:Float, width:Int, height:Int, sprite:Sprite) { super(x, y); makeGraphic(width, height, FlxColor.TRANSPARENT); - flSprite = Sprite; + flSprite = sprite; pixels.draw(flSprite); } @@ -26,23 +27,25 @@ class OpenFLSprite extends FlxSprite { if (_frameCount != 2) { - pixels.draw(flSprite); + var s = flSprite; + if (s != null) + pixels.draw(s); _frameCount++; } } public function updateDisplay() { - if (flSprite != null && pixels != null) + var s = flSprite; + if (s != null && pixels != null) { try { - pixels.draw(flSprite); + pixels.draw(s); } catch (e:Dynamic) { trace('Error drawing OpenFL Sprite: $e'); - // Optionally, set a fallback graphic or skip } } } diff --git a/source/engine/objects/StrumNote.hx b/source/engine/objects/StrumNote.hx index e374e90d..51cd0624 100644 --- a/source/engine/objects/StrumNote.hx +++ b/source/engine/objects/StrumNote.hx @@ -7,10 +7,11 @@ import shaders.RGBPalette.RGBShaderReference; using backend.CoolUtil; +@:nullSafety class StrumNote extends FlxSkewedSprite { - public var colorSwap:ColorSwap = null; - public var rgbShader:RGBShaderReference; + public var colorSwap:Null = null; + public var rgbShader:Null = null; public var resetAnim:Float = 0; private var noteData:Int = 0; @@ -19,11 +20,11 @@ class StrumNote extends FlxSkewedSprite public var downScroll:Bool = false; // plan on doing scroll directions soon -bb public var sustainReduce:Bool = true; - private var player:Int; + private var player:Int = 0; - public var texture(default, set):String = null; + public var texture(default, set):Null = null; - private function set_texture(value:String):String + private function set_texture(value:Null):Null { if (texture != value) { @@ -102,16 +103,20 @@ class StrumNote extends FlxSkewedSprite public function reloadNote() { - var lastAnim:String = null; + var lastAnim:Null = null; if (animation.curAnim != null) lastAnim = animation.curAnim.name; if (PlayState.isPixelStage.priorityBool(usePixelTextures)) { - loadGraphic(Paths.image('pixelUI/' + texture)); + var pixelImg = Paths.image('pixelUI/' + (texture != null ? texture : '')); + if (pixelImg != null) + loadGraphic(pixelImg); width = width / 4; height = height / 5; - loadGraphic(Paths.image('pixelUI/' + texture), true, Math.floor(width), Math.floor(height)); + pixelImg = Paths.image('pixelUI/' + (texture != null ? texture : '')); + if (pixelImg != null) + loadGraphic(pixelImg, true, Math.floor(width), Math.floor(height)); antialiasing = false; setGraphicSize(Std.int(width * PlayState.daPixelZoom)); @@ -142,7 +147,9 @@ class StrumNote extends FlxSkewedSprite } else { - frames = Paths.getSparrowAtlas(texture); + var sparrowFrames = Paths.getSparrowAtlas(texture != null ? texture : ''); + if (sparrowFrames != null) + frames = sparrowFrames; animation.addByPrefix('green', 'arrowUP'); animation.addByPrefix('blue', 'arrowDOWN'); animation.addByPrefix('purple', 'arrowLEFT'); @@ -214,17 +221,23 @@ class StrumNote extends FlxSkewedSprite { if (animation.curAnim == null || animation.curAnim.name == 'static') { - colorSwap.hue = 0; - colorSwap.saturation = 0; - colorSwap.brightness = 0; + if (colorSwap != null) + { + colorSwap.hue = 0; + colorSwap.saturation = 0; + colorSwap.brightness = 0; + } } else { if (noteData > -1 && noteData < ClientPrefs.data.arrowHSV.length) { - colorSwap.hue = ClientPrefs.data.arrowHSV[noteData][0] / 360; - colorSwap.saturation = ClientPrefs.data.arrowHSV[noteData][1] / 100; - colorSwap.brightness = ClientPrefs.data.arrowHSV[noteData][2] / 100; + if (colorSwap != null) + { + colorSwap.hue = ClientPrefs.data.arrowHSV[noteData][0] / 360; + colorSwap.saturation = ClientPrefs.data.arrowHSV[noteData][1] / 100; + colorSwap.brightness = ClientPrefs.data.arrowHSV[noteData][2] / 100; + } } if (animation.curAnim != null) @@ -234,7 +247,7 @@ class StrumNote extends FlxSkewedSprite } } } - else if (useRGBShader) + else if (useRGBShader && rgbShader != null) rgbShader.enabled = (animation.curAnim != null && animation.curAnim.name != 'static'); } diff --git a/source/engine/objects/SustainSplash.hx b/source/engine/objects/SustainSplash.hx index 895929d6..5e7dd437 100644 --- a/source/engine/objects/SustainSplash.hx +++ b/source/engine/objects/SustainSplash.hx @@ -2,38 +2,40 @@ package objects; +import flixel.graphics.frames.FlxAtlasFrames; import shaders.ColorSwap; import shaders.RGBPalette; import shaders.PixelSplashShader.PixelSplashShaderRef; using backend.CoolUtil; +@:nullSafety class SustainSplash extends FlxSprite { public static var DEFAULT_TEXTURE(get, never):String; - public static var startCrochet:Float; - public static var frameRate:Int; - public static var mainGroup:FlxTypedGroup; + public static var startCrochet:Float = 0; + public static var frameRate:Int = 0; + public static var mainGroup:Null> = null; @:isVar - public static var texture(get, set):String = null; + public static var texture(get, set):Null = null; public static var useRGBShader:Bool = true; public static var usePixelTextures(default, set):Null; public static var noRGBTextures(default, null):Array = []; - public static var playerTexture:String = null; - public static var opponentTexture:String = null; + public static var playerTexture:Null = null; + public static var opponentTexture:Null = null; - public var strumNote(default, set):StrumNote; - public var noteData(default, null):Int; - public var targetStrumTime(default, null):Float; + public var strumNote(default, set):Null = null; + public var noteData(default, null):Int = 0; + public var targetStrumTime(default, null):Float = 0; public var mustPress(default, null):Bool = true; - public var colorSwap:ColorSwap; + public var colorSwap:Null = null; public var rgbShaders(default, null):Array> = [[], []]; - private var curTexture:String = null; + private var curTexture:Null = null; private var reachedEnd:Bool = false; - private var rgbShader:PixelSplashShaderRef; + private var rgbShader:Null = null; public static function init(group:FlxTypedGroup, startCrochet:Float, frameRate:Int):Void { @@ -62,14 +64,17 @@ class SustainSplash extends FlxSprite public static function generateSustainSplash(strumNote:StrumNote, targetStrumTime:Float, mustPress:Bool = true):SustainSplash { + if (SustainSplash.mainGroup == null) return new SustainSplash(); var splash:SustainSplash = SustainSplash.mainGroup.recycle(null, () -> new SustainSplash(), false, true); - splash.resetSustainSplash(strumNote, targetStrumTime, mustPress); + if (splash != null) + splash.resetSustainSplash(strumNote, targetStrumTime, mustPress); return splash; } public static function hideAtData(noteData:Int):Void { + if (SustainSplash.mainGroup == null) return; for (splash in SustainSplash.mainGroup.members) { if (splashIsValid(splash, noteData) && splash.mustPress && splash.animation.curAnim.name != 'end') @@ -79,6 +84,7 @@ class SustainSplash extends FlxSprite public static function showAtData(noteData:Int):Void { + if (SustainSplash.mainGroup == null) return; for (splash in SustainSplash.mainGroup.members) { if (splashIsValid(splash, noteData) && splash.mustPress) @@ -88,6 +94,7 @@ class SustainSplash extends FlxSprite public static function hasSplashAtData(noteData:Int, mustPess:Bool):Bool { + if (SustainSplash.mainGroup == null) return false; for (splash in SustainSplash.mainGroup.members) { if (splashIsValid(splash, noteData) && splash.mustPress == mustPess) @@ -108,7 +115,8 @@ class SustainSplash extends FlxSprite SustainSplash.frameRate = 0; SustainSplash.texture = DEFAULT_TEXTURE; SustainSplash.usePixelTextures = null; - SustainSplash.mainGroup.destroy(); + if (SustainSplash.mainGroup != null) + SustainSplash.mainGroup.destroy(); } public function resetSustainSplash(strumNote:StrumNote, targetStrumTime:Float, mustPress:Bool = true):Void @@ -148,7 +156,10 @@ class SustainSplash extends FlxSprite if (PlayState.isPixelStage.priorityBool(usePixelTextures)) texture = 'pixelUI/' + texture; - frames = Paths.getSparrowAtlas(texture); + var tex:String = Std.string(SustainSplash.texture); + var frameData:Null = Paths.getSparrowAtlas(tex); + if (frameData != null) + frames = frameData; animation.onFinish.add((name:String) -> { switch (name) @@ -208,7 +219,9 @@ class SustainSplash extends FlxSprite rgbShader = rgbShaders[shaderID][noteData]; shader = rgbShader.shader; - rgbShader.copyValues(useRGBShader ? Note.initializeGlobalRGBShader(noteData) : null); + var tempShader = useRGBShader ? Note.initializeGlobalRGBShader(noteData) : null; + if (tempShader != null) + rgbShader.copyValues(tempShader); } } } @@ -242,10 +255,13 @@ class SustainSplash extends FlxSprite private static function getTextureNameFromData(noteData:Int, mustPress:Bool):String { - var tex:String = mustPress ? playerTexture : opponentTexture; + var tex:Null = mustPress ? playerTexture : opponentTexture; if (tex == null) tex = texture; + if (tex == null) + tex = DEFAULT_TEXTURE; + if (!useRGBShader || ClientPrefs.data.disableRGBNotes) { return switch (noteData) @@ -312,16 +328,19 @@ class SustainSplash extends FlxSprite } @:noCompletion - private static function set_texture(value:String):String + private static function set_texture(value:Null):Null { #if !haxe5 @:bypassAccessor #end texture = value; - for (splash in SustainSplash.mainGroup.members) - if (splash.exists && splash.alive) - splash.reloadSustainSplash(getTextureNameFromData(splash.noteData, splash.mustPress), true); + if (SustainSplash.mainGroup != null) + { + for (splash in SustainSplash.mainGroup.members) + if (splash.exists && splash.alive) + splash.reloadSustainSplash(getTextureNameFromData(splash.noteData, splash.mustPress), true); + } return value; } @@ -336,9 +355,12 @@ class SustainSplash extends FlxSprite #end usePixelTextures = value; - for (splash in SustainSplash.mainGroup.members) - if (splash.exists && splash.alive) - splash.reloadSustainSplash(getTextureNameFromData(splash.noteData, splash.mustPress), true); + if (SustainSplash.mainGroup != null) + { + for (splash in SustainSplash.mainGroup.members) + if (splash.exists && splash.alive) + splash.reloadSustainSplash(getTextureNameFromData(splash.noteData, splash.mustPress), true); + } } return value; @@ -349,7 +371,7 @@ class SustainSplash extends FlxSprite return texture ?? DEFAULT_TEXTURE; @:noCompletion - private function set_strumNote(value:StrumNote):StrumNote + private function set_strumNote(value:Null):Null { if (strumNote != null) { diff --git a/source/engine/objects/TypedAlphabet.hx b/source/engine/objects/TypedAlphabet.hx index faedbb11..747a8714 100644 --- a/source/engine/objects/TypedAlphabet.hx +++ b/source/engine/objects/TypedAlphabet.hx @@ -1,8 +1,9 @@ package objects; +@:nullSafety class TypedAlphabet extends Alphabet { - public var onFinish:Void->Void = null; + public var onFinish:NullVoid> = null; public var finishedText:Bool = false; public var delay:Float = 0.05; public var sound:String = 'dialogue'; @@ -12,7 +13,7 @@ class TypedAlphabet extends Alphabet { super(x, y, text, bold); - this.delay = delay; + this.delay = (delay != null) ? delay : 0.05; } override private function set_text(newText:String) @@ -37,7 +38,9 @@ class TypedAlphabet extends Alphabet showCharacterUpTo(_curLetter + 1); if (!playedSound && sound != '' && (delay > 0.025 || _curLetter % 2 == 0)) { - FlxG.sound.play(Paths.sound(sound), volume); + var soundToPlay = Paths.sound(sound); + if (soundToPlay != null) + FlxG.sound.play(soundToPlay, volume); } playedSound = true; @@ -88,7 +91,11 @@ class TypedAlphabet extends Alphabet showCharacterUpTo(letters.length - 1); if (sound != '') - FlxG.sound.play(Paths.sound(sound), volume); + { + var soundToPlay = Paths.sound(sound); + if (soundToPlay != null) + FlxG.sound.play(soundToPlay, volume); + } finishedText = true; if (onFinish != null) diff --git a/source/engine/objects/VideoSprite.hx b/source/engine/objects/VideoSprite.hx index 0f645751..153bb40c 100644 --- a/source/engine/objects/VideoSprite.hx +++ b/source/engine/objects/VideoSprite.hx @@ -5,21 +5,22 @@ import flixel.addons.display.FlxPieDial; import hxvlc.flixel.FlxVideoSprite; #end +@:nullSafety class VideoSprite extends FlxSpriteGroup { #if FEATURE_VIDEOS - public var finishCallback:Void->Void = null; - public var onSkip:Void->Void = null; + public var finishCallback:NullVoid> = null; + public var onSkip:NullVoid> = null; final _timeToSkip:Float = 1; public var holdingTime:Float = 0; - public var videoSprite:FlxVideoSprite; - public var skipSprite:FlxPieDial; - public var cover:FlxSprite; + public var videoSprite:Null = null; + public var skipSprite:Null = null; + public var cover:Null = null; public var canSkip(default, set):Bool = false; - private var videoName:String; + private var videoName:String = ''; public var waiting:Bool = false; @@ -49,26 +50,35 @@ class VideoSprite extends FlxSpriteGroup this.canSkip = true; // callbacks - if (!shouldLoop) - videoSprite.bitmap.onEndReached.add(finishVideo); + var vs = videoSprite; + var vsBitmap = (vs != null) ? vs.bitmap : null; + if (!shouldLoop && vsBitmap != null) + vsBitmap.onEndReached.add(finishVideo); - videoSprite.bitmap.onFormatSetup.add(function() + if (vsBitmap != null) { - /* - #if hxvlc - var wd:Int = videoSprite.bitmap.formatWidth; - var hg:Int = videoSprite.bitmap.formatHeight; - trace('Video Resolution: ${wd}x${hg}'); - videoSprite.scale.set(FlxG.width / wd, FlxG.height / hg); - #end - */ - videoSprite.setGraphicSize(FlxG.width); - videoSprite.updateHitbox(); - videoSprite.screenCenter(); - }); - - // start video and adjust resolution to screen size - videoSprite.load(videoName, shouldLoop ? ['input-repeat=65545'] : null); + vsBitmap.onFormatSetup.add(function() + { + /* + #if hxvlc + var wd:Int = vsBitmap.formatWidth; + var hg:Int = vsBitmap.formatHeight; + trace('Video Resolution: ${wd}x${hg}'); + vs.scale.set(FlxG.width / wd, FlxG.height / hg); + #end + */ + if (vs != null) + { + vs.setGraphicSize(FlxG.width); + vs.updateHitbox(); + vs.screenCenter(); + } + }); + + // start video and adjust resolution to screen size + if (vs != null) + vs.load(videoName, shouldLoop ? ['input-repeat=65545'] : null); + } } var alreadyDestroyed:Bool = false; @@ -115,7 +125,16 @@ class VideoSprite extends FlxSpriteGroup { if (canSkip) { - if (Controls.instance.pressed('accept') || mobile.backend.TouchUtil.pressed) + var controlsPressed = false; + if (Controls.instance != null) + { + if (Controls.instance.pressed('accept')) + controlsPressed = true; + } + if (mobile.backend.TouchUtil.pressed) + controlsPressed = true; + + if (controlsPressed) { holdingTime = Math.max(0, Math.min(_timeToSkip, holdingTime + elapsed)); } @@ -130,7 +149,10 @@ class VideoSprite extends FlxSpriteGroup if (onSkip != null) onSkip(); finishCallback = null; - videoSprite.bitmap.onEndReached.dispatch(); + var vs = videoSprite; + var vsBitmap = (vs != null) ? vs.bitmap : null; + if (vsBitmap != null) + vsBitmap.onEndReached.dispatch(); //trace('Skipped video'); return; } diff --git a/source/engine/options/Option.hx b/source/engine/options/Option.hx index 713ce973..648ebb9f 100644 --- a/source/engine/options/Option.hx +++ b/source/engine/options/Option.hx @@ -6,35 +6,35 @@ typedef Keybind = gamepad:String } +@:nullSafety class Option { - public var child:Alphabet; + public var child:Null = null; public var text(get, set):String; - public var onChange:Void->Void = null; // Pressed enter (on Bool type options) or pressed/held left/right (on other types) + private var _text:String = ''; + public var onChange:NullVoid> = null; - public var type(get, default):String = 'bool'; // bool, int (or integer), float (or fl), percent, string (or str), keybind (or key) + public var type(get, default):String = 'bool'; - // Bool will use checkboxes - // Everything else will use a text - public var scrollSpeed:Float = 50; // Only works on int/float, defines how fast it scrolls per second while holding left/right + public var scrollSpeed:Float = 50; - private var variable:String = null; // Variable from ClientPrefs.hx + private var variable:Null = null; public var defaultValue:Dynamic = null; - public var curOption:Int = 0; // Don't change this - public var options:Array = null; // Only used in string type - public var changeValue:Dynamic = 1; // Only used in int/float/percent type, how much is changed when you PRESS - public var minValue:Dynamic = null; // Only used in int/float/percent type - public var maxValue:Dynamic = null; // Only used in int/float/percent type - public var decimals:Int = 1; // Only used in float/percent type + public var curOption:Int = 0; + public var options:Null> = null; + public var changeValue:Dynamic = 1; + public var minValue:Dynamic = null; + public var maxValue:Dynamic = null; + public var decimals:Int = 1; - public var displayFormat:String = '%v'; // How String/Float/Percent/Int values are shown, %v = Current value, %d = Default value + public var displayFormat:String = '%v'; public var description:String = ''; public var name:String = 'Unknown'; - public var defaultKeys:Keybind = null; // Only used in keybind type - public var keys:Keybind = null; // Only used in keybind type + public var defaultKeys:Null = null; + public var keys:Null = null; public function new(name:String, description:String = '', variable:String, type:String = 'bool', ?options:Array = null) { @@ -66,7 +66,7 @@ class Option case 'string': if (defaultValue == null) defaultValue = ''; - if (options.length > 0) + if (options != null && options.length > 0) { defaultValue = options[0]; } @@ -87,10 +87,13 @@ class Option switch (type) { case 'string': - var num:Int = options.indexOf(getValue()); - if (num > -1) + if (options != null) { - curOption = num; + var num:Int = options.indexOf(getValue()); + if (num > -1) + { + curOption = num; + } } } } @@ -108,9 +111,13 @@ class Option dynamic public function getValue():Dynamic { - var value = Reflect.getProperty(ClientPrefs.data, variable); + var varName:String = (variable != null) ? variable : ''; + var value = Reflect.getProperty(ClientPrefs.data, varName); if (type == 'keybind') - return !Controls.instance.controllerMode ? value.keyboard : value.gamepad; + { + var isControllerMode:Bool = (Controls.instance != null && Controls.instance.controllerMode); + return !isControllerMode ? value.keyboard : value.gamepad; + } return value; } @@ -118,32 +125,36 @@ class Option { if (type == 'keybind') { - var keys = Reflect.getProperty(ClientPrefs.data, variable); - if (!Controls.instance.controllerMode) + var varName:String = (variable != null) ? variable : ''; + var keys = Reflect.getProperty(ClientPrefs.data, varName); + var isControllerMode:Bool = (Controls.instance != null && Controls.instance.controllerMode); + if (!isControllerMode) keys.keyboard = value; else keys.gamepad = value; return value; } - return Reflect.setProperty(ClientPrefs.data, variable, value); + var varName:String = (variable != null) ? variable : ''; + return Reflect.setProperty(ClientPrefs.data, varName, value); } - private function get_text() + private function get_text():String { if (child != null) { return child.text; } - return null; + return _text; } - private function set_text(newValue:String = '') + private function set_text(newValue:String):String { if (child != null) { child.text = newValue; } - return null; + _text = newValue; + return newValue; } private function get_type() diff --git a/source/engine/psychlua/Convert.hx b/source/engine/psychlua/Convert.hx index 9f2c1fe5..a2d95186 100644 --- a/source/engine/psychlua/Convert.hx +++ b/source/engine/psychlua/Convert.hx @@ -11,6 +11,7 @@ import hxluajit.Types; * * We didn't use hxluajit-wrapper because we wanted to have our functions and methods as similar as possible to linc_luajit */ +@:nullSafety class Convert { public static function addCallback(l:State, name:String, func:Dynamic) diff --git a/source/engine/psychlua/ReflectionFunctions.hx b/source/engine/psychlua/ReflectionFunctions.hx index 1aa3218c..c11cad17 100644 --- a/source/engine/psychlua/ReflectionFunctions.hx +++ b/source/engine/psychlua/ReflectionFunctions.hx @@ -6,6 +6,7 @@ import substates.GameOverSubstate; // Functions that use a high amount of Reflections, which are somewhat CPU intensive // These functions are held together by duct tape +@:nullSafety class ReflectionFunctions { static final instanceStr:Dynamic = "##PSYCHLUA_STRINGTOOBJ"; @@ -191,7 +192,7 @@ class ReflectionFunctions return; } - if (index < 0) + if (index == null || index < 0) { switch (Type.typeof(groupOrArray)) { @@ -220,11 +221,11 @@ class ReflectionFunctions funk.set("callMethod", function(funcToRun:String, ?args:Array = null) { - return callMethodFromObject(FunkinLua.getCurrentMusicState(), funcToRun, parseInstances(args)); + return callMethodFromObject(FunkinLua.getCurrentMusicState(), funcToRun, parseInstances(args ?? [])); }); funk.set("callMethodFromClass", function(className:String, funcToRun:String, ?args:Array = null) { - return callMethodFromObject(Type.resolveClass(className), funcToRun, parseInstances(args)); + return callMethodFromObject(Type.resolveClass(className), funcToRun, parseInstances(args ?? [])); }); funk.set("createInstance", function(variableToSave:String, className:String, ?args:Array = null) @@ -259,7 +260,8 @@ class ReflectionFunctions if (FunkinLua.getCurrentMusicState().variables.exists(objectName)) { var obj:Dynamic = FunkinLua.getCurrentMusicState().variables.get(objectName); - if (FunkinLua.getCurrentMusicState() is PlayState && !inFront) + var inFrontVal:Bool = inFront ?? false; + if (FunkinLua.getCurrentMusicState() is PlayState && !inFrontVal) { if (!PlayState.instance.isDead) PlayState.instance.insert(PlayState.instance.members.indexOf(LuaUtils.getLowestCharacterGroup()), obj); @@ -267,7 +269,10 @@ class ReflectionFunctions GameOverSubstate.instance.insert(GameOverSubstate.instance.members.indexOf(GameOverSubstate.instance.boyfriend), obj); } else - LuaUtils.getTargetInstance().add(obj); + { + var target = LuaUtils.getTargetInstance(); + if (target != null) target.add(obj); + } } else FunkinLua.luaTrace('addInstance: Can\'t add what doesn\'t exist~ ($objectName)', false, false, FlxColor.RED); @@ -315,7 +320,6 @@ class ReflectionFunctions args = []; var split:Array = funcStr.split('.'); - var funcToRun:Function = null; var obj:Dynamic = classObj; // trace('start: ' + obj); if (obj == null) @@ -329,7 +333,7 @@ class ReflectionFunctions // trace(obj, split[i]); } - funcToRun = cast obj; + var funcToRun:Null = cast obj; // trace('end: $obj'); return funcToRun != null ? Reflect.callMethod(obj, funcToRun, args) : null; } diff --git a/source/engine/psychlua/ShaderFunctions.hx b/source/engine/psychlua/ShaderFunctions.hx index c8d60fce..84cbd1c0 100644 --- a/source/engine/psychlua/ShaderFunctions.hx +++ b/source/engine/psychlua/ShaderFunctions.hx @@ -5,6 +5,7 @@ import openfl.filters.ShaderFilter; import flixel.addons.display.FlxRuntimeShader; #end +@:nullSafety class ShaderFunctions { #if !flash @@ -35,25 +36,26 @@ class ShaderFunctions if (index == null || index.length < 1) index = shader; - #if !flash - if (!funk.runtimeShaders.exists(shader) && !funk.initLuaShader(shader)) - { - FunkinLua.luaTrace('addShaderToCam: Shader $shader is missing!', false, false, FlxColor.RED); - return false; - } + #if !flash + if (!funk.runtimeShaders.exists(shader) && !funk.initLuaShader(shader)) + { + FunkinLua.luaTrace('addShaderToCam: Shader $shader is missing!', false, false, FlxColor.RED); + return false; + } - var arr:Array = funk.runtimeShaders.get(shader); - // Both FlxGame and FlxCamera has a _filters array and a setFilters function - // We should maybe make an interface for that? - var camera = getCam(cam); - @:privateAccess { - if (camera._filters == null) - camera._filters = []; - var filter = new ShaderFilter(new FlxRuntimeShader(arr[0], arr[1])); - storedFilters.set(index, filter); - camera._filters.push(filter); - } - return true; + var arr:Null> = funk.runtimeShaders.get(shader); + if (arr == null) return false; + // Both FlxGame and FlxCamera has a _filters array and a setFilters function + // We should maybe make an interface for that? + var camera = getCam(cam); + @:privateAccess { + if (camera._filters == null) + camera._filters = []; + var filter = new ShaderFilter(new FlxRuntimeShader(arr[0], arr[1])); + storedFilters.set(index, filter); + camera._filters.push(filter); + } + return true; #else FunkinLua.luaTrace("addShaderToCam: Platform unsupported for Runtime Shaders!", false, false, FlxColor.RED); #end @@ -102,7 +104,7 @@ class ShaderFunctions } var split:Array = obj.split('.'); - var leObj:FlxSprite = LuaUtils.getObjectDirectly(split[0]); + var leObj:Null = LuaUtils.getObjectDirectly(split[0]); if (split.length > 1) { leObj = LuaUtils.getVarInArray(LuaUtils.getPropertyLoop(split), split[split.length - 1]); @@ -110,8 +112,9 @@ class ShaderFunctions if (leObj != null) { - var arr:Array = funk.runtimeShaders.get(shader); - leObj.shader = new FlxRuntimeShader(arr[0], arr[1]); + var arr:Null> = funk.runtimeShaders.get(shader); + if (arr != null) + leObj.shader = new FlxRuntimeShader(arr[0], arr[1]); return true; } #else @@ -123,7 +126,7 @@ class ShaderFunctions funk.set("removeSpriteShader", function(obj:String) { var split:Array = obj.split('.'); - var leObj:FlxSprite = LuaUtils.getObjectDirectly(split[0]); + var leObj:Null = LuaUtils.getObjectDirectly(split[0]); if (split.length > 1) { leObj = LuaUtils.getVarInArray(LuaUtils.getPropertyLoop(split), split[split.length - 1]); @@ -131,7 +134,8 @@ class ShaderFunctions if (leObj != null) { - leObj.shader = null; + var sprite:FlxSprite = leObj; + Reflect.setProperty(sprite, 'shader', null); return true; } return false; @@ -140,7 +144,7 @@ class ShaderFunctions funk.set("getShaderBool", function(obj:String, prop:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("getShaderBool: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -156,7 +160,7 @@ class ShaderFunctions funk.set("getShaderBoolArray", function(obj:String, prop:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("getShaderBoolArray: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -171,7 +175,7 @@ class ShaderFunctions funk.set("getShaderInt", function(obj:String, prop:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("getShaderInt: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -186,7 +190,7 @@ class ShaderFunctions funk.set("getShaderIntArray", function(obj:String, prop:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("getShaderIntArray: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -201,7 +205,7 @@ class ShaderFunctions funk.set("getShaderFloat", function(obj:String, prop:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("getShaderFloat: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -216,7 +220,7 @@ class ShaderFunctions funk.set("getShaderFloatArray", function(obj:String, prop:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("getShaderFloatArray: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -232,7 +236,7 @@ class ShaderFunctions funk.set("setShaderBool", function(obj:String, prop:String, value:Bool) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderBool: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -248,7 +252,7 @@ class ShaderFunctions funk.set("setShaderBoolArray", function(obj:String, prop:String, values:Dynamic) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderBoolArray: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -264,7 +268,7 @@ class ShaderFunctions funk.set("setShaderInt", function(obj:String, prop:String, value:Int) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderInt: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -280,7 +284,7 @@ class ShaderFunctions funk.set("setShaderIntArray", function(obj:String, prop:String, values:Dynamic) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderIntArray: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -296,7 +300,7 @@ class ShaderFunctions funk.set("setShaderFloat", function(obj:String, prop:String, value:Float) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderFloat: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -312,7 +316,7 @@ class ShaderFunctions funk.set("setShaderFloatArray", function(obj:String, prop:String, values:Dynamic) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderFloatArray: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -330,7 +334,7 @@ class ShaderFunctions funk.set("setShaderSampler2D", function(obj:String, prop:String, bitmapdataPath:String) { #if !flash - var shader:FlxRuntimeShader = getShader(obj); + var shader:Null = getShader(obj); if (shader == null) { FunkinLua.luaTrace("setShaderSampler2D: Shader is not FlxRuntimeShader!", false, false, FlxColor.RED); @@ -354,13 +358,14 @@ class ShaderFunctions } #if !flash - public static function getShader(obj:String):FlxRuntimeShader + public static function getShader(obj:String):Null { - if (storedFilters.exists(obj)) - return cast(storedFilters[obj].shader, FlxRuntimeShader); + var filter = storedFilters.get(obj); + if (filter != null) + return cast(filter.shader, FlxRuntimeShader); var split:Array = obj.split('.'); - var target:FlxSprite = null; + var target:Null = null; if (split.length > 1) target = LuaUtils.getVarInArray(LuaUtils.getPropertyLoop(split), split[split.length - 1]); else diff --git a/source/engine/psychlua/TextFunctions.hx b/source/engine/psychlua/TextFunctions.hx index aaf327f1..ac629b5b 100644 --- a/source/engine/psychlua/TextFunctions.hx +++ b/source/engine/psychlua/TextFunctions.hx @@ -1,5 +1,6 @@ package psychlua; +@:nullSafety class TextFunctions { private static var game(get, never):Dynamic; @@ -23,7 +24,7 @@ class TextFunctions funk.set("setTextString", function(tag:String, text:String) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.text = text; @@ -34,7 +35,7 @@ class TextFunctions }); funk.set("setTextSize", function(tag:String, size:Int) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.size = size; @@ -45,7 +46,7 @@ class TextFunctions }); funk.set("setTextWidth", function(tag:String, width:Float) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.fieldWidth = width; @@ -56,7 +57,7 @@ class TextFunctions }); funk.set("setTextHeight", function(tag:String, height:Float) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.fieldHeight = height; @@ -67,7 +68,7 @@ class TextFunctions }); funk.set("setTextAutoSize", function(tag:String, value:Bool) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.autoSize = value; @@ -78,10 +79,11 @@ class TextFunctions }); funk.set("setTextBorder", function(tag:String, size:Float, color:String, ?style:String = 'outline') { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { - CoolUtil.setTextBorderFromString(obj, (size > 0 ? style : 'none')); + var borderStyle:String = if (style == null) 'outline' else style; + CoolUtil.setTextBorderFromString(obj, (size > 0 ? borderStyle : 'none')); if (size > 0) obj.borderSize = size; @@ -93,7 +95,7 @@ class TextFunctions }); funk.set("setTextColor", function(tag:String, color:String) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.color = CoolUtil.colorFromString(color); @@ -104,7 +106,7 @@ class TextFunctions }); funk.set("setTextFont", function(tag:String, newFont:String) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.font = Paths.font(newFont); @@ -115,7 +117,7 @@ class TextFunctions }); funk.set("setTextItalic", function(tag:String, italic:Bool) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.italic = italic; @@ -126,7 +128,7 @@ class TextFunctions }); funk.set("setTextAlignment", function(tag:String, alignment:String = 'left') { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { obj.alignment = LEFT; @@ -143,9 +145,9 @@ class TextFunctions return false; }); - funk.set("getTextString", function(tag:String) + funk.set("getTextString", function(tag:String):Null { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null && obj.text != null) { return obj.text; @@ -155,17 +157,19 @@ class TextFunctions }); funk.set("getTextSize", function(tag:String) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { - return obj.size; + var text:FlxText = obj; + var sizeValue:Dynamic = Reflect.getProperty(text, 'size'); + return Std.int(sizeValue); } FunkinLua.luaTrace("getTextSize: Object " + tag + " doesn't exist!", false, false, FlxColor.RED); return -1; }); - funk.set("getTextFont", function(tag:String) + funk.set("getTextFont", function(tag:String):Null { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { return obj.font; @@ -175,7 +179,7 @@ class TextFunctions }); funk.set("getTextWidth", function(tag:String) { - var obj:FlxText = LuaUtils.getTextObject(tag); + var obj:Null = LuaUtils.getTextObject(tag); if (obj != null) { return obj.fieldWidth; @@ -189,7 +193,8 @@ class TextFunctions if (game.modchartTexts.exists(tag)) { var shit:FlxText = game.modchartTexts.get(tag); - LuaUtils.getTargetInstance().add(shit); + var target = LuaUtils.getTargetInstance(); + if (target != null) target.add(shit); } }); funk.set("removeLuaText", function(tag:String, destroy:Bool = true) @@ -200,7 +205,8 @@ class TextFunctions } var pee:FlxText = game.modchartTexts.get(tag); - LuaUtils.getTargetInstance().remove(pee, true); + var target = LuaUtils.getTargetInstance(); + if (target != null) target.remove(pee, true); if (destroy) { pee.kill(); diff --git a/source/engine/shaders/AdjustColorShader.hx b/source/engine/shaders/AdjustColorShader.hx index ae49dfac..2c3859b9 100644 --- a/source/engine/shaders/AdjustColorShader.hx +++ b/source/engine/shaders/AdjustColorShader.hx @@ -3,12 +3,13 @@ package shaders; import lime.utils.Assets; import flixel.addons.display.FlxRuntimeShader; +@:nullSafety class AdjustColorShader extends FlxRuntimeShader { - public var hue(default, set):Float; - public var saturation(default, set):Float; - public var brightness(default, set):Float; - public var contrast(default, set):Float; + public var hue(default, set):Float = 0; + public var saturation(default, set):Float = 0; + public var brightness(default, set):Float = 0; + public var contrast(default, set):Float = 0; public function new() { diff --git a/source/engine/shaders/BlendModeEffect.hx b/source/engine/shaders/BlendModeEffect.hx index b2fd382e..77090fa8 100644 --- a/source/engine/shaders/BlendModeEffect.hx +++ b/source/engine/shaders/BlendModeEffect.hx @@ -7,6 +7,7 @@ typedef BlendModeShader = var uBlendColor:ShaderParameter; } +@:nullSafety class BlendModeEffect { public var shader(default, null):BlendModeShader; diff --git a/source/engine/shaders/ColorSwap.hx b/source/engine/shaders/ColorSwap.hx index 60cacbf2..7a34bc90 100644 --- a/source/engine/shaders/ColorSwap.hx +++ b/source/engine/shaders/ColorSwap.hx @@ -1,5 +1,6 @@ package shaders; +@:nullSafety class ColorSwap { public var shader(default, null):ColorSwapShader = new ColorSwapShader(); diff --git a/source/engine/shaders/PixelSplashShader.hx b/source/engine/shaders/PixelSplashShader.hx index 894025b7..2d555572 100644 --- a/source/engine/shaders/PixelSplashShader.hx +++ b/source/engine/shaders/PixelSplashShader.hx @@ -1,5 +1,6 @@ package shaders; +@:nullSafety class PixelSplashShaderRef { public var shader:PixelSplashShader = new PixelSplashShader(); diff --git a/source/engine/shaders/RGBPalette.hx b/source/engine/shaders/RGBPalette.hx index 178384ce..1afa70c5 100644 --- a/source/engine/shaders/RGBPalette.hx +++ b/source/engine/shaders/RGBPalette.hx @@ -2,13 +2,14 @@ package shaders; import objects.Note; +@:nullSafety class RGBPalette { public var shader(default, null):RGBPaletteShader = new RGBPaletteShader(); - public var r(default, set):FlxColor; - public var g(default, set):FlxColor; - public var b(default, set):FlxColor; - public var mult(default, set):Float; + public var r(default, set):FlxColor = FlxColor.WHITE; + public var g(default, set):FlxColor = FlxColor.WHITE; + public var b(default, set):FlxColor = FlxColor.WHITE; + public var mult(default, set):Float = 1.0; private function set_r(color:FlxColor) { diff --git a/source/engine/shaders/RuntimeCustomBlendShader.hx b/source/engine/shaders/RuntimeCustomBlendShader.hx index 38553acd..fc38e245 100644 --- a/source/engine/shaders/RuntimeCustomBlendShader.hx +++ b/source/engine/shaders/RuntimeCustomBlendShader.hx @@ -6,15 +6,15 @@ import openfl.display.BlendMode; class RuntimeCustomBlendShader extends RuntimePostEffectShader { // only different name purely for hashlink fix - public var sourceSwag(default, set):BitmapData; + public var sourceSwag(default, set):Null = null; - function set_sourceSwag(value:BitmapData):BitmapData + function set_sourceSwag(value:Null):Null { this.setBitmapData("sourceSwag", value); return sourceSwag = value; } - public var backgroundSwag(default, set):BitmapData; + public var backgroundSwag(default, set):Null = null; function set_backgroundSwag(value:BitmapData):BitmapData { diff --git a/source/engine/shaders/WiggleEffect.hx b/source/engine/shaders/WiggleEffect.hx index b4ef364b..5466ba2c 100644 --- a/source/engine/shaders/WiggleEffect.hx +++ b/source/engine/shaders/WiggleEffect.hx @@ -10,6 +10,7 @@ enum WiggleEffectType FLAG; } +@:nullSafety class WiggleEffect { public var shader(default, null):WiggleShader = new WiggleShader(); diff --git a/source/haxe_std_shadows/haxe/format/JsonParser.hx b/source/haxe_std_shadows/haxe/format/JsonParser.hx index 476739e0..1710f178 100644 --- a/source/haxe_std_shadows/haxe/format/JsonParser.hx +++ b/source/haxe_std_shadows/haxe/format/JsonParser.hx @@ -48,10 +48,10 @@ class JsonParser } var str:String; - var file:String; + var file:Null; var pos:Int; - function new(str:String, file:String) + function new(str:String, ?file:String) { this.str = str; this.file = file; From 909b8d2ce0beec09f2b368e1f9e7e70f5b2d7d01 Mon Sep 17 00:00:00 2001 From: Homura Date: Wed, 25 Mar 2026 22:31:05 +0300 Subject: [PATCH 02/24] more clanking --- source/engine/backend/Controls.hx | 49 ++- source/engine/backend/Main.hx | 3 +- source/engine/backend/MusicBeatState.hx | 44 ++- source/engine/backend/MusicBeatSubstate.hx | 42 ++- source/engine/cutscenes/CutsceneHandler.hx | 41 ++- source/engine/cutscenes/DialogueBox.hx | 1 + source/engine/cutscenes/DialogueBoxPsych.hx | 317 +++++++++++------- source/engine/cutscenes/DialogueCharacter.hx | 61 ++-- source/engine/debug/codename/Framerate.hx | 60 ++-- .../debug/codename/FramerateCategory.hx | 8 +- .../engine/debug/codename/FramerateCounter.hx | 1 + source/engine/debug/codename/MemoryCounter.hx | 1 + source/engine/debug/codename/SystemInfo.hx | 8 +- source/engine/mobile/backend/MobileData.hx | 1 + source/engine/mobile/backend/StorageUtil.hx | 1 + source/engine/mobile/backend/TouchUtil.hx | 1 + source/engine/mobile/input/MobileInputID.hx | 1 + .../engine/mobile/input/MobileInputManager.hx | 1 + source/engine/mobile/objects/Hitbox.hx | 1 + .../engine/mobile/objects/IMobileControls.hx | 1 + .../engine/mobile/objects/MobileControls.hx | 1 + source/engine/mobile/objects/TouchButton.hx | 5 + source/engine/mobile/objects/TouchPad.hx | 1 + .../mobile/options/MobileOptionsSubState.hx | 6 +- source/engine/mobile/psychlua/Functions.hx | 116 ++++--- .../substates/MobileControlSelectSubState.hx | 1 + source/engine/objects/AttachedSprite.hx | 2 +- source/engine/objects/AttachedText.hx | 2 +- source/engine/objects/MusicPlayer.hx | 142 +++++--- 29 files changed, 593 insertions(+), 326 deletions(-) diff --git a/source/engine/backend/Controls.hx b/source/engine/backend/Controls.hx index 37717222..2ac4884f 100644 --- a/source/engine/backend/Controls.hx +++ b/source/engine/backend/Controls.hx @@ -156,9 +156,18 @@ class Controls if (gpBind != null) gpResult = _myGamepadJustPressed(gpBind) == true; - return keyboardResult || gpResult - #if FEATURE_MOBILE_CONTROLS || mobileCJustPressed(mobileBinds[key]) == true - || touchPadJustPressed(mobileBinds[key]) == true #end; + #if FEATURE_MOBILE_CONTROLS + var mobileBind:Null> = mobileBinds[key]; + var mobileResult = false; + if (mobileBind != null) + { + var keys = mobileBind; + mobileResult = mobileCJustPressed(keys) == true || touchPadJustPressed(keys) == true; + } + #else + var mobileResult = false; + #end + return keyboardResult || gpResult || mobileResult; } public function pressed(key:String) @@ -175,9 +184,18 @@ class Controls if (gpBind != null) gpResult = _myGamepadPressed(gpBind) == true; - return keyboardResult || gpResult - #if FEATURE_MOBILE_CONTROLS || mobileCPressed(mobileBinds[key]) == true - || touchPadPressed(mobileBinds[key]) == true #end; + #if FEATURE_MOBILE_CONTROLS + var mobileBind:Null> = mobileBinds[key]; + var mobileResult = false; + if (mobileBind != null) + { + var keys = mobileBind; + mobileResult = mobileCPressed(keys) == true || touchPadPressed(keys) == true; + } + #else + var mobileResult = false; + #end + return keyboardResult || gpResult || mobileResult; } public function justReleased(key:String) @@ -194,9 +212,18 @@ class Controls if (gpBind != null) gpResult = _myGamepadJustReleased(gpBind) == true; - return keyboardResult || gpResult - #if FEATURE_MOBILE_CONTROLS || mobileCJustReleased(mobileBinds[key]) == true - || touchPadJustReleased(mobileBinds[key]) == true #end; + #if FEATURE_MOBILE_CONTROLS + var mobileBind:Null> = mobileBinds[key]; + var mobileResult = false; + if (mobileBind != null) + { + var keys = mobileBind; + mobileResult = mobileCJustReleased(keys) == true || touchPadJustReleased(keys) == true; + } + #else + var mobileResult = false; + #end + return keyboardResult || gpResult || mobileResult; } public var controllerMode:Bool = false; @@ -251,8 +278,8 @@ class Controls #if FEATURE_MOBILE_CONTROLS public var isInSubstate:Bool = false; // don't worry about this it becomes true and false on it's own in MusicBeatSubstate - public var requestedInstance(get, default):Dynamic; // is set to MusicBeatState or MusicBeatSubstate when the constructor is called - public var requestedMobileC(get, default):IMobileControls; // for PlayState and EditorPlayState (hitbox and touchPad) + public var requestedInstance(get, default):Null = null; // is set to MusicBeatState or MusicBeatSubstate when the constructor is called + public var requestedMobileC(get, default):Null = null; // for PlayState and EditorPlayState (hitbox and touchPad) public var mobileC(get, never):Bool; private function touchPadPressed(keys:Array):Bool diff --git a/source/engine/backend/Main.hx b/source/engine/backend/Main.hx index 5af9b38e..837cff80 100644 --- a/source/engine/backend/Main.hx +++ b/source/engine/backend/Main.hx @@ -165,7 +165,8 @@ class Main extends Sprite static function resetSpriteCache(sprite:Sprite):Void { - @:privateAccess @:nullSafety(Off) + @:nullSafety(Off) + @:privateAccess { sprite.__cacheBitmap = null; sprite.__cacheBitmapData = null; diff --git a/source/engine/backend/MusicBeatState.hx b/source/engine/backend/MusicBeatState.hx index 8459d218..78c5ce9c 100644 --- a/source/engine/backend/MusicBeatState.hx +++ b/source/engine/backend/MusicBeatState.hx @@ -136,7 +136,7 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState public function makeLuaTouchPad(DPadMode:String, ActionMode:String) { - if (members.contains(luaTouchPad)) + if (luaTouchPad != null && members.contains(luaTouchPad)) return; if (!variables.exists("luaTouchPad")) @@ -152,6 +152,8 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState return; var target = LuaUtils.getTargetInstance(); + if (target == null) + return; target.insert(target.members.length + 1, luaTouchPad); } @@ -182,13 +184,15 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonPressed(MobileInputID.fromString(button)); + { + return luaTouchPad.buttonPressed(cast MobileInputID.fromString(button)); + } else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; // haxe said "You Can't Iterate On A Dyanmic Value Please Specificy Iterator or Iterable *insert nerd emoji*" so that's the only i found to fix + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyPressed(idArray); } else @@ -202,13 +206,15 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonJustPressed(MobileInputID.fromString(button)); + { + return luaTouchPad.buttonJustPressed(cast MobileInputID.fromString(button)); + } else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyJustPressed(idArray); } else @@ -222,13 +228,15 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonJustReleased(MobileInputID.fromString(button)); + { + return luaTouchPad.buttonJustReleased(cast MobileInputID.fromString(button)); + } else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyJustReleased(idArray); } else @@ -242,13 +250,15 @@ class MusicBeatState extends FlxTransitionableState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonJustReleased(MobileInputID.fromString(button)); + { + return luaTouchPad.buttonReleased(cast MobileInputID.fromString(button)); + } else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyReleased(idArray); } else diff --git a/source/engine/backend/MusicBeatSubstate.hx b/source/engine/backend/MusicBeatSubstate.hx index 8e1595b1..6ba2053c 100644 --- a/source/engine/backend/MusicBeatSubstate.hx +++ b/source/engine/backend/MusicBeatSubstate.hx @@ -136,7 +136,7 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState public function makeLuaTouchPad(DPadMode:String, ActionMode:String) { - if (members.contains(luaTouchPad)) + if (luaTouchPad != null && members.contains(luaTouchPad)) return; if (!variables.exists("luaTouchPad")) @@ -152,6 +152,8 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState return; var target = LuaUtils.getTargetInstance(); + if (target == null) + return; target.insert(target.members.length + 1, luaTouchPad); } @@ -177,18 +179,18 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState } } - public function luaTouchPadPressed(button:Dynamic):Bool +public function luaTouchPadPressed(button:Dynamic):Bool { if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonPressed(MobileInputID.fromString(button)); + return luaTouchPad.buttonPressed(cast MobileInputID.fromString(button)); else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; // haxe said "You Can't Iterate On A Dyanmic Value Please Specificy Iterator or Iterable *insert nerd emoji*" so that's the only i found to fix + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyPressed(idArray); } else @@ -202,13 +204,13 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonJustPressed(MobileInputID.fromString(button)); + return luaTouchPad.buttonJustPressed(cast MobileInputID.fromString(button)); else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyJustPressed(idArray); } else @@ -222,13 +224,15 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonJustReleased(MobileInputID.fromString(button)); + { + return luaTouchPad.buttonJustReleased(cast MobileInputID.fromString(button)); + } else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyJustReleased(idArray); } else @@ -242,13 +246,15 @@ class MusicBeatSubstate extends FlxSubState implements IMusicState if (luaTouchPad != null) { if (Std.isOfType(button, String)) - return luaTouchPad.buttonJustReleased(MobileInputID.fromString(button)); + { + return luaTouchPad.buttonReleased(cast MobileInputID.fromString(button)); + } else if (Std.isOfType(button, Array)) { - var FUCK:Array = button; + var fuck:Array = button; var idArray:Array = []; - for (strId in FUCK) - idArray.push(MobileInputID.fromString(strId)); + for (strId in fuck) + idArray.push(cast MobileInputID.fromString(strId)); return luaTouchPad.anyReleased(idArray); } else diff --git a/source/engine/cutscenes/CutsceneHandler.hx b/source/engine/cutscenes/CutsceneHandler.hx index b1011e9b..fcd6b402 100644 --- a/source/engine/cutscenes/CutsceneHandler.hx +++ b/source/engine/cutscenes/CutsceneHandler.hx @@ -3,15 +3,16 @@ package cutscenes; import flixel.FlxBasic; import flixel.util.FlxSort; +@:nullSafety class CutsceneHandler extends FlxBasic { public var timedEvents:Array = []; - public var finishCallback:Void->Void = null; - public var finishCallback2:Void->Void = null; - public var onStart:Void->Void = null; + public var finishCallback:NullVoid> = null; + public var finishCallback2:NullVoid> = null; + public var onStart:NullVoid> = null; public var endTime:Float = 0; public var objects:Array = []; - public var music:String = null; + public var music:Null = null; public function new() { @@ -21,13 +22,19 @@ class CutsceneHandler extends FlxBasic { if (music != null) { - FlxG.sound.playMusic(Paths.music(music), 0, false); - FlxG.sound.music.fadeIn(); + var musicPath = Paths.music(music); + if (musicPath != null) + FlxG.sound.playMusic(musicPath, 0, false); + var musicSound = FlxG.sound.music; + if (musicSound != null) + musicSound.fadeIn(); } if (onStart != null) onStart(); }); - PlayState.instance.add(this); + var playState = PlayState.instance; + if (playState != null) + playState.add(this); } private var cutsceneTime:Float = 0; @@ -37,7 +44,8 @@ class CutsceneHandler extends FlxBasic { super.update(elapsed); - if (FlxG.state != PlayState.instance || !firstFrame) + var playState = PlayState.instance; + if (FlxG.state != playState || !firstFrame) { firstFrame = true; return; @@ -46,25 +54,34 @@ class CutsceneHandler extends FlxBasic cutsceneTime += elapsed; if (endTime <= cutsceneTime) { - finishCallback(); + if (finishCallback != null) + finishCallback(); if (finishCallback2 != null) finishCallback2(); for (spr in objects) { - PlayState.instance.remove(spr); + var pState = PlayState.instance; + if (pState != null) + pState.remove(spr); spr.kill(); spr.destroy(); } kill(); destroy(); - PlayState.instance.remove(this); + if (playState != null) + playState.remove(this); } while (timedEvents.length > 0 && timedEvents[0][0] <= cutsceneTime) { - timedEvents[0][1](); + var event:Array = timedEvents[0]; + if (event != null && event[1] != null) + { + var func:Void->Void = cast event[1]; + func(); + } timedEvents.shift(); } } diff --git a/source/engine/cutscenes/DialogueBox.hx b/source/engine/cutscenes/DialogueBox.hx index e16a6aae..42a6470d 100644 --- a/source/engine/cutscenes/DialogueBox.hx +++ b/source/engine/cutscenes/DialogueBox.hx @@ -2,6 +2,7 @@ package cutscenes; import flixel.addons.text.FlxTypeText; +@:nullSafety class DialogueBox extends FlxSpriteGroup { var box:FlxSprite; diff --git a/source/engine/cutscenes/DialogueBoxPsych.hx b/source/engine/cutscenes/DialogueBoxPsych.hx index 53a8f202..4085ce51 100644 --- a/source/engine/cutscenes/DialogueBoxPsych.hx +++ b/source/engine/cutscenes/DialogueBoxPsych.hx @@ -22,6 +22,7 @@ typedef DialogueLine = } // TO DO: Clean code? Maybe? idk +@:nullSafety class DialogueBoxPsych extends FlxSpriteGroup { public static var DEFAULT_TEXT_X = 175; @@ -30,15 +31,15 @@ class DialogueBoxPsych extends FlxSpriteGroup var scrollSpeed = 4000; - var dialogue:TypedAlphabet; - var dialogueList:DialogueFile = null; + var dialogue:Null = null; + var dialogueList:Null = null; - public var finishThing:Void->Void; - public var nextDialogueThing:Void->Void = null; - public var skipDialogueThing:Void->Void = null; + public var finishThing:NullVoid> = null; + public var nextDialogueThing:NullVoid> = null; + public var skipDialogueThing:NullVoid> = null; - var bgFade:FlxSprite = null; - var box:FlxSprite; + var bgFade:Null = null; + var box:Null = null; var textToType:String = ''; var arrayCharacters:Array = []; @@ -62,40 +63,55 @@ class DialogueBoxPsych extends FlxSpriteGroup if (song != null && song != '') { - FlxG.sound.playMusic(Paths.music(song), 0); - FlxG.sound.music.fadeIn(2, 0, 1); + var musicPath = Paths.music(song); + if (musicPath != null) + FlxG.sound.playMusic(musicPath, 0); + var music = FlxG.sound.music; + if (music != null) + music.fadeIn(2, 0, 1); } bgFade = new FlxSprite(-500, -500).makeGraphic(FlxG.width * 2, FlxG.height * 2, FlxColor.WHITE); - bgFade.scrollFactor.set(); - bgFade.visible = true; - bgFade.alpha = 0; - add(bgFade); + if (bgFade != null) + { + bgFade.scrollFactor.set(); + bgFade.visible = true; + bgFade.alpha = 0; + add(bgFade); + } this.dialogueList = dialogueList; spawnCharacters(); box = new FlxSprite(70, 370); - box.antialiasing = ClientPrefs.data.antialiasing; - box.frames = Paths.getSparrowAtlas('speech_bubble'); - box.scrollFactor.set(); - box.animation.addByPrefix('normal', 'speech bubble normal', 24); - box.animation.addByPrefix('normalOpen', 'Speech Bubble Normal Open', 24, false); - box.animation.addByPrefix('angry', 'AHH speech bubble', 24); - box.animation.addByPrefix('angryOpen', 'speech bubble loud open', 24, false); - box.animation.addByPrefix('center-normal', 'speech bubble middle', 24); - box.animation.addByPrefix('center-normalOpen', 'Speech Bubble Middle Open', 24, false); - box.animation.addByPrefix('center-angry', 'AHH Speech Bubble middle', 24); - box.animation.addByPrefix('center-angryOpen', 'speech bubble Middle loud open', 24, false); - box.animation.play('normal', true); - box.visible = false; - box.setGraphicSize(Std.int(box.width * 0.9)); - box.updateHitbox(); - add(box); + if (box != null) + { + box.antialiasing = ClientPrefs.data.antialiasing; + var boxAtlas = Paths.getSparrowAtlas('speech_bubble'); + if (boxAtlas != null) + box.frames = boxAtlas; + box.scrollFactor.set(); + box.animation.addByPrefix('normal', 'speech bubble normal', 24); + box.animation.addByPrefix('normalOpen', 'Speech Bubble Normal Open', 24, false); + box.animation.addByPrefix('angry', 'AHH speech bubble', 24); + box.animation.addByPrefix('angryOpen', 'speech bubble loud open', 24, false); + box.animation.addByPrefix('center-normal', 'speech bubble middle', 24); + box.animation.addByPrefix('center-normalOpen', 'Speech Bubble Middle Open', 24, false); + box.animation.addByPrefix('center-angry', 'AHH Speech Bubble middle', 24); + box.animation.addByPrefix('center-angryOpen', 'speech bubble Middle loud open', 24, false); + box.animation.play('normal', true); + box.visible = false; + box.setGraphicSize(Std.int(box.width * 0.9)); + box.updateHitbox(); + add(box); + } daText = new TypedAlphabet(DEFAULT_TEXT_X, DEFAULT_TEXT_Y, ''); - daText.setScale(0.7); - add(daText); + if (daText != null) + { + daText.setScale(0.7); + add(daText); + } startNextDialog(); } @@ -109,13 +125,14 @@ class DialogueBoxPsych extends FlxSpriteGroup function spawnCharacters() { + if (dialogueList == null) return; var charsMap:Map = new Map(); for (i in 0...dialogueList.dialogue.length) { if (dialogueList.dialogue[i] != null) { - var charToAdd:String = dialogueList.dialogue[i].portrait; - if (!charsMap.exists(charToAdd) || !charsMap.get(charToAdd)) + var charToAdd:Null = dialogueList.dialogue[i].portrait; + if (charToAdd != null && (!charsMap.exists(charToAdd) || charsMap.get(charToAdd) != true)) { charsMap.set(charToAdd, true); } @@ -127,35 +144,42 @@ class DialogueBoxPsych extends FlxSpriteGroup var x:Float = LEFT_CHAR_X; var y:Float = DEFAULT_CHAR_Y; var char:DialogueCharacter = new DialogueCharacter(x + offsetPos, y, individualChar); - char.setGraphicSize(Std.int(char.width * DialogueCharacter.DEFAULT_SCALE * char.jsonFile.scale)); - char.updateHitbox(); - char.scrollFactor.set(); - char.alpha = 0.00001; - add(char); - - var saveY:Bool = false; - switch (char.jsonFile.dialogue_pos) + var jsonFile = char.jsonFile; + if (jsonFile != null) { - case 'center': - char.x = FlxG.width / 2; - char.x -= char.width / 2; - y = char.y; - char.y = FlxG.height + 50; - saveY = true; - case 'right': - x = FlxG.width - char.width + RIGHT_CHAR_X; - char.x = x - offsetPos; + char.setGraphicSize(Std.int(char.width * DialogueCharacter.DEFAULT_SCALE * jsonFile.scale)); + char.updateHitbox(); + char.scrollFactor.set(); + char.alpha = 0.00001; + add(char); + + var saveY:Bool = false; + switch (jsonFile.dialogue_pos) + { + case 'center': + char.x = FlxG.width / 2; + char.x -= char.width / 2; + y = char.y; + char.y = FlxG.height + 50; + saveY = true; + case 'right': + x = FlxG.width - char.width + RIGHT_CHAR_X; + char.x = x - offsetPos; + } + if (jsonFile.position != null && jsonFile.position.length >= 2) + { + x += jsonFile.position[0]; + y += jsonFile.position[1]; + char.x += jsonFile.position[0]; + char.y += jsonFile.position[1]; + } + char.startingPos = (saveY ? y : x); } - x += char.jsonFile.position[0]; - y += char.jsonFile.position[1]; - char.x += char.jsonFile.position[0]; - char.y += char.jsonFile.position[1]; - char.startingPos = (saveY ? y : x); arrayCharacters.push(char); } } - var daText:TypedAlphabet = null; + var daText:Null = null; var ignoreThisFrame:Bool = true; // First frame is reserved for loading dialogue images public var closeSound:String = 'dialogueClose'; @@ -172,18 +196,26 @@ class DialogueBoxPsych extends FlxSpriteGroup if (!dialogueEnded) { - bgFade.alpha += 0.5 * elapsed; - if (bgFade.alpha > 0.5) - bgFade.alpha = 0.5; + if (bgFade != null) + { + bgFade.alpha += 0.5 * elapsed; + if (bgFade.alpha > 0.5) + bgFade.alpha = 0.5; + } var justTouched:Bool = false; for (touch in FlxG.touches.list) if (touch.justPressed) justTouched = true; - if (Controls.instance.ACCEPT || justTouched) + var acceptPressed:Bool = false; + var controls = Controls.instance; + if (controls != null) + acceptPressed = controls.ACCEPT; + + if (acceptPressed || justTouched) { - if (!daText.finishedText) + if (daText != null && !daText.finishedText) { daText.finishText(); if (skipDialogueThing != null) @@ -191,57 +223,68 @@ class DialogueBoxPsych extends FlxSpriteGroup skipDialogueThing(); } } - else if (currentText >= dialogueList.dialogue.length) + else if (dialogueList != null && currentText >= dialogueList.dialogue.length) { dialogueEnded = true; for (i in 0...textBoxTypes.length) { var checkArray:Array = ['', 'center-']; - var animName:String = box.animation.curAnim.name; - for (j in 0...checkArray.length) + if (box != null && box.animation != null && box.animation.curAnim != null) { - if (animName == checkArray[j] + textBoxTypes[i] || animName == checkArray[j] + textBoxTypes[i] + 'Open') + var animName:String = box.animation.curAnim.name; + for (j in 0...checkArray.length) { - box.animation.play(checkArray[j] + textBoxTypes[i] + 'Open', true); + if (animName == checkArray[j] + textBoxTypes[i] || animName == checkArray[j] + textBoxTypes[i] + 'Open') + { + box.animation.play(checkArray[j] + textBoxTypes[i] + 'Open', true); + } } } } - box.animation.curAnim.curFrame = box.animation.curAnim.frames.length - 1; - box.animation.curAnim.reverse(); + if (box != null && box.animation != null && box.animation.curAnim != null) + { + box.animation.curAnim.curFrame = box.animation.curAnim.frames.length - 1; + box.animation.curAnim.reverse(); + } if (daText != null) { remove(daText); daText.kill(); daText.destroy(); } - updateBoxOffsets(box); + if (box != null) + updateBoxOffsets(box); FlxG.sound.music.fadeOut(1, 0); } else { startNextDialog(); } - FlxG.sound.play(Paths.sound(closeSound), closeVolume); + var soundPath = Paths.sound(closeSound); + if (soundPath != null) + FlxG.sound.play(soundPath, closeVolume); } - else if (daText.finishedText) + else if (daText != null && daText.finishedText) { - var char:DialogueCharacter = arrayCharacters[lastCharacter]; - if (char != null && char.animation.curAnim != null && char.animationIsLoop() && char.animation.finished) + var char:Null = arrayCharacters[lastCharacter]; + if (char != null && char.animation != null && char.animation.curAnim != null && char.animationIsLoop() && char.animation.finished) { - char.playAnim(char.animation.curAnim.name, true); + var animName = char.animation.curAnim.name; + if (animName != null) + char.playAnim(animName, true); } } - else + else if (daText != null) { - var char:DialogueCharacter = arrayCharacters[lastCharacter]; - if (char != null && char.animation.curAnim != null && char.animation.finished) + var char:Null = arrayCharacters[lastCharacter]; + if (char != null && char.animation != null && char.animation.curAnim != null && char.animation.finished) { char.animation.curAnim.restart(); } } - if (box.animation.curAnim.finished) + if (box != null && box.animation != null && box.animation.curAnim != null && box.animation.curAnim.finished) { for (i in 0...textBoxTypes.length) { @@ -265,9 +308,11 @@ class DialogueBoxPsych extends FlxSpriteGroup var char = arrayCharacters[i]; if (char != null) { + var jsonFile = char.jsonFile; + var pos:String = (jsonFile != null) ? jsonFile.dialogue_pos : 'left'; if (i != lastCharacter) { - switch (char.jsonFile.dialogue_pos) + switch (pos) { case 'left': char.x -= scrollSpeed * elapsed; @@ -288,7 +333,7 @@ class DialogueBoxPsych extends FlxSpriteGroup } else { - switch (char.jsonFile.dialogue_pos) + switch (pos) { case 'left': char.x += scrollSpeed * elapsed; @@ -313,7 +358,7 @@ class DialogueBoxPsych extends FlxSpriteGroup } else // Dialogue ending { - if (box != null && box.animation.curAnim.curFrame <= 0) + if (box != null && box.animation != null && box.animation.curAnim != null && box.animation.curAnim.curFrame <= 0) { remove(box); box.kill(); @@ -334,10 +379,12 @@ class DialogueBoxPsych extends FlxSpriteGroup for (i in 0...arrayCharacters.length) { - var leChar:DialogueCharacter = arrayCharacters[i]; + var leChar:Null = arrayCharacters[i]; if (leChar != null) { - switch (arrayCharacters[i].jsonFile.dialogue_pos) + var jsonFile = leChar.jsonFile; + var pos:String = (jsonFile != null) ? jsonFile.dialogue_pos : 'left'; + switch (pos) { case 'left': leChar.x -= scrollSpeed * elapsed; @@ -354,7 +401,7 @@ class DialogueBoxPsych extends FlxSpriteGroup { for (i in 0...arrayCharacters.length) { - var leChar:DialogueCharacter = arrayCharacters[0]; + var leChar:Null = arrayCharacters[0]; if (leChar != null) { arrayCharacters.remove(leChar); @@ -362,7 +409,8 @@ class DialogueBoxPsych extends FlxSpriteGroup leChar.destroy(); } } - finishThing(); + if (finishThing != null) + finishThing(); kill(); } } @@ -374,7 +422,8 @@ class DialogueBoxPsych extends FlxSpriteGroup function startNextDialog():Void { - var curDialogue:DialogueLine = null; + if (dialogueList == null) return; + var curDialogue:Null = null; do { curDialogue = dialogueList.dialogue[currentText]; @@ -388,7 +437,7 @@ class DialogueBoxPsych extends FlxSpriteGroup if (curDialogue.speed == null || Math.isNaN(curDialogue.speed)) curDialogue.speed = 0.05; - var animName:String = curDialogue.boxState; + var animName:String = (curDialogue.boxState != null) ? curDialogue.boxState : 'normal'; var boxType:String = textBoxTypes[0]; for (i in 0...textBoxTypes.length) { @@ -399,49 +448,72 @@ class DialogueBoxPsych extends FlxSpriteGroup } var character:Int = 0; - box.visible = true; + if (box != null) + box.visible = true; for (i in 0...arrayCharacters.length) { - if (arrayCharacters[i].curCharacter == curDialogue.portrait) + var arrChar = arrayCharacters[i]; + if (arrChar != null && arrChar.curCharacter == curDialogue.portrait) { character = i; break; } } var centerPrefix:String = ''; - var lePosition:String = arrayCharacters[character].jsonFile.dialogue_pos; + var lePosition:String = 'left'; + var arrChar = arrayCharacters[character]; + if (arrChar != null) + { + var jsonFile = arrChar.jsonFile; + if (jsonFile != null) + lePosition = jsonFile.dialogue_pos; + } if (lePosition == 'center') centerPrefix = 'center-'; if (character != lastCharacter) { - box.animation.play(centerPrefix + boxType + 'Open', true); - updateBoxOffsets(box); - box.flipX = (lePosition == 'left'); + if (box != null) + { + box.animation.play(centerPrefix + boxType + 'Open', true); + updateBoxOffsets(box); + box.flipX = (lePosition == 'left'); + } } else if (boxType != lastBoxType) { - box.animation.play(centerPrefix + boxType, true); - updateBoxOffsets(box); + if (box != null) + { + box.animation.play(centerPrefix + boxType, true); + updateBoxOffsets(box); + } } lastCharacter = character; lastBoxType = boxType; - daText.text = curDialogue.text; - daText.delay = curDialogue.speed; - daText.sound = curDialogue.sound; - if (daText.sound == null || daText.sound.trim() == '') - daText.sound = 'dialogue'; - - daText.y = DEFAULT_TEXT_Y; - if (daText.rows > 2) - daText.y -= LONG_TEXT_ADD; + if (daText != null && curDialogue.text != null) + daText.text = curDialogue.text; + if (daText != null && curDialogue.speed != null) + daText.delay = curDialogue.speed; + if (daText != null) + { + daText.sound = (curDialogue.sound != null) ? curDialogue.sound : 'dialogue'; + var soundTrimmed = daText.sound.trim(); + if (soundTrimmed == null || soundTrimmed == '') + daText.sound = 'dialogue'; + + daText.y = DEFAULT_TEXT_Y; + if (daText.rows > 2) + daText.y -= LONG_TEXT_ADD; + } - var char:DialogueCharacter = arrayCharacters[character]; + var char:Null = arrayCharacters[character]; if (char != null) { - char.playAnim(curDialogue.expression, daText.finishedText); - if (char.animation.curAnim != null) + var expression = curDialogue.expression; + var finished = (daText != null) ? daText.finishedText : false; + char.playAnim(expression, finished); + if (char.animation != null && char.animation.curAnim != null) { var rate:Float = 24 - (((curDialogue.speed - 0.05) / 5) * 480); if (rate < 12) @@ -459,26 +531,37 @@ class DialogueBoxPsych extends FlxSpriteGroup } } - public static function parseDialogue(path:String):DialogueFile + public static function parseDialogue(path:String):Null { if (FileSystem.exists(path)) - return cast Json.parse(File.getContent(path), path); - + { + var content = File.getContent(path); + if (content != null) + return cast Json.parse(content, path); + } return null; } // Had to make it static because of the editors - public static function updateBoxOffsets(box:FlxSprite) + public static function updateBoxOffsets(box:Null):Void { + if (box == null) return; box.centerOffsets(); box.updateHitbox(); - if (box.animation.curAnim.name.startsWith('angry')) - { - box.offset.set(50, 65); - } - else if (box.animation.curAnim.name.startsWith('center-angry')) + if (box.animation != null && box.animation.curAnim != null && box.animation.curAnim.name != null) { - box.offset.set(50, 30); + if (box.animation.curAnim.name.startsWith('angry')) + { + box.offset.set(50, 65); + } + else if (box.animation.curAnim.name.startsWith('center-angry')) + { + box.offset.set(50, 30); + } + else + { + box.offset.set(10, 0); + } } else { diff --git a/source/engine/cutscenes/DialogueCharacter.hx b/source/engine/cutscenes/DialogueCharacter.hx index 19bd999b..5afd43a9 100644 --- a/source/engine/cutscenes/DialogueCharacter.hx +++ b/source/engine/cutscenes/DialogueCharacter.hx @@ -22,13 +22,14 @@ typedef DialogueCharacterFile = var scale:Float; } +@:nullSafety class DialogueCharacter extends FlxSprite { private static var IDLE_SUFFIX:String = '-IDLE'; public static var DEFAULT_CHARACTER:String = 'bf'; public static var DEFAULT_SCALE:Float = 0.7; - public var jsonFile:DialogueCharacterFile = null; + public var jsonFile:Null = null; public var dialogueAnimations:Map = new Map(); public var startingPos:Float = 0; // For center characters, it works as the starting Y, for everything else it works as starting X @@ -46,11 +47,17 @@ class DialogueCharacter extends FlxSprite this.curCharacter = character; reloadCharacterJson(character); - frames = Paths.getSparrowAtlas('dialogue/' + jsonFile.image); + if (jsonFile != null) + { + var img:String = jsonFile.image; + var atlas = Paths.getSparrowAtlas('dialogue/' + img); + if (atlas != null) + frames = atlas; + } reloadAnimations(); antialiasing = ClientPrefs.data.antialiasing; - if (jsonFile.no_antialiasing == true) + if (jsonFile != null && jsonFile.no_antialiasing == true) antialiasing = false; } @@ -68,14 +75,15 @@ class DialogueCharacter extends FlxSprite if (!FileSystem.exists(path)) path = Paths.getSharedPath(defaultPath); - var rawJson:String = File.getContent(path); - jsonFile = cast Json.parse(rawJson, path); + var rawJson:Null = File.getContent(path); + if (rawJson != null) + jsonFile = cast Json.parse(rawJson, path); } public function reloadAnimations() { dialogueAnimations.clear(); - if (jsonFile.animations != null && jsonFile.animations.length > 0) + if (jsonFile != null && jsonFile.animations != null && jsonFile.animations.length > 0) { for (anim in jsonFile.animations) { @@ -86,9 +94,9 @@ class DialogueCharacter extends FlxSprite } } - public function playAnim(animName:String = null, playIdle:Bool = false) + public function playAnim(animName:Null = null, playIdle:Bool = false) { - var leAnim:String = animName; + var leAnim:Null = animName; if (animName == null || !dialogueAnimations.exists(animName)) // Anim is null, get a random animation { var arrayAnims:Array = []; @@ -102,27 +110,32 @@ class DialogueCharacter extends FlxSprite } } - if (dialogueAnimations.exists(leAnim) - && (dialogueAnimations.get(leAnim).loop_name == null - || dialogueAnimations.get(leAnim).loop_name.length < 1 - || dialogueAnimations.get(leAnim).loop_name == dialogueAnimations.get(leAnim).idle_name)) + if (leAnim != null && dialogueAnimations.exists(leAnim)) { - playIdle = true; + var animData:Null = dialogueAnimations.get(leAnim); + if (animData != null && (animData.loop_name == null + || animData.loop_name.length < 1 + || animData.loop_name == animData.idle_name)) + { + playIdle = true; + } } - animation.play(playIdle ? leAnim + IDLE_SUFFIX : leAnim, false); + if (leAnim != null) + animation.play(playIdle ? leAnim + IDLE_SUFFIX : leAnim, false); - if (dialogueAnimations.exists(leAnim)) + if (leAnim != null && dialogueAnimations.exists(leAnim)) { - var anim:DialogueAnimArray = dialogueAnimations.get(leAnim); - if (playIdle) - { - offset.set(anim.idle_offsets[0], anim.idle_offsets[1]); - // trace('Setting idle offsets: ' + anim.idle_offsets); - } - else + var anim:Null = dialogueAnimations.get(leAnim); + if (anim != null) { - offset.set(anim.loop_offsets[0], anim.loop_offsets[1]); - // trace('Setting loop offsets: ' + anim.loop_offsets); + if (playIdle) + { + offset.set(anim.idle_offsets[0], anim.idle_offsets[1]); + } + else + { + offset.set(anim.loop_offsets[0], anim.loop_offsets[1]); + } } } else diff --git a/source/engine/debug/codename/Framerate.hx b/source/engine/debug/codename/Framerate.hx index d946b2f2..882637da 100644 --- a/source/engine/debug/codename/Framerate.hx +++ b/source/engine/debug/codename/Framerate.hx @@ -11,14 +11,15 @@ import openfl.text.TextFormat; import openfl.ui.Keyboard; import flixel.util.FlxTimer; +@:nullSafety class Framerate extends Sprite { - public static var instance:Framerate; + public static var instance:Null = null; public static var isLoaded:Bool = false; - public static var textFormat:TextFormat; - public static var fpsCounter:FramerateCounter; - public static var memoryCounter:MemoryCounter; + public static var textFormat:Null = null; + public static var fpsCounter:Null = null; + public static var memoryCounter:Null = null; public static var fontName:String = #if windows '${Sys.getEnv("windir")}\\Fonts\\consola.ttf' #else "_typewriter" #end; @@ -31,11 +32,11 @@ class Framerate extends Sprite public static var offset:FlxPoint = new FlxPoint(); - public var bgSprite:Bitmap; + public var bgSprite:Null = null; public var categories:Array = []; - @:isVar public static var __bitmap(get, null):BitmapData = null; + @:isVar public static var __bitmap(get, null):Null = null; private static function get___bitmap():BitmapData { @@ -53,15 +54,12 @@ class Framerate extends Sprite { super(); if (instance != null) - throw "Cannot create another instance"; + return; instance = this; textFormat = new TextFormat(fontName, 12, -1); isLoaded = true; - x = 10; - y = 2; - FlxG.signals.gameResized.add(function(w, h) { setScale(Math.min(openfl.Lib.current.stage.stageWidth / FlxG.width, openfl.Lib.current.stage.stageHeight / FlxG.height)); @@ -69,12 +67,14 @@ class Framerate extends Sprite FlxG.stage.addEventListener(KeyboardEvent.KEY_UP, function(e:KeyboardEvent) { - if (Controls.instance.justReleased('fpsCounter')) + var ctrl = Controls.instance; + if (ctrl != null && ctrl.justReleased('fpsCounter')) { debugMode = (debugMode + 1) % 3; @:privateAccess { - memoryCounter.refreshText(memoryCounter.memory, memoryCounter.memoryPeak); + if (memoryCounter != null) + memoryCounter.refreshText(memoryCounter.memory, memoryCounter.memoryPeak); } } }); @@ -82,6 +82,8 @@ class Framerate extends Sprite if (__bitmap == null) __bitmap = new BitmapData(1, 1, 0xFF000000); + x = 10; + y = 2; bgSprite = new Bitmap(__bitmap); bgSprite.alpha = 0; addChild(bgSprite); @@ -95,8 +97,10 @@ class Framerate extends Sprite { for (c in categories) c.reload(); - memoryCounter.reload(); - fpsCounter.reload(); + if (memoryCounter != null) + memoryCounter.reload(); + if (fpsCounter != null) + fpsCounter.reload(); } private function __addCategory(category:FramerateCategory) @@ -105,7 +109,7 @@ class Framerate extends Sprite __addToList(category); } - private var __lastAddedSprite:DisplayObject = null; + private var __lastAddedSprite:Null = null; private function __addToList(spr:DisplayObject) { @@ -161,19 +165,29 @@ class Framerate extends Sprite if (alpha < 0.05) return; super.__enterFrame(t); - bgSprite.alpha = debugAlpha * 0.5; + if (bgSprite != null) + bgSprite.alpha = debugAlpha * 0.5; x = 10 + offset.x; y = 2 + offset.y; - var width = MathUtil.maxSmart(fpsCounter.width, memoryCounter.width) + (x * 2); - var height = memoryCounter.y + memoryCounter.height; - bgSprite.x = -x; - bgSprite.y = offset.x; - bgSprite.scaleX = width; - bgSprite.scaleY = height; + var width = 0.0; + var height = 0.0; + if (fpsCounter != null && memoryCounter != null) + { + width = MathUtil.maxSmart(fpsCounter.width, memoryCounter.width) + (x * 2); + height = memoryCounter.y + memoryCounter.height; + } + if (bgSprite != null) + { + bgSprite.x = -x; + bgSprite.y = offset.x; + bgSprite.scaleX = width; + bgSprite.scaleY = height; + } - var selectable = debugMode == 2; // idk i tried to make it more readable:sob: - Nex + var selectable = debugMode == 2; + if (memoryCounter != null && fpsCounter != null) { memoryCounter.memoryText.selectable = memoryCounter.memoryPeakText.selectable = fpsCounter.fpsNum.selectable = fpsCounter.fpsLabel.selectable = selectable; } diff --git a/source/engine/debug/codename/FramerateCategory.hx b/source/engine/debug/codename/FramerateCategory.hx index e63c4d7c..de496f0b 100644 --- a/source/engine/debug/codename/FramerateCategory.hx +++ b/source/engine/debug/codename/FramerateCategory.hx @@ -5,6 +5,7 @@ import openfl.display.Sprite; import openfl.text.TextField; import openfl.text.TextFormat; +@:nullSafety class FramerateCategory extends Sprite { public var title:TextField; @@ -18,7 +19,6 @@ class FramerateCategory extends Sprite { super(); - x = 10; this.title = new TextField(); this.text = new TextField(); @@ -40,6 +40,7 @@ class FramerateCategory extends Sprite this.text.multiline = true; this.text.y = this.title.y + this.title.height + 2; + x = 10; } public function reload() {} @@ -50,9 +51,10 @@ class FramerateCategory extends Sprite return; super.__enterFrame(t); - var width = Math.max(this.title.width, this.text.width) + (Framerate.instance.x * 2); + var instanceX = Framerate.instance != null ? Framerate.instance.x : 10; + var width = Math.max(this.title.width, this.text.width) + (instanceX * 2); var height = this.text.height + this.text.y; - bgSprite.x = -Framerate.instance.x; + bgSprite.x = -instanceX; bgSprite.scaleX = width; bgSprite.scaleY = height; } diff --git a/source/engine/debug/codename/FramerateCounter.hx b/source/engine/debug/codename/FramerateCounter.hx index aac1bfc5..e2c52060 100644 --- a/source/engine/debug/codename/FramerateCounter.hx +++ b/source/engine/debug/codename/FramerateCounter.hx @@ -4,6 +4,7 @@ import openfl.display.Sprite; import openfl.text.TextField; import openfl.text.TextFormat; +@:nullSafety class FramerateCounter extends Sprite { public var fpsNum:TextField; diff --git a/source/engine/debug/codename/MemoryCounter.hx b/source/engine/debug/codename/MemoryCounter.hx index c7de96ce..325df0c8 100644 --- a/source/engine/debug/codename/MemoryCounter.hx +++ b/source/engine/debug/codename/MemoryCounter.hx @@ -4,6 +4,7 @@ import openfl.display.Sprite; import openfl.text.TextField; import openfl.text.TextFormat; +@:nullSafety class MemoryCounter extends Sprite { public var memoryText:TextField; diff --git a/source/engine/debug/codename/SystemInfo.hx b/source/engine/debug/codename/SystemInfo.hx index 433ef500..b62e718b 100644 --- a/source/engine/debug/codename/SystemInfo.hx +++ b/source/engine/debug/codename/SystemInfo.hx @@ -26,6 +26,7 @@ using StringTools; @:headerInclude('sys/utsname.h') #end #end +@:nullSafety class SystemInfo extends FramerateCategory { public static var osInfo:String = "Unknown"; @@ -83,8 +84,9 @@ class SystemInfo extends FramerateCategory } #elseif windows var windowsCurrentVersionPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; - var buildNumber = Std.parseInt(RegistryUtil.get(HKEY_LOCAL_MACHINE, windowsCurrentVersionPath, "CurrentBuildNumber")); - var edition = RegistryUtil.get(HKEY_LOCAL_MACHINE, windowsCurrentVersionPath, "ProductName"); + var buildNumStr = RegistryUtil.get(HKEY_LOCAL_MACHINE, windowsCurrentVersionPath, "CurrentBuildNumber"); + var buildNumber:Int = (buildNumStr != null) ? Std.parseInt(buildNumStr) ?? 0 : 0; + var edition:String = RegistryUtil.get(HKEY_LOCAL_MACHINE, windowsCurrentVersionPath, "ProductName") ?? "Unknown"; var lcuKey = "WinREVersion"; // Last Cumulative Update Key On Older Windows Versions if (buildNumber >= 22000) // Windows 11 Initial Release Build Number @@ -116,7 +118,7 @@ class SystemInfo extends FramerateCategory try { #if windows - cpuName = RegistryUtil.get(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "ProcessorNameString"); + cpuName = RegistryUtil.get(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", "ProcessorNameString") ?? "Unknown"; #elseif mac var process = new Process("sysctl -a | grep brand_string"); // Somehow this isn't able to use the args but it still works if (process.exitCode() != 0) diff --git a/source/engine/mobile/backend/MobileData.hx b/source/engine/mobile/backend/MobileData.hx index 5e091076..f0989a6e 100644 --- a/source/engine/mobile/backend/MobileData.hx +++ b/source/engine/mobile/backend/MobileData.hx @@ -10,6 +10,7 @@ import flixel.util.FlxSave; * ... * @author: Karim Akra */ +@:nullSafety(Off) class MobileData { public static var actionModes:Map = new Map(); diff --git a/source/engine/mobile/backend/StorageUtil.hx b/source/engine/mobile/backend/StorageUtil.hx index 239f6b90..324eddb4 100644 --- a/source/engine/mobile/backend/StorageUtil.hx +++ b/source/engine/mobile/backend/StorageUtil.hx @@ -4,6 +4,7 @@ package mobile.backend; * A storage class for mobile. * @author Karim Akra and Homura Akemi (HomuHomu833) */ +@:nullSafety class StorageUtil { #if sys diff --git a/source/engine/mobile/backend/TouchUtil.hx b/source/engine/mobile/backend/TouchUtil.hx index 006ba6fb..d27258ff 100644 --- a/source/engine/mobile/backend/TouchUtil.hx +++ b/source/engine/mobile/backend/TouchUtil.hx @@ -7,6 +7,7 @@ import flixel.input.touch.FlxTouch; * ... * @author: Karim Akra */ +@:nullSafety(Off) class TouchUtil { public static var pressed(get, never):Bool; diff --git a/source/engine/mobile/input/MobileInputID.hx b/source/engine/mobile/input/MobileInputID.hx index fe432f24..ae34403d 100644 --- a/source/engine/mobile/input/MobileInputID.hx +++ b/source/engine/mobile/input/MobileInputID.hx @@ -9,6 +9,7 @@ import flixel.system.macros.FlxMacroUtil; * @author Karim Akra */ @:runtimeValue +@:nullSafety(Off) enum abstract MobileInputID(Int) from Int to Int { public static var fromStringMap(default, null):Map = FlxMacroUtil.buildMap("mobile.input.MobileInputID"); diff --git a/source/engine/mobile/input/MobileInputManager.hx b/source/engine/mobile/input/MobileInputManager.hx index aea65bdf..9b7c95d0 100644 --- a/source/engine/mobile/input/MobileInputManager.hx +++ b/source/engine/mobile/input/MobileInputManager.hx @@ -8,6 +8,7 @@ import haxe.ds.Map; * A TouchButton group with functions for input handling * @author Karim Akra */ +@:nullSafety(Off) class MobileInputManager extends FlxTypedSpriteGroup { /** diff --git a/source/engine/mobile/objects/Hitbox.hx b/source/engine/mobile/objects/Hitbox.hx index f7ebd6d4..4ab04879 100644 --- a/source/engine/mobile/objects/Hitbox.hx +++ b/source/engine/mobile/objects/Hitbox.hx @@ -13,6 +13,7 @@ import openfl.geom.Matrix; * * @author: Karim Akra and Homura Akemi (HomuHomu833) */ +@:nullSafety(Off) class Hitbox extends MobileInputManager implements IMobileControls { final offsetFir:Int = (ClientPrefs.data.hitboxPos ? Std.int(FlxG.height / 4) * 3 : 0); diff --git a/source/engine/mobile/objects/IMobileControls.hx b/source/engine/mobile/objects/IMobileControls.hx index b002b253..ba0f03f6 100644 --- a/source/engine/mobile/objects/IMobileControls.hx +++ b/source/engine/mobile/objects/IMobileControls.hx @@ -7,6 +7,7 @@ import flixel.util.FlxSignal.FlxTypedSignal; * ... * @author: Karim Akra */ +@:nullSafety(Off) interface IMobileControls { public var buttonLeft:TouchButton; diff --git a/source/engine/mobile/objects/MobileControls.hx b/source/engine/mobile/objects/MobileControls.hx index 64056042..8b25fb76 100644 --- a/source/engine/mobile/objects/MobileControls.hx +++ b/source/engine/mobile/objects/MobileControls.hx @@ -7,6 +7,7 @@ package mobile.objects; * ... * @author: Karim Akra */ +@:nullSafety(Off) class MobileControls extends FlxTypedSpriteGroup { public var touchPad:TouchPad = new TouchPad('NONE', 'NONE', NONE); diff --git a/source/engine/mobile/objects/TouchButton.hx b/source/engine/mobile/objects/TouchButton.hx index 6f3b84ed..4b0c8c8c 100644 --- a/source/engine/mobile/objects/TouchButton.hx +++ b/source/engine/mobile/objects/TouchButton.hx @@ -13,6 +13,7 @@ import flixel.input.mouse.FlxMouseButton; * A simple button class that calls a function when clicked by the touch. * @author: Karim Akra and Homura Akemi (HomuHomu833) */ +@:nullSafety(Off) class TouchButton extends TypedTouchButton { /** @@ -77,6 +78,7 @@ class TouchButton extends TypedTouchButton #if !display @:generic #end +@:nullSafety(Off) class TypedTouchButton extends FlxSprite implements IFlxInput { /** @@ -577,6 +579,7 @@ class TypedTouchButton extends FlxSprite implements IFlxInput /** * Helper function for `TouchButton` which handles its events. */ +@:nullSafety(Off) private class TouchButtonEvent implements IFlxDestroyable { /** @@ -631,6 +634,7 @@ private class TouchButtonEvent implements IFlxDestroyable } } +@:nullSafety(Off) class ButtonBrightnessShader extends FlxShader { public var color(default, set):Null = FlxColor.WHITE; @@ -667,6 +671,7 @@ class ButtonBrightnessShader extends FlxShader } } +@:nullSafety(Off) enum StatusIndicators { // isn't very good looking diff --git a/source/engine/mobile/objects/TouchPad.hx b/source/engine/mobile/objects/TouchPad.hx index 44598a50..d594323c 100644 --- a/source/engine/mobile/objects/TouchPad.hx +++ b/source/engine/mobile/objects/TouchPad.hx @@ -8,6 +8,7 @@ import flixel.util.FlxSignal.FlxTypedSignal; * @author: Karim Akra and Homura Akemi (HomuHomu833) */ @:access(mobile.objects.TouchButton) +@:nullSafety(Off) class TouchPad extends MobileInputManager implements IMobileControls { public var buttonLeft:TouchButton = new TouchButton(0, 0, [MobileInputID.LEFT, MobileInputID.NOTE_LEFT]); diff --git a/source/engine/mobile/options/MobileOptionsSubState.hx b/source/engine/mobile/options/MobileOptionsSubState.hx index aaeaab10..e0064e17 100644 --- a/source/engine/mobile/options/MobileOptionsSubState.hx +++ b/source/engine/mobile/options/MobileOptionsSubState.hx @@ -4,13 +4,14 @@ import flixel.input.keyboard.FlxKey; import options.BaseOptionsMenu; import options.Option; +@:nullSafety class MobileOptionsSubState extends BaseOptionsMenu { #if FEATURE_MOBILE_CONTROLS final exControlTypes:Array = ["NONE", "SINGLE", "DOUBLE"]; final hintOptions:Array = ["No Gradient", "No Gradient (Old)", "Gradient", "Hidden"]; #end - var option:Option; + var option:Null