From 658ad890f5008409320fe8aa4bfd0106ad0c1db1 Mon Sep 17 00:00:00 2001 From: zomo Date: Thu, 18 Dec 2025 01:26:45 -0600 Subject: [PATCH] init --- .gitignore | 2 + assignroom.go | 29 ++++++++ go.mod | 5 ++ go.sum | 2 + ini.go | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++ loadrooms.go | 131 ++++++++++++++++++++++++++++++++ main.go | 22 ++++++ out.go | 82 ++++++++++++++++++++ 8 files changed, 474 insertions(+) create mode 100644 .gitignore create mode 100644 assignroom.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 ini.go create mode 100644 loadrooms.go create mode 100644 main.go create mode 100644 out.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fac085f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +rooms +rooms_out diff --git a/assignroom.go b/assignroom.go new file mode 100644 index 0000000..f346d7e --- /dev/null +++ b/assignroom.go @@ -0,0 +1,29 @@ +package main + +func AssignExtraRooms(rooms []RoomFolder, roomsPerNight int) { + latestnight := 0 + + for _, r := range rooms { + if r.cfg.night > latestnight { + latestnight = r.cfg.night + } + } + + night := latestnight + 1 + room := 1 + + for i, r := range rooms { + if r.cfg.night > 0 { + continue + } + + rooms[i].cfg.night = night + rooms[i].cfg.room = room + + room++ + if room > roomsPerNight { + room = 1 + night++ + } + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..31e9e60 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module zomo.dev/bappackage + +go 1.25.0 + +require gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a8937af --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/ini.go b/ini.go new file mode 100644 index 0000000..b751d57 --- /dev/null +++ b/ini.go @@ -0,0 +1,201 @@ +package main + +import ( + "fmt" + "strconv" + + "gopkg.in/ini.v1" +) + +type RoomIni struct { + night int + room int + + size float64 + speed float64 + fov float64 + textureRepeat float64 + roomHeight float64 + layerFrames int + fogColor int + fogEnd float64 + miniSpeed float64 +} + +func (r *RoomIni) ToIni() string { + f := func(n float64) string { + return strconv.FormatFloat(n, 'f', -1, 64) + } + + return fmt.Sprintf(` +[NIGHT_%d_ROOM_%d] +size=%s +speed=%s +FOV=%s +Texture_Repeat=%s +Room_Height=%s +Layer_Frames=%d +Fog_Color=%d +Fog_End=%s +Mini_speed=%s +`, + r.night, r.room, + f(r.size), f(r.speed), + f(r.fov), f(r.textureRepeat), + f(r.roomHeight), r.layerFrames, + r.fogColor, f(r.fogEnd), + f(r.miniSpeed), +) +} + +func NewRoomIni() RoomIni { + return RoomIni { + night: -1, + room: -1, + + size: 1, + speed: 1, + fov: 55, + textureRepeat: 3, + roomHeight: 350, + layerFrames: 1, + fogColor: 0, + fogEnd: -1, + miniSpeed: 1, + } +} + +func ReadIni(path string) (RoomIni, error) { + cfg, err := ini.InsensitiveLoad(path) + if err != nil { + return RoomIni{}, err + } + + + meta, err := cfg.GetSection("DEFAULT") + if err != nil { + return RoomIni{}, fmt.Errorf("unable to load DEFAULT section in %s: %+v", path, err) + } + + sections := cfg.Sections() + var room *ini.Section = nil + + for _, sec := range sections { + if room != nil { + fmt.Printf("WARN: extra section in %s, section: %s\n", path, sec.Name()) + continue + } + if sec.Name() != "default" { + room = sec + } + } + + roomIni, err := loadIni(meta, room) + if err != nil { + return RoomIni{}, fmt.Errorf("ERROR: error loading ini from %s: %+v", path, err) + } + + return roomIni, nil +} + +func loadIni(meta *ini.Section, room *ini.Section) (RoomIni, error) { + roomini := RoomIni{} + + if val, err := loadInt(meta, "night", -1); err != nil { + return RoomIni{}, err + } else { + roomini.night = val + } + + if val, err := loadInt(meta, "room", -1); err != nil { + return RoomIni{}, err + } else { + roomini.room = val + } + + if roomini.night > 0 && roomini.room < 1 { + return RoomIni{}, fmt.Errorf("night is set but room is not set") + } + + + if val, err := loatFloat(room, "size", 1); err != nil { + return RoomIni{}, err + } else { + roomini.size = val + } + + if val, err := loatFloat(room, "speed", 1); err != nil { + return RoomIni{}, err + } else { + roomini.speed = val + } + + if val, err := loatFloat(room, "fov", 55); err != nil { + return RoomIni{}, err + } else { + roomini.fov = val + } + + if val, err := loatFloat(room, "texture_repeat", 3); err != nil { + return RoomIni{}, err + } else { + roomini.textureRepeat = val + } + + if val, err := loatFloat(room, "room_height", 350); err != nil { + return RoomIni{}, err + } else { + roomini.roomHeight = val + } + + if val, err := loadInt(room, "layer_frames", 1); err != nil { + return RoomIni{}, err + } else { + roomini.layerFrames = val + } + + if val, err := loadInt(room, "fog_color", 0); err != nil { + return RoomIni{}, err + } else { + roomini.fogColor = val + } + + if val, err := loatFloat(room, "fog_end", -1); err != nil { + return RoomIni{}, err + } else { + roomini.fogEnd = val + } + + if val, err := loatFloat(room, "mini_speed", 1); err != nil { + return RoomIni{}, err + } else { + roomini.miniSpeed = val + } + + return roomini, nil + +} + +func loadInt(sec *ini.Section, key string, def int) (int, error) { + val, err := sec.GetKey(key) + if err != nil { + return def, nil + } + valint, err := val.Int() + if err != nil { + return def, err + } + return valint, nil +} + +func loatFloat(sec *ini.Section, key string, def float64) (float64, error) { + val, err := sec.GetKey(key) + if err != nil { + return def, nil + } + valfloat, err := val.Float64() + if err != nil { + return def, err + } + return valfloat, nil +} diff --git a/loadrooms.go b/loadrooms.go new file mode 100644 index 0000000..0074101 --- /dev/null +++ b/loadrooms.go @@ -0,0 +1,131 @@ +package main + +import ( + "fmt" + "os" + "path" + "path/filepath" + "slices" + "strings" +) + +var REQUIRED_IMAGES = []string{ + "ART", + "MINI", + "CREDIT", + "INTERACT", + "FLOOR", + "LAYER", + "ROOF", + "WALL", +} +var ACCEPTED_IMAGE_EXT = []string{ + ".PNG", + ".JPG", + ".BMP", +} + +var REQUIRED_AUDIO = []string{ + "FOOT", + "MUSIC", +} +var ACCEPTED_AUDIO_EXT = []string{ + ".WAV", + ".MP3", + ".OGG", + ".MIDI", +} + +type RoomFolder struct { + path string + cfg RoomIni +} + +func LoadRoomFolders(roomspath string) ([]RoomFolder, error) { + entries, err := os.ReadDir(roomspath) + if err != nil { + return nil, err + } + + rooms := make([]RoomFolder, 0) + + for _, entry := range entries { + entrypath := filepath.Join(roomspath, entry.Name()) + if !entry.IsDir() { + fmt.Printf("WARN: unexpected non-directory found in rooms directory: %s\n", entrypath) + continue + } + + roomfolder, err := loadRoom(entrypath) + if err != nil { + fmt.Printf("ERROR: unable to load directory: %s\n", entrypath) + continue + } + + rooms = append(rooms, roomfolder) + } + + return rooms, nil +} + +func loadRoom(roompath string) (RoomFolder, error) { + entries, err := os.ReadDir(roompath) + if err != nil { + return RoomFolder{}, err + } + + requiredImages := make([]string, len(REQUIRED_IMAGES)) + copy(requiredImages, REQUIRED_IMAGES) + requiredAudio := make([]string, len(REQUIRED_AUDIO)) + copy(requiredAudio, REQUIRED_AUDIO) + + roominiName := "" + for _, entry := range entries { + filename := entry.Name() + if strings.ToLower(filename) == "room.ini" { + roominiName = filename + } + + ext := strings.ToUpper(path.Ext(filename)) + name := strings.ToUpper(filename[:len(filename)-len(ext)]) + + if index := slices.Index(requiredImages, name); index > -1 && slices.Contains(ACCEPTED_IMAGE_EXT, ext) { + requiredImages = append(requiredImages[:index], requiredImages[index+1:]...) + } + + if index := slices.Index(requiredAudio, name); index > -1 && slices.Contains(ACCEPTED_AUDIO_EXT, ext) { + requiredAudio = append(requiredAudio[:index], requiredAudio[index+1:]...) + } + } + + errormsg := "" + if len(requiredImages) > 0 && len(requiredAudio) > 0 { + errormsg = fmt.Sprintf("images: %v, audio: %v", requiredImages, requiredAudio) + } + if len(requiredImages) > 0 { + errormsg = fmt.Sprintf("images: %v", requiredImages) + } + if len(requiredAudio) > 0 { + errormsg = fmt.Sprintf("audio: %v", requiredAudio) + } + + if errormsg != "" { + return RoomFolder{}, fmt.Errorf("unable to load room %s: missing required %s", roompath, errormsg) + } + + cfg := NewRoomIni() + if roominiName != "" { + newcfg, err := ReadIni(filepath.Join(roompath, "room.ini")) + if err != nil { + return RoomFolder{}, err + } + cfg = newcfg + } + + return RoomFolder{ + path: roompath, + cfg: cfg, + }, nil +} + + diff --git a/main.go b/main.go new file mode 100644 index 0000000..4dcc925 --- /dev/null +++ b/main.go @@ -0,0 +1,22 @@ +package main + +const BASEPATH = "./rooms" +const OUTPATH = "./rooms_out" +const ROOM_PER_NIGHT = 4 + +func main() { + if err := mainErr(); err != nil { + panic(err) + } +} + +func mainErr() error { + roomFolders, err := LoadRoomFolders(BASEPATH) + if err != nil { + return err + } + + AssignExtraRooms(roomFolders, ROOM_PER_NIGHT) + + return CopyOut(roomFolders, OUTPATH) +} diff --git a/out.go b/out.go new file mode 100644 index 0000000..4ca6f96 --- /dev/null +++ b/out.go @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "os" + "path" + "path/filepath" + "strings" +) + +const FILEPERM = 0644 +const INIPREFIX = `[SETTINGS] +Sensitivity=6 +Splash1len=2 +Splash2len=2 +` + +func CopyOut(roomFolders []RoomFolder, outpath string) error { + inistr := INIPREFIX + + for _, roomFolder := range roomFolders { + err := copyFolder(roomFolder, outpath) + if err != nil { + return fmt.Errorf("error copying folder %s: %+v", roomFolder.path, err) + } + inistr += roomFolder.cfg.ToIni() + } + + outini := filepath.Join(outpath, "CF.ini") + fmt.Printf("Writing %s\n", outini) + return os.WriteFile(outini, []byte(inistr), FILEPERM) +} + +func copyFolder(roomFolder RoomFolder, outpath string) error { + nightdir := fmt.Sprintf("NIGHT_%d", roomFolder.cfg.night) + roomdir := fmt.Sprintf("ROOM_%d", roomFolder.cfg.room) + + roomoutpath := filepath.Join(outpath, "DATA", nightdir, roomdir) + + os.MkdirAll(roomoutpath, FILEPERM) + fmt.Printf(`Copying: + %s + to %s +`, roomFolder.path, roomoutpath) + + entries, err := os.ReadDir(roomFolder.path) + if err != nil { + return err + } + + for _, entry := range entries { + // TODO whitelist files? + entrypath := path.Join(roomFolder.path, entry.Name()) + + if entry.IsDir() { + fmt.Printf("WARN: unexpected folder found in room folder: %s\n", entrypath) + continue + } + + if strings.ToLower(entry.Name()) == "room.ini" { + continue + } + + topath := path.Join(roomoutpath, entry.Name()) + + err := copyFile(entrypath, topath) + if err != nil { + return err + } + } + + return nil +} + +func copyFile(from, to string) error { + fromdata, err := os.ReadFile(from) + if err != nil { + return err + } + + return os.WriteFile(to, fromdata, FILEPERM) +}