-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilesystem.go
128 lines (109 loc) · 2.99 KB
/
filesystem.go
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package filesystem
import (
"bytes"
"github.com/galaco/bsp/lumps"
"github.com/galaco/vpk2"
"io"
"io/ioutil"
"os"
"strings"
)
// FileSystem
type FileSystem struct {
gameVPKs map[string]vpk.VPK
localDirectories []string
pakFile *lumps.Pakfile
}
// NewFileSystem returns a new filesystem
func NewFileSystem() *FileSystem {
return &FileSystem{
gameVPKs: map[string]vpk.VPK{},
localDirectories: make([]string, 0),
pakFile: nil,
}
}
// PakFile returns loaded pakfile
// There can only be 1 registered pakfile at once.
func (fs *FileSystem) PakFile() *lumps.Pakfile {
return fs.pakFile
}
// RegisterVpk registers a vpk package as a valid
// asset directory
func (fs *FileSystem) RegisterVpk(path string, vpkFile *vpk.VPK) {
fs.gameVPKs[path] = *vpkFile
}
func (fs *FileSystem) UnregisterVpk(path string) {
for key := range fs.gameVPKs {
if key == path {
delete(fs.gameVPKs, key)
}
}
}
// RegisterLocalDirectory register a filesystem path as a valid
// asset directory
func (fs *FileSystem) RegisterLocalDirectory(directory string) {
fs.localDirectories = append(fs.localDirectories, directory)
}
func (fs *FileSystem) UnregisterLocalDirectory(directory string) {
for idx, dir := range fs.localDirectories {
if dir == directory {
if len(fs.localDirectories) == 1 {
fs.localDirectories = make([]string, 0)
return
}
fs.localDirectories = append(fs.localDirectories[:idx], fs.localDirectories[idx+1:]...)
}
}
}
// RegisterPakFile Set a pakfile to be used as an asset directory.
// This would normally be called during each map load
func (fs *FileSystem) RegisterPakFile(pakFile *lumps.Pakfile) {
fs.pakFile = pakFile
}
// UnregisterPakFile removes the current pakfile from
// available search locations
func (fs *FileSystem) UnregisterPakFile() {
fs.pakFile = nil
}
// EnumerateResourcePaths returns all registered resource paths.
// PakFile is excluded.
func (fs *FileSystem) EnumerateResourcePaths() []string {
list := make([]string, 0)
for idx := range fs.gameVPKs {
list = append(list, string(idx))
}
list = append(list, fs.localDirectories...)
return list
}
// GetFile attempts to get stream for filename.
// Search order is Pak->FileSystem->VPK
func (fs *FileSystem) GetFile(filename string) (io.Reader, error) {
// sanitise file
searchPath := NormalisePath(strings.ToLower(filename))
// try to read from pakfile first
if fs.pakFile != nil {
f, err := fs.pakFile.GetFile(searchPath)
if err == nil && f != nil && len(f) != 0 {
return bytes.NewReader(f), nil
}
}
// Fallback to local filesystem
for _, dir := range fs.localDirectories {
if _, err := os.Stat(dir + "\\" + searchPath); os.IsNotExist(err) {
continue
}
file, err := ioutil.ReadFile(dir + searchPath)
if err != nil {
return nil, err
}
return bytes.NewBuffer(file), nil
}
// Fall back to game vpk
for _, vfs := range fs.gameVPKs {
entry := vfs.Entry(searchPath)
if entry != nil {
return entry.Open()
}
}
return nil, NewFileNotFoundError(filename)
}