Skip to content

Commit d82c225

Browse files
committed
Oh dear god...
1 parent 2c6e5f1 commit d82c225

File tree

4 files changed

+327
-3
lines changed

4 files changed

+327
-3
lines changed

source/Main.hx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ class Main extends Sprite
134134
Toolkit.theme = 'dark'; // don't be cringe
135135
backend.Cursor.registerHaxeUICursors();
136136

137+
// yutautil.save.MixSaveWrapperBeta.testFunctionSave();
138+
137139
#if LUA_ALLOWED
138140
Mods.pushGlobalMods();
139141
#end

source/yutautil/save/FuncEmbed.hx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class FuncEmbed {
2828
* Converts a function expression to its string representation and optionally checks for errors.
2929
*
3030
* @param func The function expression to convert to a string.
31-
* @param unsafe Optional boolean flag to skip error checking. Defaults to false. Should only be used when a function needs a context.
31+
* @param unsafe Optional boolean flag to skip error checking. Defaults to false. Should only be used when a function needs a context in which cannot be accessed at compile time.
3232
* @return The string representation of the function expression.
3333
*
3434
* If `unsafe` is false, the function will check for errors in the function expression.
@@ -70,10 +70,10 @@ class FuncEmbed {
7070
* @param run Optional parameter to determine if the function should be executed immediately.
7171
* @return The result of the function execution, or null if an error occurs.
7272
*/
73-
public static function runFunctionFromString(funcStr:String, context:Dynamic, ?run = false):Dynamic {
73+
public static function runFunctionFromString(funcStr:String, context:Dynamic, ?run = false, ?contextName:String):Dynamic {
7474
var parser = new Parser();
7575
var interp = new Interp();
76-
interp.variables.set("context", context);
76+
interp.variables.set(contextName != null ? contextName : "context", context);
7777

7878
// Convert the expression string into a format that HScript can read
7979
var hscriptExprStr = funcStr;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package yutautil.save;
2+
3+
import haxe.macro.Context;
4+
import yutautil.save.FuncEmbed as FuncE;
5+
import haxe.macro.Expr;
6+
import haxe.macro.Printer;
7+
8+
class MixSave {
9+
public var content:Map<String, Dynamic>;
10+
public var customBehaviors:Map<String, {save:String, load:String}>;
11+
12+
public function new() {
13+
content = new Map();
14+
customBehaviors = new Map();
15+
}
16+
17+
public function addContent(key:String, value:Dynamic):Void {
18+
content.set(key, value);
19+
}
20+
21+
public function getContent(key:String):Dynamic {
22+
return content.get(key);
23+
}
24+
25+
public macro function addContentWithBehavior(key:String, value:Dynamic, saveFunc:Expr, loadFunc:Expr):Expr {
26+
var saveFuncStr = FuncE.functionToString(saveFunc);
27+
var loadFuncStr = FuncE.functionToString(loadFunc);
28+
var key = Context.makeExpr(key, Context.currentPos());
29+
return macro {
30+
this.addContent($key, $value);
31+
this.customBehaviors.set($key, {save: $saveFuncStr, load: $loadFuncStr});
32+
};
33+
}
34+
35+
public macro function registerBehavior(key:String, saveFunc:Expr, loadFunc:Expr):Expr {
36+
var saveFuncStr = FuncE.functionToString(saveFunc);
37+
var loadFuncStr = FuncE.functionToString(loadFunc);
38+
var key = Context.makeExpr(key, Context.currentPos());
39+
return macro {
40+
this.customBehaviors.set($key, {save: $saveFuncStr, load: $loadFuncStr});
41+
if (!this.content.exists($key)) {
42+
this.content.set($key, null);
43+
}
44+
};
45+
}
46+
47+
public function saveContent(key:String):String {
48+
if (customBehaviors.exists(key)) {
49+
var saveFuncStr = customBehaviors.get(key).save;
50+
var saveFunc = FuncE.runFunctionFromString(saveFuncStr, this.content.get(key));
51+
return saveFunc(content.get(key));
52+
} else {
53+
return haxe.Json.stringify(content.get(key));
54+
}
55+
}
56+
57+
public function loadContent(key:String, data:String):Void {
58+
if (customBehaviors.exists(key)) {
59+
var loadFuncStr = customBehaviors.get(key).load;
60+
var loadFunc = FuncE.runFunctionFromString(loadFuncStr, this);
61+
content.set(key, loadFunc(data));
62+
} else {
63+
content.set(key, haxe.Json.parse(data));
64+
}
65+
}
66+
}
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
package yutautil.save;
2+
3+
import haxe.macro.Expr;
4+
import sys.io.File;
5+
using yutautil.save.MixSaveBeta;
6+
using yutautil.CollectionUtils;
7+
8+
enum OutputType {
9+
MixSaveWrapperType;
10+
MixSaveType;
11+
MapType;
12+
DynamicType;
13+
}
14+
15+
class MixSaveWrapper {
16+
public var mixSave:MixSaveBeta;
17+
private var filePath:String;
18+
public var fancyFormat:Bool = false;
19+
20+
public function new(?mixSave:MixSave, filePath:String = "save/mixsave.json", autoLoad:Bool = true) {
21+
this.mixSave = mixSave != null ? mixSave : new MixSave();
22+
this.filePath = filePath;
23+
if (!filePath.endsWith(".json")) {
24+
filePath += ".json";
25+
this.filePath = filePath;
26+
}
27+
if (sys.FileSystem.exists(filePath) && autoLoad) {
28+
load();
29+
}
30+
}
31+
32+
public function save():Void {
33+
var fileContent = new Map<String, String>();
34+
var behaviorContent = new Map<String, {save:String, load:String}>();
35+
for (key in mixSave.content.keys()) {
36+
fileContent.set(key, mixSave.saveContent(key));
37+
if (mixSave.customBehaviors.exists(key)) {
38+
behaviorContent.set(key, mixSave.customBehaviors.get(key));
39+
}
40+
}
41+
if (!sys.FileSystem.exists(haxe.io.Path.directory(filePath))) {
42+
sys.FileSystem.createDirectory(haxe.io.Path.directory(filePath));
43+
}
44+
var jsonString = haxe.Json.stringify(fileContent, null, fancyFormat ? "\t" : null);
45+
var behaviorString = haxe.Json.stringify(behaviorContent, null, fancyFormat ? "\t" : null);
46+
File.saveContent(filePath, jsonString);
47+
File.saveContent(filePath + ".behaviors", behaviorString);
48+
}
49+
50+
public function saveContent(key:String):String {
51+
return mixSave.saveContent(key);
52+
}
53+
54+
public function addItem(key:String, value:Dynamic):Void {
55+
mixSave.addContent(key, value);
56+
}
57+
58+
public function addItemFunction(key:String, saveFunc:Expr, loadFunc:Expr):Void {
59+
macro mixSave.registerBehavior(key, saveFunc, loadFunc);
60+
}
61+
62+
public function addItemWithFunction(key:String, value:Dynamic, saveFunc:Expr, loadFunc:Expr):Void {
63+
macro mixSave.addContentWithBehavior(key, value, saveFunc, loadFunc);
64+
}
65+
66+
public function getItem(key:String):Dynamic {
67+
return mixSave.getContent(key);
68+
}
69+
70+
public function removeItem(key:String):Void {
71+
mixSave.content.remove(key);
72+
}
73+
74+
public function hasItem(key:String):Bool {
75+
return mixSave.content.exists(key);
76+
}
77+
78+
public function editItem(key:String, value:Dynamic):Void {
79+
mixSave.content.set(key, value);
80+
}
81+
82+
public function clear():Void {
83+
mixSave.content = new Map();
84+
}
85+
86+
public function load():Void {
87+
if (sys.FileSystem.exists(filePath)) {
88+
var jsonContent = File.getContent(filePath);
89+
var parsedContent = haxe.Json.parse(jsonContent);
90+
var fileContent:Map<String, String> = new Map();
91+
for (key in Reflect.fields(parsedContent)) {
92+
fileContent.set(key, Reflect.field(parsedContent, key));
93+
}
94+
var behaviorContent:Map<String, {save:String, load:String}> = new Map();
95+
if (sys.FileSystem.exists(filePath + ".behaviors")) {
96+
var behaviorJsonContent = File.getContent(filePath + ".behaviors");
97+
var parsedBehaviorContent = haxe.Json.parse(behaviorJsonContent);
98+
for (key in Reflect.fields(parsedBehaviorContent)) {
99+
behaviorContent.set(key, Reflect.field(parsedBehaviorContent, key));
100+
}
101+
if (behaviorContent.lengthTo() > 0) {
102+
for (key in behaviorContent.keys()) {
103+
var behavior = behaviorContent.get(key);
104+
mixSave.customBehaviors.set(key, behavior);
105+
}
106+
}
107+
}
108+
109+
110+
111+
112+
113+
// trace(fileContent);
114+
for (key in fileContent.keys()) {
115+
mixSave.loadContent(key, fileContent.get(key));
116+
}
117+
}
118+
}
119+
120+
public function addObject(thing:Dynamic):Void {
121+
for (field in Reflect.fields(thing)) {
122+
var value = Reflect.field(thing, field);
123+
mixSave.content.set(field, value);
124+
}
125+
}
126+
127+
public static function saveObjectToFile(thing:Dynamic, filePath:String = "save/mixsave.json", ?fancy:Bool = false):Void {
128+
var wrapper = new MixSaveWrapper(new MixSave(), filePath);
129+
wrapper.addObject(thing);
130+
wrapper.fancyFormat = fancy;
131+
wrapper.save();
132+
}
133+
134+
public static function loadObjectFromFile(thing:Dynamic, filePath:String = "save/mixsave.json"):Void {
135+
var wrapper = new MixSaveWrapper(new MixSave(), filePath);
136+
wrapper.load();
137+
for (field in Reflect.fields(thing)) {
138+
if (wrapper.mixSave.content.exists(field)) {
139+
Reflect.setField(thing, field, wrapper.mixSave.content.get(field));
140+
}
141+
}
142+
}
143+
144+
/**
145+
* Loads a mix file from the specified file path and returns the content based on the specified output type.
146+
*
147+
* @param filePath The path to the mix file to load. Defaults to "save/mixsave.json".
148+
* @param outputType The type of output to return. Can be one of the following:
149+
* - MixSaveWrapperType: Returns the MixSaveWrapper instance.
150+
* - MixSaveType: Returns the MixSave instance.
151+
* - MapType: Returns the content of the MixSave as a map.
152+
* - DynamicType: Returns the content of the MixSave as a dynamic object.
153+
* @return The content of the mix file based on the specified output type.
154+
*/
155+
public static function loadMixFile(filePath:String = "save/mixsave.json", outputType:OutputType):Dynamic {
156+
var wrapper = new MixSaveWrapper(new MixSave(), filePath);
157+
switch (outputType) {
158+
case MixSaveWrapperType:
159+
return wrapper;
160+
case MixSaveType:
161+
return wrapper.mixSave;
162+
case MapType:
163+
return wrapper.mixSave.content;
164+
case DynamicType:
165+
var result = {};
166+
for (field in wrapper.mixSave.content.keys()) {
167+
Reflect.setField(result, field, wrapper.mixSave.content.get(field));
168+
}
169+
return result;
170+
}
171+
}
172+
173+
public static function newWithData(mixSave:MixSave, data:Map<String, Dynamic>, filePath:String = "save/mixsave.json"):MixSaveWrapper {
174+
var wrapper = new MixSaveWrapper(mixSave, filePath);
175+
wrapper.mixSave.content = data;
176+
return wrapper;
177+
}
178+
179+
public static function newWithDynamic(mixSave:MixSave, data:Dynamic, filePath:String = "save/mixsave.json"):MixSaveWrapper {
180+
var wrapper = new MixSaveWrapper(mixSave, filePath);
181+
for (field in Reflect.fields(data)) {
182+
wrapper.mixSave.content.set(field, Reflect.field(data, field));
183+
}
184+
return wrapper;
185+
}
186+
187+
public static function newWithDefault(filePath:String = "save/mixsave.json"):MixSaveWrapper {
188+
var wrapper = new MixSaveWrapper(new MixSave(), filePath, false);
189+
if (!sys.FileSystem.exists(filePath)) {
190+
wrapper.mixSave.content = new Map();
191+
wrapper.save();
192+
} else {
193+
wrapper.load();
194+
}
195+
return wrapper;
196+
}
197+
198+
public function isEmpty():Bool {
199+
return mixSave.content.toArray().length <= 0;
200+
}
201+
202+
public function toString():String {
203+
return 'MixSaveWrapper(\n' +
204+
' filePath: "' + filePath + '",\n' +
205+
' fancyFormat: ' + Std.string(fancyFormat) + ',\n' +
206+
' content: ' + mixSave.content.toString() + '\n' +
207+
' customBehaviors: ' + mixSave.customBehaviors.toString() + '\n' +
208+
')';
209+
}
210+
public function toMap():Map<String, Dynamic> {
211+
return mixSave.content;
212+
}
213+
public function toDynamic():Dynamic {
214+
var result = {};
215+
for (field in mixSave.content.keys()) {
216+
Reflect.setField(result, field, mixSave.content.get(field));
217+
}
218+
return result;
219+
}
220+
public static function newMix(filePath = "save/mixsave.json"):MixSaveWrapper {
221+
return new MixSaveWrapper(new MixSave(), filePath);
222+
}
223+
public static function newMixWithData(data:Map<String, Dynamic>, filePath = "save/mixsave.json"):MixSaveWrapper {
224+
return newWithData(new MixSave(), data, filePath);
225+
}
226+
227+
public static function testFunctionSave():Void {
228+
var wrapper = new MixSaveWrapper(new MixSave(), "save/test.json");
229+
wrapper.addItemWithFunction("test", 5, macro function (value:Dynamic):String {
230+
return Std.string(value);
231+
}, macro function (value:String):Dynamic {
232+
return Std.parseInt(value);
233+
});
234+
trace(wrapper.toString());
235+
wrapper.save();
236+
}
237+
}
238+
239+
class ActiveSave extends MixSaveWrapper { // Work in progress
240+
public function new(?mixSave:MixSave, filePath:String = "save/activesave.json") {
241+
super(mixSave, filePath);
242+
}
243+
244+
override public function addObject(thing:Dynamic):Void {
245+
super.addObject(thing);
246+
save();
247+
}
248+
249+
override public function save():Void {
250+
super.save();
251+
}
252+
253+
override public function load():Void {
254+
super.load();
255+
}
256+
}

0 commit comments

Comments
 (0)