From a06787411dc4ea6734ae6bbeb6ebb5d279dd0751 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Thu, 18 Apr 2024 22:12:56 -0700 Subject: [PATCH] Resolve circular import errors for Doodle++ plugin * pkg/plus/dpp is the main plugin bridge, and defines nothing but an interface that defines the Doodle++ surface area (referring to internal game types such as doodad.Doodad or level.Level), but not their implementations. * dpp.Driver (an interface) is the main API that other parts of the game will call, for example "dpp.Driver.IsLevelSigned()" * plus_dpp.go and plus_foss.go provide the dpp.Driver implementation for their build; with plus_dpp.go generally forwarding function calls directly to the proprietary dpp package and plus_foss.go generally returning false/errors. * The bootstrap package simply assigns the above stub function to dpp.Driver * pkg/plus/bootstrap is a package directly imported by main (in the doodle and doodad programs) and it works around circular dependency issues: this package simply assigns dpp.Driver to the DPP or FOSS version. Miscellaneous fixes: * File->Open in the editor and PlayScene will use the new Open Level window instead of loading the legacy GotoLoadMenu scene. * Deprecated legacy scenes: d.GotoLoadMenu() and d.GotoPlayMenu(). * The doodle-admin program depends on the private dpp package, so can not be compiled in FOSS mode. --- cmd/doodad/main.go | 3 ++ cmd/doodle-admin/command/key.go | 2 +- cmd/doodle-admin/command/sign.go | 2 +- cmd/doodle-admin/command/sign_level.go | 4 +- cmd/doodle-admin/command/verify.go | 2 +- cmd/doodle-admin/command/verify_level.go | 4 +- cmd/doodle/main.go | 3 ++ pkg/branding/builds/builds.go | 4 +- pkg/editor_scene.go | 9 ++-- pkg/editor_ui_doodad.go | 4 +- pkg/editor_ui_menubar.go | 24 +++++++-- pkg/editor_ui_popups.go | 4 +- .../giant_screenshot/giant_screenshot.go | 4 +- .../giant_screenshot/regular_screenshot.go | 4 +- pkg/level/publishing/publishing.go | 7 ++- pkg/main_scene.go | 4 +- pkg/menu_scene.go | 4 ++ pkg/native/username.go | 8 +-- pkg/play_scene.go | 10 ++-- pkg/play_scene_menubar.go | 21 +++++++- pkg/plus/bootstrap/bootstrap_dpp.go | 21 ++++++++ pkg/plus/bootstrap/bootstrap_foss.go | 14 +++++ pkg/plus/dpp/plugin.go | 21 ++++++++ pkg/plus/dpp/plus_dpp.go | 54 +++++++++++++++++-- pkg/plus/dpp/plus_foss.go | 46 ++++++++++++++++ pkg/plus/foss/plus_foss.go | 22 -------- pkg/plus/initdpp/plus_dpp.go | 24 --------- pkg/plus/initdpp/plus_foss.go | 22 -------- pkg/plus/initdpp/plus_init.go | 1 - pkg/plus/plus.go | 12 ++--- pkg/uix/canvas_actors.go | 9 ++-- pkg/windows/license_key.go | 9 ++-- 32 files changed, 253 insertions(+), 129 deletions(-) create mode 100644 pkg/plus/bootstrap/bootstrap_dpp.go create mode 100644 pkg/plus/bootstrap/bootstrap_foss.go create mode 100644 pkg/plus/dpp/plugin.go create mode 100644 pkg/plus/dpp/plus_foss.go delete mode 100644 pkg/plus/foss/plus_foss.go delete mode 100644 pkg/plus/initdpp/plus_dpp.go delete mode 100644 pkg/plus/initdpp/plus_foss.go delete mode 100644 pkg/plus/initdpp/plus_init.go diff --git a/cmd/doodad/main.go b/cmd/doodad/main.go index 01f4754..9d626d5 100644 --- a/cmd/doodad/main.go +++ b/cmd/doodad/main.go @@ -10,6 +10,7 @@ import ( "git.kirsle.net/SketchyMaze/doodle/cmd/doodad/commands" "git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds" "git.kirsle.net/SketchyMaze/doodle/pkg/log" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/bootstrap" "github.com/urfave/cli/v2" ) @@ -26,6 +27,8 @@ func init() { } func main() { + bootstrap.InitPlugins() + app := cli.NewApp() app.Name = "doodad" app.Usage = "command line interface for Doodle" diff --git a/cmd/doodle-admin/command/key.go b/cmd/doodle-admin/command/key.go index 671728d..4d2382a 100644 --- a/cmd/doodle-admin/command/key.go +++ b/cmd/doodle-admin/command/key.go @@ -1,8 +1,8 @@ package command import ( - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" + "git.kirsle.net/SketchyMaze/dpp/license" "github.com/urfave/cli/v2" ) diff --git a/cmd/doodle-admin/command/sign.go b/cmd/doodle-admin/command/sign.go index e14684b..aeb0ed5 100644 --- a/cmd/doodle-admin/command/sign.go +++ b/cmd/doodle-admin/command/sign.go @@ -4,8 +4,8 @@ import ( "fmt" "io/ioutil" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" + "git.kirsle.net/SketchyMaze/dpp/license" "github.com/urfave/cli/v2" ) diff --git a/cmd/doodle-admin/command/sign_level.go b/cmd/doodle-admin/command/sign_level.go index c49d0bf..bd7c526 100644 --- a/cmd/doodle-admin/command/sign_level.go +++ b/cmd/doodle-admin/command/sign_level.go @@ -6,8 +6,8 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" - "git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning" + "git.kirsle.net/SketchyMaze/dpp/license" + "git.kirsle.net/SketchyMaze/dpp/license/levelsigning" "github.com/urfave/cli/v2" ) diff --git a/cmd/doodle-admin/command/verify.go b/cmd/doodle-admin/command/verify.go index 8922c9d..ddb9a41 100644 --- a/cmd/doodle-admin/command/verify.go +++ b/cmd/doodle-admin/command/verify.go @@ -4,8 +4,8 @@ import ( "io/ioutil" "time" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" + "git.kirsle.net/SketchyMaze/dpp/license" "github.com/urfave/cli/v2" ) diff --git a/cmd/doodle-admin/command/verify_level.go b/cmd/doodle-admin/command/verify_level.go index b7a695b..0a0d24e 100644 --- a/cmd/doodle-admin/command/verify_level.go +++ b/cmd/doodle-admin/command/verify_level.go @@ -5,9 +5,9 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" - "git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning" "git.kirsle.net/SketchyMaze/doodle/pkg/log" + "git.kirsle.net/SketchyMaze/dpp/license" + "git.kirsle.net/SketchyMaze/dpp/license/levelsigning" "github.com/urfave/cli/v2" ) diff --git a/cmd/doodle/main.go b/cmd/doodle/main.go index b8e16ca..c1b36c2 100644 --- a/cmd/doodle/main.go +++ b/cmd/doodle/main.go @@ -20,6 +20,7 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/gamepad" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/native" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/bootstrap" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/sound" "git.kirsle.net/SketchyMaze/doodle/pkg/sprites" @@ -51,6 +52,8 @@ func init() { func main() { runtime.LockOSThread() + bootstrap.InitPlugins() + app := cli.NewApp() app.Name = "doodle" app.Usage = fmt.Sprintf("%s - %s", branding.AppName, branding.Summary) diff --git a/pkg/branding/builds/builds.go b/pkg/branding/builds/builds.go index cf2b3d8..d91cd26 100644 --- a/pkg/branding/builds/builds.go +++ b/pkg/branding/builds/builds.go @@ -6,7 +6,7 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/branding" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" ) var ( @@ -26,7 +26,7 @@ var ( func init() { if !balance.DPP { VersionSuffix = " (open source)" - } else if !license.IsRegistered() { + } else if !dpp.Driver.IsRegistered() { VersionSuffix = " (shareware)" } else { VersionSuffix = "" diff --git a/pkg/editor_scene.go b/pkg/editor_scene.go index 07cc711..bdb10d7 100644 --- a/pkg/editor_scene.go +++ b/pkg/editor_scene.go @@ -15,16 +15,17 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/level/giant_screenshot" "git.kirsle.net/SketchyMaze/doodle/pkg/level/publishing" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen" "git.kirsle.net/SketchyMaze/doodle/pkg/native" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/doodle/pkg/usercfg" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/windows" "git.kirsle.net/go/render" "git.kirsle.net/go/render/event" + "git.kirsle.net/go/ui" ) // EditorScene manages the "Edit Level" game mode. @@ -55,6 +56,8 @@ type EditorScene struct { filename string lastAutosaveAt time.Time + + winOpenLevel *ui.Window } // Name of the scene. @@ -252,7 +255,7 @@ func (s *EditorScene) setupAsync(d *Doodle) error { func (s *EditorScene) installActors() error { if err := s.UI.Canvas.InstallActors(s.Level.Actors); err != nil { summary := "This level references some doodads that were not found:" - if strings.Contains(err.Error(), license.ErrRegisteredFeature.Error()) { + if strings.Contains(err.Error(), plus.ErrRegisteredFeature.Error()) { summary = "This level contains embedded doodads, but this is not\n" + "available in the free version of the game. The following\n" + "doodads could not be loaded:" @@ -507,7 +510,7 @@ func (s *EditorScene) LoadLevel(filename string) error { log.Info("Installing %d actors into the drawing", len(level.Actors)) if err := s.UI.Canvas.InstallActors(level.Actors); err != nil { summary := "This level references some doodads that were not found:" - if strings.Contains(err.Error(), license.ErrRegisteredFeature.Error()) { + if strings.Contains(err.Error(), plus.ErrRegisteredFeature.Error()) { summary = "This level contains embedded doodads, but this is not\n" + "available in the free version of the game. The following\n" + "doodads could not be loaded:" diff --git a/pkg/editor_ui_doodad.go b/pkg/editor_ui_doodad.go index f0f3436..7bd7bd6 100644 --- a/pkg/editor_ui_doodad.go +++ b/pkg/editor_ui_doodad.go @@ -9,7 +9,7 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/log" - "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/uix" "git.kirsle.net/go/render" ) @@ -35,7 +35,7 @@ func (u *EditorUI) startDragActor(doodad *doodads.Doodad, actor *level.Actor) { if doodad == nil { if actor != nil { - obj, err := plus.DoodadFromEmbeddable(actor.Filename, u.Scene.Level, false) + obj, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, u.Scene.Level, false) if err != nil { log.Error("startDragExistingActor: actor doodad name %s not found: %s", actor.Filename, err) return diff --git a/pkg/editor_ui_menubar.go b/pkg/editor_ui_menubar.go index fc3b961..d9f9fe0 100644 --- a/pkg/editor_ui_menubar.go +++ b/pkg/editor_ui_menubar.go @@ -9,10 +9,11 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/drawtool" "git.kirsle.net/SketchyMaze/doodle/pkg/enum" "git.kirsle.net/SketchyMaze/doodle/pkg/level/giant_screenshot" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/native" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" + "git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/windows" "git.kirsle.net/go/render" @@ -282,7 +283,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar { // Registration item for Doodle++ builds. if balance.DPP { var registerText = "Register" - if license.IsRegistered() { + if dpp.Driver.IsRegistered() { registerText = "Registration" } @@ -318,7 +319,24 @@ func (s *EditorScene) MenuNewDoodad() { // File->Open, or Ctrl-O func (s *EditorScene) MenuOpen() { s.ConfirmUnload(func() { - s.d.GotoLoadMenu() + if s.winOpenLevel == nil { + s.winOpenLevel = windows.NewOpenDrawingWindow(windows.OpenDrawing{ + Supervisor: s.UI.Supervisor, + Engine: shmem.CurrentRenderEngine, + OnOpenDrawing: func(filename string) { + s.d.EditFile(filename) + }, + OnCloseWindow: func() { + s.winOpenLevel.Destroy() + s.winOpenLevel = nil + }, + }) + } + s.winOpenLevel.MoveTo(render.Point{ + X: (s.d.width / 2) - (s.winOpenLevel.Size().W / 2), + Y: (s.d.height / 2) - (s.winOpenLevel.Size().H / 2), + }) + s.winOpenLevel.Show() }) } diff --git a/pkg/editor_ui_popups.go b/pkg/editor_ui_popups.go index ffbe44d..45feaae 100644 --- a/pkg/editor_ui_popups.go +++ b/pkg/editor_ui_popups.go @@ -9,9 +9,9 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/drawtool" "git.kirsle.net/SketchyMaze/doodle/pkg/level" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/modal" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/windows" "git.kirsle.net/go/render" "git.kirsle.net/go/ui" @@ -68,7 +68,7 @@ func (u *EditorUI) OpenPublishWindow() { OnPublish: func(includeBuiltins bool) { u.d.FlashError("OnPublish Called") // XXX: Paid Version Only. - if !license.IsRegistered() { + if !dpp.Driver.IsRegistered() { if u.licenseWindow != nil { u.licenseWindow.Show() u.Supervisor.FocusWindow(u.licenseWindow) diff --git a/pkg/level/giant_screenshot/giant_screenshot.go b/pkg/level/giant_screenshot/giant_screenshot.go index d9c3ed3..e76b439 100644 --- a/pkg/level/giant_screenshot/giant_screenshot.go +++ b/pkg/level/giant_screenshot/giant_screenshot.go @@ -11,7 +11,7 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/log" - "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/SketchyMaze/doodle/pkg/wallpaper" @@ -95,7 +95,7 @@ func GiantScreenshot(lvl *level.Level) (image.Image, error) { // Render the doodads. log.Debug("GiantScreenshot: Render actors...") for _, actor := range lvl.Actors { - doodad, err := plus.DoodadFromEmbeddable(actor.Filename, lvl, false) + doodad, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, lvl, false) if err != nil { log.Error("GiantScreenshot: Load doodad: %s", err) continue diff --git a/pkg/level/giant_screenshot/regular_screenshot.go b/pkg/level/giant_screenshot/regular_screenshot.go index 4ece9d7..9c7e994 100644 --- a/pkg/level/giant_screenshot/regular_screenshot.go +++ b/pkg/level/giant_screenshot/regular_screenshot.go @@ -14,7 +14,7 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/log" - "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/userdir" "git.kirsle.net/go/render" "golang.org/x/image/draw" @@ -78,7 +78,7 @@ func CroppedScreenshot(lvl *level.Level, viewport render.Rect) (image.Image, err // Render the doodads. log.Debug("CroppedScreenshot: Render actors...") for _, actor := range lvl.Actors { - doodad, err := plus.DoodadFromEmbeddable(actor.Filename, lvl, false) + doodad, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, lvl, false) if err != nil { log.Error("CroppedScreenshot: Load doodad: %s", err) continue diff --git a/pkg/level/publishing/publishing.go b/pkg/level/publishing/publishing.go index 42e5eeb..d31034b 100644 --- a/pkg/level/publishing/publishing.go +++ b/pkg/level/publishing/publishing.go @@ -17,9 +17,8 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/level" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" - "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" ) /* @@ -38,7 +37,7 @@ func Publish(lvl *level.Level) error { } // Registered games only. - if !balance.DPP || !license.IsRegistered() { + if !balance.DPP || !dpp.Driver.IsRegistered() { return errors.New("only registered versions of the game can attach doodads to levels") } @@ -53,7 +52,7 @@ func Publish(lvl *level.Level) error { log.Debug("Embed filename: %s", filename) names[filename] = nil - doodad, err := plus.DoodadFromEmbeddable(filename, lvl, false) + doodad, err := dpp.Driver.LoadFromEmbeddable(filename, lvl, false) if err != nil { return fmt.Errorf("couldn't load doodad %s: %s", filename, err) } diff --git a/pkg/main_scene.go b/pkg/main_scene.go index 22cca58..8666a36 100644 --- a/pkg/main_scene.go +++ b/pkg/main_scene.go @@ -9,10 +9,10 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds" "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen" "git.kirsle.net/SketchyMaze/doodle/pkg/native" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/savegame" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem" @@ -225,7 +225,7 @@ func (s *MainScene) Setup(d *Doodle) error { { Name: "Register", If: func() bool { - return balance.DPP && !license.IsRegistered() + return balance.DPP && !dpp.Driver.IsRegistered() }, Func: func() { if s.winRegister == nil { diff --git a/pkg/menu_scene.go b/pkg/menu_scene.go index 42ba387..a87f924 100644 --- a/pkg/menu_scene.go +++ b/pkg/menu_scene.go @@ -73,6 +73,8 @@ func (d *Doodle) GotoNewDoodadMenu() { } // GotoLoadMenu loads the MenuScene and shows the "Load" window. +// +// DEPRECATED: loads the old menu, in dev console run `$ d.GotoLoadMenu()` to see. func (d *Doodle) GotoLoadMenu() { log.Info("Loading the MenuScene to the Load window for Edit Mode") scene := &MenuScene{ @@ -83,6 +85,8 @@ func (d *Doodle) GotoLoadMenu() { // GotoPlayMenu loads the MenuScene and shows the "Load" window for playing a // level, not editing it. +// +// DEPRECATED: loads the old menu, in dev console run `$ d.GotoPlayMenu()` to see. func (d *Doodle) GotoPlayMenu() { log.Info("Loading the MenuScene to the Load window for Play Mode") scene := &MenuScene{ diff --git a/pkg/native/username.go b/pkg/native/username.go index 7d7d222..2316f58 100644 --- a/pkg/native/username.go +++ b/pkg/native/username.go @@ -3,7 +3,7 @@ package native import ( "os" - "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" ) var USER string = os.Getenv("USER") @@ -17,9 +17,9 @@ If they have registered the game, use the name from their license JWT token. Otherwise fall back to their native operating system user. */ func DefaultAuthor() string { - // Are we registered? - if plus.IsRegistered() { - if reg, err := plus.GetRegistration(); err == nil { + // Are we registered? TODO: get from registration + if dpp.Driver.IsRegistered() { + if reg, err := dpp.Driver.GetRegistration(); err == nil { return reg.Name } } diff --git a/pkg/play_scene.go b/pkg/play_scene.go index 3625916..0c41e9a 100644 --- a/pkg/play_scene.go +++ b/pkg/play_scene.go @@ -13,13 +13,12 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/keybind" "git.kirsle.net/SketchyMaze/doodle/pkg/level" "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" - "git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen" "git.kirsle.net/SketchyMaze/doodle/pkg/physics" "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/savegame" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting" "git.kirsle.net/SketchyMaze/doodle/pkg/shmem" @@ -63,6 +62,7 @@ type PlayScene struct { menubar *ui.MenuBar editButton *ui.Button winLevelPacks *ui.Window + winOpenLevel *ui.Window // Custom debug labels. debPosition *string @@ -247,7 +247,7 @@ func (s *PlayScene) setupAsync(d *Doodle) error { s.drawing.OnResetTimer = s.ResetTimer // If this level game from a signed LevelPack, inform the canvas. - if s.LevelPack != nil && levelsigning.IsLevelPackSigned(s.LevelPack) { + if s.LevelPack != nil && dpp.Driver.IsLevelPackSigned(s.LevelPack) { s.drawing.IsSignedLevelPack = s.LevelPack } @@ -337,7 +337,7 @@ func (s *PlayScene) setupAsync(d *Doodle) error { func (s *PlayScene) installActors() error { if err := s.drawing.InstallActors(s.Level.Actors); err != nil { summary := "This level references some doodads that were not found:" - if strings.Contains(err.Error(), license.ErrRegisteredFeature.Error()) { + if strings.Contains(err.Error(), plus.ErrRegisteredFeature.Error()) { summary = "This level contains embedded doodads, but this is not\n" + "available in the free version of the game. The following\n" + "doodads could not be loaded:" @@ -504,7 +504,7 @@ func (s *PlayScene) setupPlayer(playerCharacterFilename string) { // centerIn is optional, ignored if zero. func (s *PlayScene) installPlayerDoodad(filename string, spawn render.Point, centerIn render.Rect) { // Load in the player character. - player, err := plus.DoodadFromEmbeddable(filename, s.Level, false) + player, err := dpp.Driver.LoadFromEmbeddable(filename, s.Level, false) if err != nil { log.Error("PlayScene.Setup: failed to load player doodad: %s", err) player = doodads.NewDummy(32) diff --git a/pkg/play_scene_menubar.go b/pkg/play_scene_menubar.go index 8cf77f1..a07f85d 100644 --- a/pkg/play_scene_menubar.go +++ b/pkg/play_scene_menubar.go @@ -40,7 +40,26 @@ func (u *PlayScene) setupMenuBar(d *Doodle) *ui.MenuBar { u.winLevelPacks.Show() }) gameMenu.AddItemAccel("New drawing", "Ctrl-N", d.GotoNewMenu) - gameMenu.AddItemAccel("Open drawing", "Ctrl-O", d.GotoLoadMenu) + gameMenu.AddItemAccel("Open drawing", "Ctrl-O", func() { + if u.winOpenLevel == nil { + u.winOpenLevel = windows.NewOpenDrawingWindow(windows.OpenDrawing{ + Supervisor: u.Supervisor, + Engine: shmem.CurrentRenderEngine, + OnOpenDrawing: func(filename string) { + d.EditFile(filename) + }, + OnCloseWindow: func() { + u.winOpenLevel.Destroy() + u.winOpenLevel = nil + }, + }) + } + u.winOpenLevel.MoveTo(render.Point{ + X: (d.width / 2) - (u.winOpenLevel.Size().W / 2), + Y: (d.height / 2) - (u.winOpenLevel.Size().H / 2), + }) + u.winOpenLevel.Show() + }) gameMenu.AddSeparator() gameMenu.AddItem("Quit to menu", func() { diff --git a/pkg/plus/bootstrap/bootstrap_dpp.go b/pkg/plus/bootstrap/bootstrap_dpp.go new file mode 100644 index 0000000..5e6c566 --- /dev/null +++ b/pkg/plus/bootstrap/bootstrap_dpp.go @@ -0,0 +1,21 @@ +//go:build dpp +// +build dpp + +/* +Package bootstrap is a common import between the Doodle and Doodad programs. + +Its chief job is to work around circular dependency issues when dealing with +pluggable parts of the codebase, such as Doodle++ which adds features for the +official release which are missing from the FOSS version. +*/ +package bootstrap + +import ( + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" +) + +var Driver dpp.Pluggable + +func InitPlugins() { + Driver = dpp.Plugin{} +} diff --git a/pkg/plus/bootstrap/bootstrap_foss.go b/pkg/plus/bootstrap/bootstrap_foss.go new file mode 100644 index 0000000..dd213f1 --- /dev/null +++ b/pkg/plus/bootstrap/bootstrap_foss.go @@ -0,0 +1,14 @@ +//go:build !dpp +// +build !dpp + +package bootstrap + +import ( + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" +) + +var Driver dpp.Pluggable + +func InitPlugins() { + Driver = dpp.Plugin{} +} diff --git a/pkg/plus/dpp/plugin.go b/pkg/plus/dpp/plugin.go new file mode 100644 index 0000000..606d883 --- /dev/null +++ b/pkg/plus/dpp/plugin.go @@ -0,0 +1,21 @@ +package dpp + +import ( + "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" + "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" + "git.kirsle.net/SketchyMaze/doodle/pkg/level" + "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus" +) + +var Driver Pluggable + +// Plugin +type Pluggable interface { + LoadFromEmbeddable(string, filesystem.Embeddable, bool) (*doodads.Doodad, error) + IsRegistered() bool + GetRegistration() (plus.Registration, error) + UploadLicenseFile(string) (plus.Registration, error) + IsLevelSigned(*level.Level) bool + IsLevelPackSigned(*levelpack.LevelPack) bool +} diff --git a/pkg/plus/dpp/plus_dpp.go b/pkg/plus/dpp/plus_dpp.go index 31825ee..9a3a69b 100644 --- a/pkg/plus/dpp/plus_dpp.go +++ b/pkg/plus/dpp/plus_dpp.go @@ -1,24 +1,68 @@ //go:build dpp // +build dpp -package plus +package dpp import ( + "encoding/json" + "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" + "git.kirsle.net/SketchyMaze/doodle/pkg/level" + "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus" "git.kirsle.net/SketchyMaze/dpp/embedding" "git.kirsle.net/SketchyMaze/dpp/license" + "git.kirsle.net/SketchyMaze/dpp/license/levelsigning" ) -func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { +type Plugin struct{} + +func (Plugin) LoadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { return embedding.LoadFromEmbeddable(filename, fs, force) } -func IsRegistered() bool { +func (Plugin) IsRegistered() bool { return license.IsRegistered() } -func GetRegistration() (*Registration, error) { +func (Plugin) GetRegistration() (plus.Registration, error) { reg, err := license.GetRegistration() - return reg.(*Registration), err + if err != nil { + return plus.Registration{}, err + } + + return translateLicenseStruct(reg) +} + +func (Plugin) UploadLicenseFile(filename string) (plus.Registration, error) { + reg, err := license.UploadLicenseFile(filename) + if err != nil { + return plus.Registration{}, err + } + + return translateLicenseStruct(reg) +} + +// Hack: to translate JWT token types, easiest is to just encode/decode them (inner jwt.StandardClaims complexity). +func translateLicenseStruct(reg license.Registration) (plus.Registration, error) { + jsonStr, err := json.Marshal(reg) + if err != nil { + return plus.Registration{}, err + } + var result plus.Registration + err = json.Unmarshal(jsonStr, &result) + return result, err +} + +func (Plugin) IsLevelPackSigned(lp *levelpack.LevelPack) bool { + return levelsigning.IsLevelPackSigned(lp) +} + +func (Plugin) IsLevelSigned(lvl *level.Level) bool { + return levelsigning.IsLevelSigned(lvl) +} + +func init() { + Driver = Plugin{} } diff --git a/pkg/plus/dpp/plus_foss.go b/pkg/plus/dpp/plus_foss.go new file mode 100644 index 0000000..0a00b2d --- /dev/null +++ b/pkg/plus/dpp/plus_foss.go @@ -0,0 +1,46 @@ +//go:build !dpp +// +build !dpp + +package dpp + +import ( + "errors" + + "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" + "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" + "git.kirsle.net/SketchyMaze/doodle/pkg/level" + "git.kirsle.net/SketchyMaze/doodle/pkg/levelpack" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus" +) + +var ErrNotImplemented = errors.New("not implemented") + +type Plugin struct{} + +func (Plugin) LoadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { + return doodads.LoadFile(filename) +} + +func (Plugin) IsRegistered() bool { + return false +} + +func (Plugin) GetRegistration() (plus.Registration, error) { + return plus.Registration{}, ErrNotImplemented +} + +func (Plugin) UploadLicenseFile(string) (plus.Registration, error) { + return plus.Registration{}, ErrNotImplemented +} + +func (Plugin) IsLevelPackSigned(*levelpack.LevelPack) bool { + return false +} + +func (Plugin) IsLevelSigned(*level.Level) bool { + return false +} + +func init() { + Driver = Plugin{} +} diff --git a/pkg/plus/foss/plus_foss.go b/pkg/plus/foss/plus_foss.go deleted file mode 100644 index c4c649e..0000000 --- a/pkg/plus/foss/plus_foss.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build !dpp -// +build !dpp - -package plus - -import ( - "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" - "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" -) - -// DoodadFromEmbeddable may load a doodad from an embedding filesystem, such as a Level or LevelPack. -func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { - return doodads.LoadFile(filename) -} - -func IsRegistered() bool { - return false -} - -func GetRegistration() (*Registration, error) { - return nil, ErrNotImplemented -} diff --git a/pkg/plus/initdpp/plus_dpp.go b/pkg/plus/initdpp/plus_dpp.go deleted file mode 100644 index 31825ee..0000000 --- a/pkg/plus/initdpp/plus_dpp.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build dpp -// +build dpp - -package plus - -import ( - "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" - "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" - "git.kirsle.net/SketchyMaze/dpp/embedding" - "git.kirsle.net/SketchyMaze/dpp/license" -) - -func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { - return embedding.LoadFromEmbeddable(filename, fs, force) -} - -func IsRegistered() bool { - return license.IsRegistered() -} - -func GetRegistration() (*Registration, error) { - reg, err := license.GetRegistration() - return reg.(*Registration), err -} diff --git a/pkg/plus/initdpp/plus_foss.go b/pkg/plus/initdpp/plus_foss.go deleted file mode 100644 index c4c649e..0000000 --- a/pkg/plus/initdpp/plus_foss.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build !dpp -// +build !dpp - -package plus - -import ( - "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" - "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" -) - -// DoodadFromEmbeddable may load a doodad from an embedding filesystem, such as a Level or LevelPack. -func DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) { - return doodads.LoadFile(filename) -} - -func IsRegistered() bool { - return false -} - -func GetRegistration() (*Registration, error) { - return nil, ErrNotImplemented -} diff --git a/pkg/plus/initdpp/plus_init.go b/pkg/plus/initdpp/plus_init.go deleted file mode 100644 index f5ca1e4..0000000 --- a/pkg/plus/initdpp/plus_init.go +++ /dev/null @@ -1 +0,0 @@ -package initdpp diff --git a/pkg/plus/plus.go b/pkg/plus/plus.go index c7d9491..05de27c 100644 --- a/pkg/plus/plus.go +++ b/pkg/plus/plus.go @@ -4,16 +4,14 @@ package plus import ( "errors" - "git.kirsle.net/SketchyMaze/doodle/pkg/doodads" - "git.kirsle.net/SketchyMaze/doodle/pkg/filesystem" "github.com/dgrijalva/jwt-go" ) -var ErrNotImplemented = errors.New("not implemented") - -type Bridge interface { - DoodadFromEmbeddable(filename string, fs filesystem.Embeddable, force bool) (*doodads.Doodad, error) -} +// Errors +var ( + ErrNotImplemented = errors.New("not implemented") + ErrRegisteredFeature = errors.New("feature not available") +) // Registration object encoded into a license key file. type Registration struct { diff --git a/pkg/uix/canvas_actors.go b/pkg/uix/canvas_actors.go index 965f269..c9c6ed1 100644 --- a/pkg/uix/canvas_actors.go +++ b/pkg/uix/canvas_actors.go @@ -7,9 +7,8 @@ import ( "strings" "git.kirsle.net/SketchyMaze/doodle/pkg/level" - "git.kirsle.net/SketchyMaze/doodle/pkg/license/levelsigning" "git.kirsle.net/SketchyMaze/doodle/pkg/log" - "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting" "git.kirsle.net/SketchyMaze/doodle/pkg/scripting/exceptions" "git.kirsle.net/go/render" @@ -37,18 +36,18 @@ func (w *Canvas) InstallActors(actors level.ActorMap) error { // Signed Levels: the free version normally won't load embedded assets from // a level and the call to LoadFromEmbeddable below returns the error. If the // level is signed it is allowed to use its embedded assets. - isSigned := w.IsSignedLevelPack != nil || levelsigning.IsLevelSigned(w.level) + isSigned := w.IsSignedLevelPack != nil || dpp.Driver.IsLevelSigned(w.level) w.actors = make([]*Actor, 0) for _, id := range actorIDs { var actor = actors[id] // Try loading the doodad from the level's own attached files. - doodad, err := plus.DoodadFromEmbeddable(actor.Filename, w.level, isSigned) + doodad, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, w.level, isSigned) if err != nil { // If we have a signed levelpack, try loading from the levelpack. if w.IsSignedLevelPack != nil { - if found, err := plus.DoodadFromEmbeddable(actor.Filename, w.IsSignedLevelPack, true); err == nil { + if found, err := dpp.Driver.LoadFromEmbeddable(actor.Filename, w.IsSignedLevelPack, true); err == nil { doodad = found } } diff --git a/pkg/windows/license_key.go b/pkg/windows/license_key.go index 997dfff..9ff5c9a 100644 --- a/pkg/windows/license_key.go +++ b/pkg/windows/license_key.go @@ -7,10 +7,11 @@ import ( "git.kirsle.net/SketchyMaze/doodle/pkg/balance" "git.kirsle.net/SketchyMaze/doodle/pkg/branding" "git.kirsle.net/SketchyMaze/doodle/pkg/branding/builds" - "git.kirsle.net/SketchyMaze/doodle/pkg/license" "git.kirsle.net/SketchyMaze/doodle/pkg/log" "git.kirsle.net/SketchyMaze/doodle/pkg/modal" "git.kirsle.net/SketchyMaze/doodle/pkg/native" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus" + "git.kirsle.net/SketchyMaze/doodle/pkg/plus/dpp" "git.kirsle.net/go/render" "git.kirsle.net/go/ui" "git.kirsle.net/go/ui/style" @@ -51,12 +52,12 @@ func NewLicenseWindow(cfg License) *ui.Window { labelSize = render.NewRect(100, 16) valueSize = render.NewRect(windowWidth-labelSize.W-4, labelSize.H) isRegistered bool - registration license.Registration + registration plus.Registration summary = "Unregistered" + builds.VersionSuffix ) // Get our current registration status. - if reg, err := license.GetRegistration(); err == nil { + if reg, err := dpp.Driver.GetRegistration(); err == nil { isRegistered = true registration = reg windowHeight = 200 @@ -141,7 +142,7 @@ func NewLicenseWindow(cfg License) *ui.Window { } // Upload and validate the license key. - reg, err := license.UploadLicenseFile(filename) + reg, err := dpp.Driver.UploadLicenseFile(filename) if err != nil { modal.Alert("That license key didn't seem quite right.").WithTitle("License Error") return