z_mirror/fmm

git clone https://git.raiguard.me/z_mirror/fmm

Caleb HeuerMove log file parsing into the library27d8943

updating
2.1 KiB81 linesraw
1package fmm
2
3import (
4	"archive/zip"
5	"compress/zlib"
6	"errors"
7	"io"
8	"strings"
9)
10
11// Returns a slice of mod names and versions extracted from the given save
12// file.
13func ParseSaveFile(filepath string) ([]ModIdent, error) {
14	zipReader, err := zip.OpenReader(filepath)
15	if err != nil {
16		return nil, err
17	}
18	defer zipReader.Close()
19
20	var dat *zip.File
21	compressed := false
22	for _, file := range zipReader.File {
23		parts := strings.Split(file.Name, "/")
24		name := parts[len(parts)-1]
25		if name == "level.dat" || name == "level.dat0" {
26			dat = file
27			compressed = name == "level.dat0"
28			break
29		}
30	}
31	if dat == nil {
32		return nil, errors.New("invalid save file: could not locate level data")
33	}
34
35	rawReader, err := dat.Open()
36	if err != nil {
37		return nil, err
38	}
39	if compressed {
40		rawReader, err = zlib.NewReader(rawReader)
41	}
42	if err != nil {
43		return nil, err
44	}
45	defer rawReader.Close()
46
47	bytes, err := io.ReadAll(rawReader)
48	if err != nil {
49		return nil, err
50	}
51
52	datReader := newDatReader(bytes)
53
54	datReader.ReadUnoptimizedVersion()   // mapVersion
55	datReader.ReadUint8()                // branchVersion
56	datReader.ReadString()               // campaignName
57	datReader.ReadString()               // levelName
58	datReader.ReadString()               // modName
59	datReader.ReadUint8()                // difficulty
60	datReader.ReadBool()                 // finished
61	datReader.ReadBool()                 // playerWon
62	datReader.ReadString()               // nextLevel
63	datReader.ReadBool()                 // canContinue
64	datReader.ReadBool()                 // finishedButContinuing
65	datReader.ReadBool()                 // savingReplay
66	datReader.ReadBool()                 // allowNonAdminDebugOptions
67	datReader.ReadOptimizedVersion(true) // scenarioVersion
68	datReader.ReadUint8()                // scenarioBranchVersion
69	datReader.ReadUint8()                // allowedCommands
70
71	numMods := datReader.ReadUint16Optimized()
72	mods := make([]ModIdent, numMods)
73	for i := uint16(0); i < numMods; i += 1 {
74		mods[i] = datReader.ReadModWithCRC()
75	}
76
77	datReader.ReadUint32() // startupModSettingsCrc
78	// TODO: Startup mod settings PropertyTree
79
80	return mods, nil
81}