Skip to content

Commit 5d9fd34

Browse files
committed
Preparing for something big!
1 parent d59b463 commit 5d9fd34

19 files changed

+2018
-163
lines changed

Project.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<define name="MODS_ALLOWED" if="desktop" />
2424
<define name="HSCRIPT_ALLOWED" if="desktop" />
2525
<define name="LUA_ALLOWED" if="desktop" />
26+
<!-- <define name="PYTHON_ALLOWED" if="desktop" /> -->
2627
<define name="ACHIEVEMENTS_ALLOWED" />
2728
<define name="DISCORD_ALLOWED" />
2829
<define name="TRANSLATIONS_ALLOWED" />
@@ -141,6 +142,7 @@
141142
<haxelib name="hxvlc" if="VIDEOS_ALLOWED" version="2.0.1"/>
142143
<haxelib name="hxdiscord_rpc" version="1.2.4" if="DISCORD_ALLOWED"/>
143144
<haxelib name="flxanimate"/>
145+
<haxelib name="hxpy" if="PYTHON_ALLOWED" />
144146

145147
<!-- Archipelago Stuff-->
146148
<haxelib name="helder.set" />

haxelib.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"cpp": {
3+
"build_flags": [
4+
"-I/C:/Program Files/Python313/include"
5+
]
6+
}
7+
}

source/Main.hx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,20 @@ class Main extends Sprite
8989

9090
public static function main():Void
9191
{
92+
trace(18.sum());
93+
trace([1, 2, 3].sum());
94+
trace([1, 2.3, 3.4].sum());
95+
96+
function testOneOrMore(o:OneOrMore<Float>):Void {
97+
if (o.isSingle()) {
98+
trace("Single value: " + o.getSingle());
99+
} else {
100+
trace("Multiple values: " + o.toArray());
101+
}
102+
}
103+
testOneOrMore(39.asFloat());
104+
testOneOrMore([1, 2, 3].asFloat());
105+
92106
Lib.current.addChild(new Main());
93107
//Stolen from Psych Online. Thanks for making the next hour of my life not hell.
94108
Lib.current.addChild(new archipelago.console.SideUI());

source/backend/Paths.hx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,12 @@ class Paths
659659
return allowNull ? {location: null, modded: false} : null;
660660
}
661661

662+
public static inline function assetInTopMod(key:String, ?parentFolder:String = null, ?pathType:PathType = IMAGES):Bool
663+
{
664+
var assetLocation = assetLocation(key, parentFolder, pathType, true, true);
665+
return assetLocation != null && assetLocation.modded;
666+
}
667+
662668
static public function image(key:String, ?parentFolder:String = null, ?allowGPU:Bool = true):FlxGraphic
663669
{
664670
key = Language.getFileTranslation('images/$key') + '.png';

source/import.hx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,11 @@ using StringTools;
9898
using yutautil.CollectionUtils;
9999
using yutautil.MetaData;
100100
using yutautil.PointerTools;
101-
using yutautil.CUMacroTools; // Careful. Using C++ Lables in Haxe may act strangely.
101+
using yutautil.CUMacroTools;
102102
using yutautil.KonamiTracker;
103103
using yutautil.GenericObject;
104104
using yutautil.PyScript;
105+
using yutautil.FieldMap;
106+
using yutautil.Tracked;
107+
using yutautil.OneOrMany;
105108
#end
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package states.freeplay;
2+
3+
import flixel.FlxState;
4+
import flixel.FlxG;
5+
import hscript.Parser;
6+
import hscript.Interp;
7+
import sys.io.File;
8+
import managers.FreeplayManager;
9+
10+
import crowplexus.iris.Iris;
11+
import crowplexus.iris.IrisConfig;
12+
13+
class CustomFreeplayState extends MusicBeatState {
14+
public var scriptInterp:psychlua.HScript.CustomInterp;
15+
public var scriptEnv:Dynamic;
16+
public var scriptPath:String;
17+
public var themeName:String;
18+
19+
public function new(scriptPath:String) {
20+
super();
21+
this.scriptPath = scriptPath;
22+
this.themeName = scriptPath.split('/').pop().split('.').shift(); // Extract theme name from script path
23+
}
24+
25+
26+
// ...existing code...
27+
28+
override public function create():Void {
29+
super.create();
30+
31+
// Prepare Iris interpreter
32+
var scriptCode = File.getContent(scriptPath);
33+
var iris = new Iris(scriptCode, new IrisConfig(null, false, false));
34+
var customInterp:psychlua.HScript.CustomInterp = new psychlua.HScript.CustomInterp();
35+
customInterp.parentInstance = FlxG.state;
36+
customInterp.showPosOnLog = false;
37+
this.scriptInterp = customInterp;
38+
39+
// Only expose Freeplay-relevant variables
40+
iris.set('FreeplayManager', FreeplayManager);
41+
iris.set('FlxG', FlxG);
42+
iris.set('FlxState', FlxState);
43+
iris.set('FlxSprite', flixel.FlxSprite);
44+
iris.set('${Type.getClassName(Type.getClass(FlxG.state))}', this);
45+
iris.set('state', this);
46+
47+
// Parse and execute the script, expecting it to return an object with lifecycle methods
48+
iris.parse(true);
49+
scriptEnv = iris.funcAndReturn(iris.execute);
50+
51+
// Call script's create if it exists
52+
if (scriptEnv != null && Reflect.hasField(scriptEnv, "create")) {
53+
Reflect.callMethod(scriptEnv, Reflect.field(scriptEnv, "create"), []);
54+
}
55+
this.scriptInterp = iris;
56+
}
57+
58+
override public function update(elapsed:Float):Void {
59+
super.update(elapsed);
60+
if (scriptEnv != null && Reflect.hasField(scriptEnv, "update")) {
61+
Reflect.callMethod(scriptEnv, Reflect.field(scriptEnv, "update"), [elapsed]);
62+
}
63+
}
64+
65+
override public function destroy():Void {
66+
if (scriptEnv != null && Reflect.hasField(scriptEnv, "destroy")) {
67+
Reflect.callMethod(scriptEnv, Reflect.field(scriptEnv, "destroy"), []);
68+
}
69+
super.destroy();
70+
}
71+
}

source/yutautil/BrainFuck.hx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,41 @@ class BrainFuck {
5757

5858
return output;
5959
}
60+
61+
public static function run(code:String, input:String = "", native:Bool = false):String {
62+
try {
63+
return interpret(code, input, native);
64+
} catch (e:Dynamic) {
65+
return "Error: " + e;
66+
}
67+
}
68+
69+
public static function runFile(filePath:String, input:String = "", native:Bool = false):String {
70+
var code:String = haxe.io.File.getContent(filePath);
71+
return run(code, input, native);
72+
}
73+
74+
// Generates a Brainfuck program that sets the memory to match the given array.
75+
// If native is true, checks that all values are in 0...255.
76+
public static function mimicArray(arr:Array<Int>, native:Bool = false):String {
77+
var code = "";
78+
var last = 0;
79+
var memorySize = native ? 256 : 30000;
80+
81+
// Check validity if native
82+
if (native) {
83+
for (v in arr) {
84+
if (v < 0 || v > 255) throw "All values must be in 0...255 for native mode";
85+
}
86+
}
87+
88+
for (i in 0...arr.length) {
89+
code += ">";
90+
var diff = arr[i] - last;
91+
if (diff > 0) code += StringTools.rpad("", "+", diff);
92+
else if (diff < 0) code += StringTools.rpad("", "-", -diff);
93+
last = arr[i];
94+
}
95+
return code;
96+
}
6097
}

