diff options
| author | raven <citrons@mondecitronne.com> | 2026-03-20 14:29:52 -0500 |
|---|---|---|
| committer | raven <citrons@mondecitronne.com> | 2026-03-20 14:29:52 -0500 |
| commit | c3d63652a4b80add587ee17f5c9f3773417203ad (patch) | |
| tree | e26e1d36f912f1bca210e1aaa3e314668d0b010b /server/data.go | |
initial commit
Diffstat (limited to 'server/data.go')
| -rw-r--r-- | server/data.go | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/server/data.go b/server/data.go new file mode 100644 index 0000000..b7ed280 --- /dev/null +++ b/server/data.go @@ -0,0 +1,87 @@ +package server + +import ( + "os" + "encoding/binary" + "git.citrons.xyz/metronode/phony" +) + +var dataManager struct { + phony.Inbox + errHand interface { + OnSaveError(from phony.Actor, err error) + OnLoadError(from phony.Actor, err error) + } +} + +type atomicWriter struct { + from phony.Actor + name string + tmpFile *os.File +} + +func createAtomic(from phony.Actor, name string) (atomicWriter, error) { + os.Mkdir("world", 0777) + f, err := os.CreateTemp("world", "*.tmp") + if err != nil { + dataManager.errHand.OnSaveError(from, err) + return atomicWriter {}, err + } + return atomicWriter {from, name, f}, nil +} + +func (f atomicWriter) Write(b []byte) (n int, err error) { + return f.tmpFile.Write(b) +} + +func (f atomicWriter) Close() error { + if f.tmpFile == nil { + return nil + } + dataManager.Act(f.from, func() { + err := f.tmpFile.Close() + if err != nil { + dataManager.errHand.OnSaveError(&dataManager, err) + return + } + err = os.Rename(f.tmpFile.Name(), f.name) + if err != nil { + dataManager.errHand.OnSaveError(&dataManager, err) + } + }) + return nil +} + +func saveDataFile[T any](from phony.Actor, name string, data T) { + f, err := createAtomic(from, "world/" + name + ".bin") + if err != nil { + dataManager.errHand.OnSaveError(from, err) + return + } + defer f.Close() + err = binary.Write(f, binary.BigEndian, data) + if err != nil { + dataManager.errHand.OnSaveError(from, err) + } +} + +func loadDataFile[T any]( + from phony.Actor, name string, reply func(data T, ok bool)) { + dataManager.Act(from, func() { + f, err := os.Open("world/" + name + ".bin") + if err != nil { + if !os.IsNotExist(err) { + dataManager.errHand.OnLoadError(&dataManager, err) + } + return + } + defer f.Close() + var data T + err = binary.Read(f, binary.BigEndian, &data) + if err != nil { + dataManager.errHand.OnLoadError(&dataManager, err) + } + from.Act(nil, func() {reply(data, err == nil)}) + }) +} + |
