summaryrefslogtreecommitdiff
path: root/engine/Dynamic
diff options
context:
space:
mode:
authorPhyscik <mynameisgennadiy@vk.com>2026-01-10 17:27:55 +0500
committerPhyscik <mynameisgennadiy@vk.com>2026-01-10 17:27:55 +0500
commita364d4330dfd34f953f64e90020f8b8d6f2e82c4 (patch)
treedb71d125f633832b130821f3aec07d4b714ab7bb /engine/Dynamic
parente6ccb74f77d0d03d33c422ca7dc942422074d7dd (diff)
World storage system change
Diffstat (limited to 'engine/Dynamic')
-rw-r--r--engine/Dynamic/Common.go23
-rw-r--r--engine/Dynamic/Descriptors/Assets.go5
-rw-r--r--engine/Dynamic/Descriptors/Tile.go24
-rw-r--r--engine/Dynamic/Descriptors/World.go28
-rw-r--r--engine/Dynamic/Manager.go51
-rw-r--r--engine/Dynamic/Package.go118
-rw-r--r--engine/Dynamic/Validation.go15
7 files changed, 264 insertions, 0 deletions
diff --git a/engine/Dynamic/Common.go b/engine/Dynamic/Common.go
new file mode 100644
index 0000000..99cfdc2
--- /dev/null
+++ b/engine/Dynamic/Common.go
@@ -0,0 +1,23 @@
+package dynamic
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+)
+
+func ReadJSONfromFile(fileLocation string, v any) error {
+ var file, openErr = os.ReadFile(fileLocation)
+ if openErr != nil {
+ return openErr
+ }
+ var jsonErr = json.Unmarshal(file, v)
+ if jsonErr != nil {
+ return jsonErr
+ }
+ return nil
+}
+
+func ConcantinateFileLocation(baseDirLocation string, appendix string) string {
+ return fmt.Sprintf("%v/%v", baseDirLocation, appendix)
+}
diff --git a/engine/Dynamic/Descriptors/Assets.go b/engine/Dynamic/Descriptors/Assets.go
new file mode 100644
index 0000000..864761d
--- /dev/null
+++ b/engine/Dynamic/Descriptors/Assets.go
@@ -0,0 +1,5 @@
+package descriptors
+
+type AssetsDescriptor struct {
+ Textures map[int]string `json:"textures"`
+}
diff --git a/engine/Dynamic/Descriptors/Tile.go b/engine/Dynamic/Descriptors/Tile.go
new file mode 100644
index 0000000..09c8c62
--- /dev/null
+++ b/engine/Dynamic/Descriptors/Tile.go
@@ -0,0 +1,24 @@
+package descriptors
+
+import rl "github.com/gen2brain/raylib-go/raylib"
+
+// Represents a type of a tile that can be used in the world
+type TileDescriptor struct {
+ Id uint64 `json:"id"`
+ Position rl.Vector2 `json:"position"`
+ TextureId int `json:"textureid"`
+ OveralyTextureId int `json:"overalytextureid"`
+}
+
+func (base *TileDescriptor) IsValid() error {
+ return nil
+}
+
+// Maps the tiles by IDs
+func MapTileDescriptors(data []*TileDescriptor) map[uint64]*TileDescriptor {
+ var outp = make(map[uint64]*TileDescriptor)
+ for _, v := range data {
+ outp[v.Id] = v
+ }
+ return outp
+}
diff --git a/engine/Dynamic/Descriptors/World.go b/engine/Dynamic/Descriptors/World.go
new file mode 100644
index 0000000..00e17f3
--- /dev/null
+++ b/engine/Dynamic/Descriptors/World.go
@@ -0,0 +1,28 @@
+package descriptors
+
+import rl "github.com/gen2brain/raylib-go/raylib"
+
+type WorldDescriptor struct {
+ Name string
+ // Deprecated
+ TileSize rl.Vector2 `json:"-"`
+ FloorMap []FloorPiece
+}
+
+func (base *WorldDescriptor) IsValid() error {
+ return nil
+}
+
+// Maps the world descriptor by IDs
+func MapWorldDescriptors(data []*WorldDescriptor) map[string]*WorldDescriptor {
+ var outp = make(map[string]*WorldDescriptor)
+ for _, v := range data {
+ outp[v.Name] = v
+ }
+ return outp
+}
+
+type FloorPiece struct {
+ Position rl.Vector2
+ TextureId uint64
+}
diff --git a/engine/Dynamic/Manager.go b/engine/Dynamic/Manager.go
new file mode 100644
index 0000000..7e5a567
--- /dev/null
+++ b/engine/Dynamic/Manager.go
@@ -0,0 +1,51 @@
+package dynamic
+
+import (
+ "fmt"
+ "os"
+
+ settings "github.com/DegustatorPonos/RuinesOfRafdolon/Settings"
+ rl "github.com/gen2brain/raylib-go/raylib"
+)
+
+// The collection of all avaliable packages that are loaded in the system
+type PackageManager struct {
+ AvaliablePackages map[string]Package
+}
+
+var Manager *PackageManager = nil
+
+func loadPackages() (*PackageManager, error) {
+ var dir, dirErr = os.ReadDir(settings.Current.PackagesLocation)
+ if dirErr != nil {
+ return nil, dirErr
+ }
+ var outp = PackageManager{
+ AvaliablePackages: make(map[string]Package),
+ }
+ for _, v := range dir {
+ var packagePath = ConcantinateFileLocation(settings.Current.PackagesLocation, v.Name())
+ var newPackage, packageErr = ReadPackage(v)
+ if packageErr != nil {
+ rl.TraceLog(rl.LogWarning, "Failed to load the module %v: %s", packagePath, packageErr.Error())
+ continue
+ }
+ newPackage.location = packagePath
+
+ // newPackage.LoadTiles()
+ newPackage.LoadWorlds()
+
+ outp.AvaliablePackages[newPackage.Description.Name] = *newPackage
+ rl.TraceLog(rl.LogInfo, "Loaded the module %s", newPackage.Description.Name)
+ }
+ return &outp, nil
+}
+
+// Loads the packages from the specified in settings directory. Panics on serious error
+func Init() {
+ var manager, err = loadPackages()
+ if err != nil {
+ panic(fmt.Sprintf("Failed to load packages: %v", err.Error()))
+ }
+ Manager = manager
+}
diff --git a/engine/Dynamic/Package.go b/engine/Dynamic/Package.go
new file mode 100644
index 0000000..8cabc91
--- /dev/null
+++ b/engine/Dynamic/Package.go
@@ -0,0 +1,118 @@
+package dynamic
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+
+ descriptors "github.com/DegustatorPonos/RuinesOfRafdolon/Dynamic/Descriptors"
+ settings "github.com/DegustatorPonos/RuinesOfRafdolon/Settings"
+ 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
+ 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 = ConcantinateFileLocation(settings.Current.PackagesLocation, dir.Name())
+ var desc = PackageDescription{}
+ if descErr := ReadValidJSONfromFile(ConcantinateFileLocation(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(ConcantinateFileLocation(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) LoadWorlds() {
+ if base.Description.Type != "story" {
+ return
+ }
+ var worlds, loadErr = loadWorldsFromDir(ConcantinateFileLocation(base.location, "Worlds"))
+ if loadErr != nil {
+ rl.TraceLog(rl.LogWarning, "Failed to load world from the module %s: %s", base.location, loadErr)
+ } else {
+ base.Worlds = worlds
+ }
+}
+
+// func (base *Package) LoadTiles() {
+ // var tiles, loadErr = loadTilesFromDir(ConcantinateFileLocation(base.location, "Worlds"))
+ // if loadErr != nil {
+ // rl.TraceLog(rl.LogWarning, "Failed to load tiles from the module %s: %s", base.location, loadErr)
+ // } else {
+ // base.Tiles = tiles
+ // }
+// }
+
+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 loadTilesFromDir(dirLocation string) (map[uint64]*descriptors.TileDescriptor, error) {
+ var loaded, err = loadAssetsFromDir(dirLocation, func() *descriptors.TileDescriptor{ return &descriptors.TileDescriptor{} })
+ if err != nil {
+ return nil, err
+ }
+ return descriptors.MapTileDescriptors(loaded), nil
+}
diff --git a/engine/Dynamic/Validation.go b/engine/Dynamic/Validation.go
new file mode 100644
index 0000000..dfe1d5c
--- /dev/null
+++ b/engine/Dynamic/Validation.go
@@ -0,0 +1,15 @@
+package dynamic
+
+type Validatable interface {
+ // If the object is returned invalid this function should return the reason
+ IsValid() error
+}
+
+// Reads object fron the file and validates it
+func ReadValidJSONfromFile(fileLocation string, v Validatable) error {
+ var err = ReadJSONfromFile(fileLocation, v)
+ if err != nil {
+ return err
+ }
+ return v.IsValid()
+}