commit 658ad890f5008409320fe8aa4bfd0106ad0c1db1 Author: zomo Date: Thu Dec 18 01:26:45 2025 -0600 init 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) +}