source/yutautil/CUMacroTools.hx

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,4 +644,68 @@ class CUMacroTools
644644
public static macro function checkKeysAnyPressed(keys:Array<Dynamic>):Expr {
645645
return macro CUMacroTools.generateKeyCheckFunction($a{[for (k in keys) macro $v{k}]}, "anyPressed")();
646646
}
647-
}
647+
}
648+
649+
// Macro + Abstract for strongly-typed, size-limited function argument arrays
650+
651+
@:forward
652+
abstract FuncArgsArray<T>(Array<Null<T>>) from Array<Null<T>> to Array<Null<T>> {
653+
// Only allow creation via macro
654+
@:from
655+
static macro function fromExprs(exprs:Array<Expr>):Expr {
656+
var pos = Context.currentPos();
657+
// The macro must be called as FuncArgsArray.make(functionType, [args...])
658+
Context.error("FuncArgsArray can only be created via FuncArgsArray.make(functionType, [args...])", pos);
659+
return macro null;
660+
}
661+
662+
// Helper to get argument types from a function type
663+
public static function getArgTypes(funcType:Type):Array<Type> {
664+
switch (funcType) {
665+
case TFun(args, _):
666+
return [for (a in args) a.t];
667+
default:
668+
throw "Not a function type";
669+
}
670+
}
671+
672+
// Macro to create a FuncArgsArray for a given function type and argument expressions
673+
public static macro function make(funcType:Expr, args:Array<Expr>):Expr {
674+
var pos = Context.currentPos();
675+
var t = Context.typeof(funcType);
676+
var argTypes:Array<Type> = [];
677+
switch (t) {
678+
case TFun(params, _):
679+
argTypes = [for (a in params) a.t];
680+
default:
681+
Context.error("FuncArgsArray.make: funcType must be a function type", pos);
682+
}
683+
if (args.length > argTypes.length) {
684+
Context.error('Too many arguments: expected ${argTypes.length}, got ${args.length}', pos);
685+
}
686+
// Fill missing args with null
687+
var filledArgs = [];
688+
for (i in 0...argTypes.length) {
689+
if (i < args.length) {
690+
filledArgs.push(args[i]);
691+
} else {
692+
filledArgs.push(macro null);
693+
}
694+
}
695+
// Wrap in abstract
696+
return macro new FuncArgsArray<Dynamic>([$a{filledArgs}]);
697+
}
698+
699+
// Get argument at index (null if not provided)
700+
public inline function get(i:Int):Null<T> return this[i];
701+
702+
// Length is fixed to the function's arity
703+
public var length(get, never):Int;
704+
inline function get_length() return this.length;
705+
}
706+
707+
// Usage example (not part of the macro/abstract):
708+
// var args = FuncArgsArray.make(macro myFunc, [macro 1, macro "test"]);
709+
// args.get(0); // 1
710+
// args.get(1); // "test"
711+
// args.get(2); // null (if myFunc has 3 args)

0 commit comments

Comments
 (0)