package dynamic import ( "encoding/json" "fmt" "os" components "github.com/DegustatorPonos/RuinesOfRafdolon/Components" descriptors "github.com/DegustatorPonos/RuinesOfRafdolon/Dynamic/Descriptors" settings "github.com/DegustatorPonos/RuinesOfRafdolon/Settings" utils "github.com/DegustatorPonos/RuinesOfRafdolon/Utils" rl "github.com/gen2brain/raylib-go/raylib" ) // The defenition of the package type PackageDescription struct { Name string `json:"name"` Version uint64 `json:"version"` Type string `json:"type"` MinimumVersion *settings.AppVersion MaximumVersion *settings.AppVersion } func (base *PackageDescription) IsValid() error { if base.Name == "" { return fmt.Errorf("Invalid package descriptor: the name cannot be empty") } if base.Version == 0 { return fmt.Errorf("Invalid package descriptor: the version cannot be 0") } if base.MinimumVersion == nil { return fmt.Errorf("Invalid package descriptor: The package must specify the minimal version") } if !base.MinimumVersion.IsCompatible() || (base.MaximumVersion != nil && !base.MaximumVersion.IsLessThan(&settings.Current.Version)){ return fmt.Errorf("Invalid package descriptor: The package is made for the newer or older version") } return nil } // The dynamic collection of the things type Package struct { Description PackageDescription Textures *descriptors.TexturesDescriptor Objects map[string]*descriptors.ObjectDescriptor Worlds map[string]*descriptors.WorldDescriptor location string } func (base *Package) String() string { var outp, jsonErr = json.Marshal(base) if jsonErr != nil { return fmt.Sprintf("Failed to parse settings: %s", jsonErr.Error()) } return string(outp) } func ReadPackage(dir os.DirEntry) (*Package, error) { var dirPath = utils.JoinFileLocation(settings.Current.PackagesLocation, dir.Name()) var desc = PackageDescription{} if descErr := ReadValidJSONfromFile(utils.JoinFileLocation(dirPath, "Description.json"), &desc); descErr != nil { return nil, descErr } return &Package{ Description: desc, }, nil } func loadAssetsFromDir[T Validatable](dirLocation string, InitializeFunc func()T) ([]T, error) { var files, err = os.ReadDir(dirLocation) if err != nil { return nil, err } var outp = make([]T, 0) for _, v := range files { var new = InitializeFunc() var loadErr = ReadValidJSONfromFile(utils.JoinFileLocation(dirLocation, v.Name()), new) if loadErr != nil { rl.TraceLog(rl.LogWarning, "Failed to load the asset %s: %s", v.Name(), loadErr) continue } outp = append(outp, new) } return outp, nil } func (base *Package) ReadTextures() { var textures = &descriptors.TexturesDescriptor{} var texturesLocation = utils.JoinFileLocation(base.location, descriptors.TexturesDescriptorDirectoryName) var loadErr = utils.ReadJSONfromFile(utils.JoinFileLocation(texturesLocation, descriptors.TexturesDescriptorFileName), textures) if loadErr != nil { rl.TraceLog(rl.LogWarning, "Failed to load texture description from the module %s: %s", base.location, loadErr) } else { base.Textures = textures } } // Loads textures in the resource manager func (base *Package) LoadTextures() { for _, v := range base.Textures.Avaliable { var location = base.Textures.GetTexturePath(base.location, v) var displayName = fmt.Sprintf("%v/%v", base.Description.Name, v) components.Resources.Textures.LoadTexture(location, displayName) } } func (base *Package) ReadWorlds() { if base.Description.Type != "story" { return } var worlds, loadErr = loadWorldsFromDir(utils.JoinFileLocation(base.location, descriptors.WorldsDirName)) if loadErr != nil { rl.TraceLog(rl.LogWarning, "Failed to load world from the module %s: %s", base.location, loadErr) } else { base.Worlds = worlds } } // Loads worlds in the resource manager func (base *Package) LoadWorlds() { if base.Description.Type != "story" { return } for _, v := range base.Worlds { var parsed = v.Parse() components.Resources.Worlds[v.Name] = &parsed } } func (base *Package) ReadObjects() { var loaded, err = loadObjectsFromDir(utils.JoinFileLocation(base.location, descriptors.ObjectsDirName)) if err != nil { rl.TraceLog(rl.LogWarning, "Failed to load objects from the module %s: %s", base.location, err) return } base.Objects = loaded } // Loads objects in the resource manager func (base *Package) LoadObjects() { rl.TraceLog(rl.LogInfo, "%s", base.Objects) for _, v := range base.Objects { var parsed = v.Parse() var err = components.Resources.RegisterObject(base.Description.Name, v.Name, &parsed) if err != nil { rl.TraceLog(rl.LogWarning, "Failed to register object %s: %s", v.Name, err.Error()) } } } func loadWorldsFromDir(dirLocation string) (map[string]*descriptors.WorldDescriptor, error) { var loaded, err = loadAssetsFromDir(dirLocation, func() *descriptors.WorldDescriptor{ return &descriptors.WorldDescriptor{} }) if err != nil { return nil, err } return descriptors.MapWorldDescriptors(loaded), nil } func loadObjectsFromDir(dir string) (map[string]*descriptors.ObjectDescriptor, error) { var loaded, err = loadAssetsFromDir(dir, func() *descriptors.ObjectDescriptor { return &descriptors.ObjectDescriptor{} }) if err != nil { return nil, err } return descriptors.MapObjectDescriptors(loaded), nil }