small racing game im working on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
class_name GhostData
extends Resource

var time: float
var checkpoints: Array
var snapped_checkpoints: Array
# i hope this is performant
var snaps: Array# it doesnt let me type it
var snap_count := 0

func snapshot(obj: Car):
	snaps.append(CarVars.create(obj))
	snap_count += 1

## returns a CarVars array
func load_snap(i: int) -> PackedFloat32Array:
	return snaps[i]

func save(path: String) -> void:
	GhostData._save_file(path, {checkpoints = checkpoints, snapped_checkpoints = snapped_checkpoints, time = time, snaps = snaps, snap_count = snap_count})

func mkarr(size: int) -> Array:
	var arr := []
	arr.resize(size)
	arr.fill(-1)
	return arr

func _init(num_checkpoints := 0, laps := 0) -> void:
	for i in laps:
		checkpoints.append(mkarr(num_checkpoints + 1))
		snapped_checkpoints.append(mkarr(num_checkpoints + 1))

func clear() -> void:
	for lap in checkpoints:
		lap.fill(-1)
	snaps.clear()
	time = 0
	snap_count = 0

func collect(lap: int, cp: int, now: float) -> void:
	checkpoints[lap][cp] = now
	snapped_checkpoints[lap][cp] = snap_count
	if lap == len(checkpoints) - 1 && cp == -1:
		time = now

func has_collected(lap: int, cp: int) -> bool:
	return checkpoints[lap][cp] != -1

func get_time(lap: int, cp: int) -> float:
	return checkpoints[lap][cp]

static func from_d(d: Dictionary) -> GhostData:
	var obj := GhostData.new()
	obj.time = d.time
	obj.checkpoints = d.checkpoints
	obj.snapped_checkpoints = d.snapped_checkpoints
	obj.snap_count = d.snap_count
	obj.snaps = d.snaps
	return obj

## Saves a basic dictionary to a path.
static func _save_file(path: String, data: Dictionary) -> void:
	var file := FileAccess.open_compressed(path, FileAccess.WRITE, FileAccess.COMPRESSION_ZSTD)
	file.store_buffer(var_to_bytes(data))

## Loads a basic dictionary out of a file.
static func _load_file(path: String) -> Dictionary:
	if FileAccess.file_exists(path):
		var file := FileAccess.open_compressed(path, FileAccess.READ, FileAccess.COMPRESSION_ZSTD)
		var text := file.get_buffer(file.get_length())
		var dict := {}
		if text:
			dict = bytes_to_var(text)
		return dict
	_save_file(path, {})  # create file if it doesn't exist
	return {}

## Creates a [GhostData] from a file
static func _load(path: String) -> GhostData:
	var res := _load_file(path)
	if res.is_empty():
		return null
	return GhostData.from_d(res)