Browse Source

Initial commit

GeekROS 1 year ago
commit
cec0aae8e3
69 changed files with 2687 additions and 0 deletions
  1. 17 0
      .gitignore
  2. 34 0
      desktop/framework/config/config.go
  3. 62 0
      desktop/framework/framework.go
  4. 74 0
      desktop/framework/windows/start/index.go
  5. 43 0
      desktop/go.mod
  6. 104 0
      desktop/go.sum
  7. 26 0
      desktop/main.go
  8. 15 0
      desktop/template/index.html
  9. 33 0
      desktop/template/package.json
  10. 1 0
      desktop/template/package.json.md5
  11. BIN
      desktop/template/public/favicon.ico
  12. BIN
      desktop/template/public/static/image/logo.png
  13. 36 0
      desktop/template/src/app.vue
  14. 55 0
      desktop/template/src/assets/css/base.scss
  15. 42 0
      desktop/template/src/main.ts
  16. 6 0
      desktop/template/src/package/wailsjs/go/StartWindows/Api.d.ts
  17. 11 0
      desktop/template/src/package/wailsjs/go/StartWindows/Api.js
  18. 24 0
      desktop/template/src/package/wailsjs/runtime/package.json
  19. 235 0
      desktop/template/src/package/wailsjs/runtime/runtime.d.ts
  20. 202 0
      desktop/template/src/package/wailsjs/runtime/runtime.js
  21. 15 0
      desktop/template/src/router/index.ts
  22. 7 0
      desktop/template/src/vite-env.d.ts
  23. 45 0
      desktop/template/src/windows/start.vue
  24. 33 0
      desktop/template/tsconfig.json
  25. 14 0
      desktop/template/tsconfig.node.json
  26. 17 0
      desktop/template/vite.config.ts
  27. 24 0
      desktop/wails.json
  28. 1 0
      engine/assets/icon.svg
  29. 37 0
      engine/assets/icon.svg.import
  30. BIN
      engine/assets/launch/background.jpeg
  31. 34 0
      engine/assets/launch/background.jpeg.import
  32. 40 0
      engine/project.godot
  33. 22 0
      engine/scenes/launch/launch.tscn
  34. 28 0
      engine/scripts/framework/client/client.gd
  35. 53 0
      engine/scripts/framework/global.gd
  36. 29 0
      engine/scripts/framework/server/server.gd
  37. 30 0
      engine/scripts/framework/utils/request.gd
  38. 49 0
      readme.md
  39. 52 0
      server/framework/config/config.go
  40. 61 0
      server/framework/controller/controller.go
  41. 18 0
      server/framework/controller/ping/ping.go
  42. 74 0
      server/framework/database/database.go
  43. 65 0
      server/framework/database/interface.go
  44. 23 0
      server/framework/framework.go
  45. 3 0
      server/framework/utils/empty_data.go
  46. 27 0
      server/framework/utils/hashids.go
  47. 49 0
      server/framework/utils/header.go
  48. 17 0
      server/framework/utils/mailbox.go
  49. 27 0
      server/framework/utils/markdown.go
  50. 22 0
      server/framework/utils/md5.go
  51. 18 0
      server/framework/utils/order.go
  52. 69 0
      server/framework/utils/phone.go
  53. 7 0
      server/framework/utils/price.go
  54. 20 0
      server/framework/utils/rand.go
  55. 105 0
      server/framework/utils/return.go
  56. 33 0
      server/framework/utils/time.go
  57. 42 0
      server/go.mod
  58. 126 0
      server/go.sum
  59. 15 0
      server/main.go
  60. 0 0
      tools/centos/data/wwwroot/default/index.html
  61. 41 0
      tools/centos/etc/nginx/conf.d/game.makeryang.com.conf
  62. 30 0
      tools/centos/etc/nginx/nginx.conf
  63. 27 0
      tools/centos/etc/nginx/ssl/game.makeryang.com.key
  64. 61 0
      tools/centos/etc/nginx/ssl/game.makeryang.com.pem
  65. 13 0
      tools/centos/etc/systemd/system/game.service
  66. 12 0
      tools/centos/etc/systemd/system/server.service
  67. 27 0
      tools/update.sh
  68. 5 0
      update.bat
  69. 100 0
      wiki/course/0001.md

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+.idea
+.DS*
+.git
+.vscode
+.godot
+*.cfg
+*.tmp
+desktop/release
+!desktop/release/appicon.png
+desktop/template/yarn.lock
+desktop/template/yarn-error.log
+desktop/template/node_modules
+desktop/template/dist
+engine/release
+engine/runtime
+!engine/release/.gitkeep
+!engine/runtime/.gitkeep

+ 34 - 0
desktop/framework/config/config.go

@@ -0,0 +1,34 @@
+/**
+ ******************************************************************************
+ * @file    config.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Config
+
+import (
+	"embed"
+	"encoding/json"
+	"golang.org/x/sync/errgroup"
+)
+
+var Get = &Data{}
+
+type Data struct {
+	Info struct {
+		CompanyName    string `json:"companyName"`
+		ProductName    string `json:"productName"`
+		ProductVersion string `json:"productVersion"`
+	} `json:"info"`
+	Group errgroup.Group
+}
+
+func Init(version embed.FS) {
+	wails, _ := version.ReadFile("wails.json")
+	var wailsJson Data
+	json.Unmarshal(wails, &wailsJson)
+	Get.Info.ProductVersion = wailsJson.Info.ProductVersion
+	Get.Info.ProductName = wailsJson.Info.ProductName
+	Get.Info.CompanyName = wailsJson.Info.CompanyName
+}

+ 62 - 0
desktop/framework/framework.go

@@ -0,0 +1,62 @@
+/**
+ ******************************************************************************
+ * @file    framework.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Framework
+
+import (
+	"cnc/framework/config"
+	"cnc/framework/windows/start"
+	"embed"
+	"fmt"
+	"github.com/gookit/color"
+	"github.com/wailsapp/wails/v2"
+	"github.com/wailsapp/wails/v2/pkg/options"
+	"github.com/wailsapp/wails/v2/pkg/options/assetserver"
+	"github.com/wailsapp/wails/v2/pkg/options/linux"
+	"github.com/wailsapp/wails/v2/pkg/options/windows"
+)
+
+func Init(template embed.FS, version embed.FS) {
+
+	Config.Init(version)
+
+	start := StartWindows.Init()
+
+	err := wails.Run(&options.App{
+		Title:     "",
+		Width:     1200,
+		Height:    768,
+		MinWidth:  1200,
+		MinHeight: 768,
+		AssetServer: &assetserver.Options{
+			Assets: template,
+		},
+		BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 1},
+		OnStartup:        start.Startup,
+		OnShutdown:       start.Shutdown,
+		Bind: []interface{}{
+			start,
+		},
+		WindowStartState: options.Normal,
+		Windows: &windows.Options{
+			WebviewDisableRendererCodeIntegrity: true,
+			DisableWindowIcon:                   true,
+		},
+		Linux: &linux.Options{
+			Icon:                []byte(""),
+			WindowIsTranslucent: false,
+			WebviewGpuPolicy:    linux.WebviewGpuPolicyNever,
+		},
+		Debug: options.Debug{
+			OpenInspectorOnStartup: false,
+		},
+	})
+
+	if err != nil {
+		fmt.Println("[desktop][framework]:" + color.Gray.Text(err.Error()))
+	}
+}

+ 74 - 0
desktop/framework/windows/start/index.go

@@ -0,0 +1,74 @@
+/**
+ ******************************************************************************
+ * @file    index.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package StartWindows
+
+import (
+	"cnc/framework/config"
+	"context"
+	"os"
+	"runtime"
+	"strings"
+)
+
+type Api struct {
+	ctx context.Context
+}
+
+type ReturnResponse struct {
+	Code int         `json:"code"`
+	Data interface{} `json:"data"`
+	Msg  string      `json:"msg"`
+}
+
+func Init() *Api {
+	return &Api{}
+}
+
+func (start *Api) Startup(ctx context.Context) {
+	start.ctx = ctx
+}
+
+func (start *Api) Shutdown(ctx context.Context) {
+
+}
+
+func (start *Api) GetPlatform() string {
+	platform := ""
+	switch runtime.GOOS {
+	case "windows":
+		platform = "Windows"
+	case "darwin":
+		platform = "Darwin"
+	case "linux":
+		platform = "Linux"
+		content, err := os.ReadFile("/etc/os-release")
+		if err == nil {
+			lines := strings.Split(string(content), "\n")
+			for _, line := range lines {
+				if strings.HasPrefix(line, "ID=") {
+					switch {
+					case strings.Contains(line, "ubuntu"):
+						platform = "Ubuntu"
+					case strings.Contains(line, "debian"):
+						platform = "Debian"
+					default:
+						platform = "Linux"
+					}
+				}
+			}
+		}
+	default:
+		platform = "-"
+	}
+
+	return platform
+}
+
+func (start *Api) GetVersion() []string {
+	return []string{Config.Get.Info.ProductName, Config.Get.Info.ProductVersion}
+}

+ 43 - 0
desktop/go.mod

@@ -0,0 +1,43 @@
+module cnc
+
+go 1.18
+
+require (
+	github.com/gookit/color v1.5.2
+	github.com/wailsapp/wails/v2 v2.7.1
+	golang.org/x/sync v0.5.0
+)
+
+require (
+	github.com/bep/debounce v1.2.1 // indirect
+	github.com/go-ole/go-ole v1.2.6 // indirect
+	github.com/godbus/dbus/v5 v5.1.0 // indirect
+	github.com/google/uuid v1.3.0 // indirect
+	github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
+	github.com/labstack/echo/v4 v4.10.2 // indirect
+	github.com/labstack/gommon v0.4.0 // indirect
+	github.com/leaanthony/go-ansi-parser v1.6.0 // indirect
+	github.com/leaanthony/gosod v1.0.3 // indirect
+	github.com/leaanthony/slicer v1.6.0 // indirect
+	github.com/leaanthony/u v1.1.0 // indirect
+	github.com/mattn/go-colorable v0.1.13 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
+	github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/rivo/uniseg v0.4.4 // indirect
+	github.com/samber/lo v1.38.1 // indirect
+	github.com/stretchr/testify v1.8.3 // indirect
+	github.com/tkrajina/go-reflector v0.5.6 // indirect
+	github.com/valyala/bytebufferpool v1.0.0 // indirect
+	github.com/valyala/fasttemplate v1.2.2 // indirect
+	github.com/wailsapp/go-webview2 v1.0.10 // indirect
+	github.com/wailsapp/mimetype v1.4.1 // indirect
+	github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
+	golang.org/x/crypto v0.14.0 // indirect
+	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
+	golang.org/x/net v0.17.0 // indirect
+	golang.org/x/sys v0.13.0 // indirect
+	golang.org/x/text v0.13.0 // indirect
+)
+
+// replace github.com/wailsapp/wails/v2 v2.3.1 => C:\Users\admin\go\pkg\mod

+ 104 - 0
desktop/go.sum

@@ -0,0 +1,104 @@
+github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
+github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
+github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
+github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
+github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
+github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
+github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
+github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
+github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
+github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg=
+github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
+github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ=
+github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4=
+github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
+github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
+github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
+github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI=
+github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
+github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
+github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
+github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
+github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w=
+github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
+github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
+github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
+github.com/wailsapp/wails/v2 v2.7.1 h1:HAzp2c5ODOzsLC6ZMDVtNOB72ozM7/SJecJPB2Ur+UU=
+github.com/wailsapp/wails/v2 v2.7.1/go.mod h1:oIJVwwso5fdOgprBYWXBBqtx6PaSvxg8/KTQHNGkadc=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
+golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
+golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 26 - 0
desktop/main.go

@@ -0,0 +1,26 @@
+/**
+ ******************************************************************************
+ * @file    main.go
+ * @author  Makeryang
+ ******************************************************************************
+ */
+
+package main
+
+import (
+	"cnc/framework"
+	"embed"
+	"fmt"
+	"github.com/gookit/color"
+)
+
+//go:embed all:template/dist
+var Template embed.FS
+
+//go:embed all:wails.json
+var VersionInfo embed.FS
+
+func main() {
+	fmt.Println("[desktop][main]:" + color.Gray.Text("starting..."))
+	Framework.Init(Template, VersionInfo)
+}

+ 15 - 0
desktop/template/index.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8" />
+    <meta content="width=device-width, initial-scale=1.0" name="viewport" />
+    <title>Index</title>
+</head>
+
+<body>
+    <div id="app"></div>
+    <script src="./src/main.ts" type="module"></script>
+</body>
+
+</html>

+ 33 - 0
desktop/template/package.json

@@ -0,0 +1,33 @@
+{
+    "name": "frontend",
+    "private": true,
+    "version": "0.0.0",
+    "scripts": {
+        "dev": "vite",
+        "rebuild": "node-gyp rebuild",
+        "build": "vue-tsc --noEmit && vite build",
+        "preview": "vite preview"
+    },
+    "engines": {
+        "node": ">=18"
+    },
+    "dependencies": {
+        "@element-plus/icons": "^0.0.11",
+        "@element-plus/icons-vue": "^2.0.9",
+        "axios": "^0.27.2",
+        "element-plus": "2.3.7",
+        "uuid": "^9.0.0",
+        "vue": "3.2.37",
+        "vue-router": "4.1.5"
+    },
+    "devDependencies": {
+        "@babel/types": "^7.18.10",
+        "@types/react": "^18.2.56",
+        "@types/node": "^18.11.18",
+        "@vitejs/plugin-vue": "^3.0.3",
+        "@vue/tsconfig": "0.1.3",
+        "typescript": "4.6.4",
+        "vite": "3.0.7",
+        "vue-tsc": "0.39.5"
+    }
+}

+ 1 - 0
desktop/template/package.json.md5

@@ -0,0 +1 @@
+d24d6b406b5af24715d4d957ed80e892

BIN
desktop/template/public/favicon.ico


BIN
desktop/template/public/static/image/logo.png


+ 36 - 0
desktop/template/src/app.vue

@@ -0,0 +1,36 @@
+<template>
+    <router-view ref="routerView" v-slot="{Component}">
+        <component :is="Component" :cnc="appData" />
+    </router-view>
+</template>
+
+<script lang="ts">
+import {ref, defineComponent} from "vue";
+import {ElLoading} from "element-plus";
+export default defineComponent({
+    name: "App",
+    emits: [],
+    props: [],
+    components: {},
+    setup(props, context) {
+
+        const appData: any = ref({
+            loading: ElLoading.service({
+                lock: true,
+                background: "rgba(0, 0, 0, .5)",
+                customClass: "desktop",
+            }),
+            data: false
+        });
+
+        return {
+            props,
+            appData
+        }
+    }
+});
+</script>
+
+<style>
+@import "./assets/css/base.scss";
+</style>

+ 55 - 0
desktop/template/src/assets/css/base.scss

@@ -0,0 +1,55 @@
+@charset "UTF-8";
+
+* {
+    box-sizing: border-box;
+    -webkit-tap-highlight-color: transparent;
+    -webkit-appearance: none;
+    -webkit-touch-callout: none;
+    outline: none;
+    user-select: none;
+    margin: 0;
+    padding: 0;
+}
+
+body {
+    font-family: Inter, sans-serif;
+    font-feature-settings: "tnum";
+    font-variant: tabular-nums;
+    -webkit-font-smoothing: antialiased;
+    font-size: 12px;
+    color: #666666;
+}
+
+ul li, ol li {
+    list-style: none;
+}
+
+::-webkit-scrollbar {
+    width: 3px;
+    height: 3px;
+}
+::-webkit-scrollbar-thumb {
+    border-radius: 0;
+    box-shadow: inset 0 0 3px rgba(68, 68, 71, 1);
+    background: rgba(68, 68, 71, .5);
+}
+::-webkit-scrollbar-track{
+    box-shadow: none;
+    border-radius: 0;
+    background: rgba(68, 68, 71, 0);
+}
+
+*:focus {
+    outline: none !important;
+}
+
+.page-main{
+    width: 100%;
+    height: 100%;
+    position: fixed;
+    z-index: 1;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}

+ 42 - 0
desktop/template/src/main.ts

@@ -0,0 +1,42 @@
+import {createApp} from "vue";
+import App from "./app.vue";
+import {router} from "./router";
+import ElementPlus from "element-plus";
+import "element-plus/dist/index.css";
+import * as ElIcons from "@element-plus/icons-vue";
+
+const app = createApp(App);
+
+app.use(ElementPlus, {zIndex: 90000});
+
+for (const [key, component] of Object.entries(ElIcons)) {
+    app.component(key, component);
+}
+
+app.use(router);
+
+app.directive("resize", {
+    mounted(el, binding) {
+        let _this: any = this;
+        function debounce(fn: any, delay = 16) {
+            let time: any = null;
+            return function () {
+                if (time) {
+                    clearTimeout(time);
+                }
+                const context = _this;
+                const args = arguments
+                time = setTimeout(function () {
+                    fn.apply(context, args);
+                }, delay);
+            }
+        }
+        el._resizer = new window.ResizeObserver(debounce(binding.value, Number(binding.arg) || 16));
+        el._resizer.observe(el);
+    },
+    unmounted(el) {
+        el._resizer.disconnect();
+    }
+});
+
+app.mount("#app");

+ 6 - 0
desktop/template/src/package/wailsjs/go/StartWindows/Api.d.ts

@@ -0,0 +1,6 @@
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export function GetPlatform():Promise<string>;
+
+export function GetVersion():Promise<Array<string>>;

+ 11 - 0
desktop/template/src/package/wailsjs/go/StartWindows/Api.js

@@ -0,0 +1,11 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+export function GetPlatform() {
+  return window['go']['StartWindows']['Api']['GetPlatform']();
+}
+
+export function GetVersion() {
+  return window['go']['StartWindows']['Api']['GetVersion']();
+}

+ 24 - 0
desktop/template/src/package/wailsjs/runtime/package.json

@@ -0,0 +1,24 @@
+{
+  "name": "@wailsapp/runtime",
+  "version": "2.0.0",
+  "description": "Wails Javascript runtime library",
+  "main": "runtime.js",
+  "types": "runtime.d.ts",
+  "scripts": {
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/wailsapp/wails.git"
+  },
+  "keywords": [
+    "Wails",
+    "Javascript",
+    "Go"
+  ],
+  "author": "Lea Anthony <lea.anthony@gmail.com>",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/wailsapp/wails/issues"
+  },
+  "homepage": "https://github.com/wailsapp/wails#readme"
+}

+ 235 - 0
desktop/template/src/package/wailsjs/runtime/runtime.d.ts

@@ -0,0 +1,235 @@
+/*
+ _       __      _ __
+| |     / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__  )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+export interface Position {
+    x: number;
+    y: number;
+}
+
+export interface Size {
+    w: number;
+    h: number;
+}
+
+export interface Screen {
+    isCurrent: boolean;
+    isPrimary: boolean;
+    width : number
+    height : number
+}
+
+// Environment information such as platform, buildtype, ...
+export interface EnvironmentInfo {
+    buildType: string;
+    platform: string;
+    arch: string;
+}
+
+// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
+// emits the given event. Optional data may be passed with the event.
+// This will trigger any event listeners.
+export function EventsEmit(eventName: string, ...data: any): void;
+
+// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
+export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
+
+// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
+// sets up a listener for the given event name, but will only trigger a given number times.
+export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
+
+// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
+// sets up a listener for the given event name, but will only trigger once.
+export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
+
+// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
+// unregisters the listener for the given event name.
+export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
+
+// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
+// unregisters all listeners.
+export function EventsOffAll(): void;
+
+// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
+// logs the given message as a raw message
+export function LogPrint(message: string): void;
+
+// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
+// logs the given message at the `trace` log level.
+export function LogTrace(message: string): void;
+
+// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
+// logs the given message at the `debug` log level.
+export function LogDebug(message: string): void;
+
+// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
+// logs the given message at the `error` log level.
+export function LogError(message: string): void;
+
+// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
+// logs the given message at the `fatal` log level.
+// The application will quit after calling this method.
+export function LogFatal(message: string): void;
+
+// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
+// logs the given message at the `info` log level.
+export function LogInfo(message: string): void;
+
+// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
+// logs the given message at the `warning` log level.
+export function LogWarning(message: string): void;
+
+// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
+// Forces a reload by the main application as well as connected browsers.
+export function WindowReload(): void;
+
+// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
+// Reloads the application frontend.
+export function WindowReloadApp(): void;
+
+// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
+// Sets the window AlwaysOnTop or not on top.
+export function WindowSetAlwaysOnTop(b: boolean): void;
+
+// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
+// *Windows only*
+// Sets window theme to system default (dark/light).
+export function WindowSetSystemDefaultTheme(): void;
+
+// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
+// *Windows only*
+// Sets window to light theme.
+export function WindowSetLightTheme(): void;
+
+// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
+// *Windows only*
+// Sets window to dark theme.
+export function WindowSetDarkTheme(): void;
+
+// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
+// Centers the window on the monitor the window is currently on.
+export function WindowCenter(): void;
+
+// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
+// Sets the text in the window title bar.
+export function WindowSetTitle(title: string): void;
+
+// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
+// Makes the window full screen.
+export function WindowFullscreen(): void;
+
+// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
+// Restores the previous window dimensions and position prior to full screen.
+export function WindowUnfullscreen(): void;
+
+// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
+// Returns the state of the window, i.e. whether the window is in full screen mode or not.
+export function WindowIsFullscreen(): Promise<boolean>;
+
+// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
+// Sets the width and height of the window.
+export function WindowSetSize(width: number, height: number): Promise<Size>;
+
+// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
+// Gets the width and height of the window.
+export function WindowGetSize(): Promise<Size>;
+
+// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
+// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
+// Setting a size of 0,0 will disable this constraint.
+export function WindowSetMaxSize(width: number, height: number): void;
+
+// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
+// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
+// Setting a size of 0,0 will disable this constraint.
+export function WindowSetMinSize(width: number, height: number): void;
+
+// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
+// Sets the window position relative to the monitor the window is currently on.
+export function WindowSetPosition(x: number, y: number): void;
+
+// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
+// Gets the window position relative to the monitor the window is currently on.
+export function WindowGetPosition(): Promise<Position>;
+
+// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
+// Hides the window.
+export function WindowHide(): void;
+
+// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
+// Shows the window, if it is currently hidden.
+export function WindowShow(): void;
+
+// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
+// Maximises the window to fill the screen.
+export function WindowMaximise(): void;
+
+// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
+// Toggles between Maximised and UnMaximised.
+export function WindowToggleMaximise(): void;
+
+// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
+// Restores the window to the dimensions and position prior to maximising.
+export function WindowUnmaximise(): void;
+
+// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
+// Returns the state of the window, i.e. whether the window is maximised or not.
+export function WindowIsMaximised(): Promise<boolean>;
+
+// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
+// Minimises the window.
+export function WindowMinimise(): void;
+
+// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
+// Restores the window to the dimensions and position prior to minimising.
+export function WindowUnminimise(): void;
+
+// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
+// Returns the state of the window, i.e. whether the window is minimised or not.
+export function WindowIsMinimised(): Promise<boolean>;
+
+// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
+// Returns the state of the window, i.e. whether the window is normal or not.
+export function WindowIsNormal(): Promise<boolean>;
+
+// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
+// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
+export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
+
+// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
+// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
+export function ScreenGetAll(): Promise<Screen[]>;
+
+// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
+// Opens the given URL in the system browser.
+export function BrowserOpenURL(url: string): void;
+
+// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
+// Returns information about the environment
+export function Environment(): Promise<EnvironmentInfo>;
+
+// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
+// Quits the application.
+export function Quit(): void;
+
+// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
+// Hides the application.
+export function Hide(): void;
+
+// [Show](https://wails.io/docs/reference/runtime/intro#show)
+// Shows the application.
+export function Show(): void;
+
+// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
+// Returns the current text stored on clipboard
+export function ClipboardGetText(): Promise<string>;
+
+// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
+// Sets a text on the clipboard
+export function ClipboardSetText(text: string): Promise<boolean>;

+ 202 - 0
desktop/template/src/package/wailsjs/runtime/runtime.js

@@ -0,0 +1,202 @@
+/*
+ _       __      _ __
+| |     / /___ _(_) /____
+| | /| / / __ `/ / / ___/
+| |/ |/ / /_/ / / (__  )
+|__/|__/\__,_/_/_/____/
+The electron alternative for Go
+(c) Lea Anthony 2019-present
+*/
+
+export function LogPrint(message) {
+    window.runtime.LogPrint(message);
+}
+
+export function LogTrace(message) {
+    window.runtime.LogTrace(message);
+}
+
+export function LogDebug(message) {
+    window.runtime.LogDebug(message);
+}
+
+export function LogInfo(message) {
+    window.runtime.LogInfo(message);
+}
+
+export function LogWarning(message) {
+    window.runtime.LogWarning(message);
+}
+
+export function LogError(message) {
+    window.runtime.LogError(message);
+}
+
+export function LogFatal(message) {
+    window.runtime.LogFatal(message);
+}
+
+export function EventsOnMultiple(eventName, callback, maxCallbacks) {
+    return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
+}
+
+export function EventsOn(eventName, callback) {
+    return EventsOnMultiple(eventName, callback, -1);
+}
+
+export function EventsOff(eventName, ...additionalEventNames) {
+    return window.runtime.EventsOff(eventName, ...additionalEventNames);
+}
+
+export function EventsOnce(eventName, callback) {
+    return EventsOnMultiple(eventName, callback, 1);
+}
+
+export function EventsEmit(eventName) {
+    let args = [eventName].slice.call(arguments);
+    return window.runtime.EventsEmit.apply(null, args);
+}
+
+export function WindowReload() {
+    window.runtime.WindowReload();
+}
+
+export function WindowReloadApp() {
+    window.runtime.WindowReloadApp();
+}
+
+export function WindowSetAlwaysOnTop(b) {
+    window.runtime.WindowSetAlwaysOnTop(b);
+}
+
+export function WindowSetSystemDefaultTheme() {
+    window.runtime.WindowSetSystemDefaultTheme();
+}
+
+export function WindowSetLightTheme() {
+    window.runtime.WindowSetLightTheme();
+}
+
+export function WindowSetDarkTheme() {
+    window.runtime.WindowSetDarkTheme();
+}
+
+export function WindowCenter() {
+    window.runtime.WindowCenter();
+}
+
+export function WindowSetTitle(title) {
+    window.runtime.WindowSetTitle(title);
+}
+
+export function WindowFullscreen() {
+    window.runtime.WindowFullscreen();
+}
+
+export function WindowUnfullscreen() {
+    window.runtime.WindowUnfullscreen();
+}
+
+export function WindowIsFullscreen() {
+    return window.runtime.WindowIsFullscreen();
+}
+
+export function WindowGetSize() {
+    return window.runtime.WindowGetSize();
+}
+
+export function WindowSetSize(width, height) {
+    window.runtime.WindowSetSize(width, height);
+}
+
+export function WindowSetMaxSize(width, height) {
+    window.runtime.WindowSetMaxSize(width, height);
+}
+
+export function WindowSetMinSize(width, height) {
+    window.runtime.WindowSetMinSize(width, height);
+}
+
+export function WindowSetPosition(x, y) {
+    window.runtime.WindowSetPosition(x, y);
+}
+
+export function WindowGetPosition() {
+    return window.runtime.WindowGetPosition();
+}
+
+export function WindowHide() {
+    window.runtime.WindowHide();
+}
+
+export function WindowShow() {
+    window.runtime.WindowShow();
+}
+
+export function WindowMaximise() {
+    window.runtime.WindowMaximise();
+}
+
+export function WindowToggleMaximise() {
+    window.runtime.WindowToggleMaximise();
+}
+
+export function WindowUnmaximise() {
+    window.runtime.WindowUnmaximise();
+}
+
+export function WindowIsMaximised() {
+    return window.runtime.WindowIsMaximised();
+}
+
+export function WindowMinimise() {
+    window.runtime.WindowMinimise();
+}
+
+export function WindowUnminimise() {
+    window.runtime.WindowUnminimise();
+}
+
+export function WindowSetBackgroundColour(R, G, B, A) {
+    window.runtime.WindowSetBackgroundColour(R, G, B, A);
+}
+
+export function ScreenGetAll() {
+    return window.runtime.ScreenGetAll();
+}
+
+export function WindowIsMinimised() {
+    return window.runtime.WindowIsMinimised();
+}
+
+export function WindowIsNormal() {
+    return window.runtime.WindowIsNormal();
+}
+
+export function BrowserOpenURL(url) {
+    window.runtime.BrowserOpenURL(url);
+}
+
+export function Environment() {
+    return window.runtime.Environment();
+}
+
+export function Quit() {
+    window.runtime.Quit();
+}
+
+export function Hide() {
+    window.runtime.Hide();
+}
+
+export function Show() {
+    window.runtime.Show();
+}
+
+export function ClipboardGetText() {
+    return window.runtime.ClipboardGetText();
+}
+
+export function ClipboardSetText(text) {
+    return window.runtime.ClipboardSetText(text);
+}

+ 15 - 0
desktop/template/src/router/index.ts

@@ -0,0 +1,15 @@
+import { createRouter, createWebHashHistory } from "vue-router";
+import StartPage from "../windows/start.vue";
+
+const routes = [
+    {
+        path: "/",
+        name: "Start",
+        component: StartPage
+    },
+];
+
+export const router = createRouter({
+    history: createWebHashHistory(),
+    routes: routes
+})

+ 7 - 0
desktop/template/src/vite-env.d.ts

@@ -0,0 +1,7 @@
+/// <reference types="vite/client" />
+
+declare module "*.vue" {
+    import type {DefineComponent} from "vue";
+    const component: DefineComponent<{}, {}, any>;
+    export default component;
+}

+ 45 - 0
desktop/template/src/windows/start.vue

@@ -0,0 +1,45 @@
+<template>
+    <div>Hello</div>
+</template>
+
+<script lang="ts">
+import {defineComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, onUnmounted} from "vue";
+import {ElLoading, ElMessage, ElNotification} from "element-plus";
+import * as icons from "@element-plus/icons";
+export default defineComponent({
+    name: "Start",
+    emits: [],
+    props: ["cnc"],
+    components: {},
+    setup(props, context) {
+
+        onBeforeMount(() => {
+            props.cnc.loading = ElLoading.service({
+                lock: true,
+                background: "rgba(0, 0, 0, .5)",
+                customClass: "desktop",
+                fullscreen: true
+            });
+        });
+
+        onMounted(() => {
+            nextTick(()=>{
+                props.cnc.loading.close();
+            });
+        });
+
+        onBeforeUnmount(()=>{})
+
+        onUnmounted(() => {});
+
+        return {
+            props,
+            icons
+        }
+    }
+});
+</script>
+
+<style scoped>
+
+</style>

+ 33 - 0
desktop/template/tsconfig.json

@@ -0,0 +1,33 @@
+{
+    "compilerOptions": {
+        "target": "ESNext",
+        "useDefineForClassFields": true,
+        "module": "ESNext",
+        "moduleResolution": "node",
+        "strict": true,
+        "jsx": "preserve",
+        "sourceMap": false,
+        "resolveJsonModule": true,
+        "isolatedModules": true,
+        "esModuleInterop": true,
+        "lib": [
+            "ESNext",
+            "DOM"
+        ],
+        "types": [
+            "node"
+        ],
+        "skipLibCheck": true
+    },
+    "include": [
+        "src/**/*.ts",
+        "src/**/*.d.ts",
+        "src/**/*.tsx",
+        "src/**/*.vue"
+    ],
+    "references": [
+        {
+            "path": "./tsconfig.node.json"
+        }
+    ]
+}

+ 14 - 0
desktop/template/tsconfig.node.json

@@ -0,0 +1,14 @@
+{
+    "compilerOptions": {
+        "composite": true,
+        "module": "ESNext",
+        "moduleResolution": "node",
+        "allowSyntheticDefaultImports": true,
+        "types": [
+            "node"
+        ]
+    },
+    "include": [
+        "vite.config.ts"
+    ]
+}

+ 17 - 0
desktop/template/vite.config.ts

@@ -0,0 +1,17 @@
+import { defineConfig } from "vite";
+import vue from "@vitejs/plugin-vue";
+
+export default defineConfig({
+    server: {
+        port: 6173
+    },
+    plugins: [
+        vue()
+    ],
+    build: {
+        sourcemap: false
+    },
+    optimizeDeps: {
+        exclude: ["punycode"]
+    },
+})

+ 24 - 0
desktop/wails.json

@@ -0,0 +1,24 @@
+{
+    "$schema": "https://wails.io/schemas/config.v2.json",
+    "name": "desktop",
+    "outputfilename": "desktop",
+    "build:dir": "release",
+    "wailsjsdir": "template/src/package",
+    "frontend:dir": "template",
+    "frontend:install": "yarn",
+    "frontend:build": "yarn build",
+    "frontend:dev:watcher": "yarn dev",
+    "frontend:dev:serverUrl": "auto",
+    "devServer": "localhost:10090",
+    "author": {
+        "name": "MakerYang",
+        "email": "admin@wileho.com"
+    },
+    "info": {
+        "companyName": "MakerYang",
+        "productName": "Desktop",
+        "productVersion": "1.0.0",
+        "copyright": "Copyright © 2019-2022 MakerYang All Rights Reserved",
+        "comments": "MakerYang (https://www.makeryang.com)"
+    }
+}

+ 1 - 0
engine/assets/icon.svg

@@ -0,0 +1 @@
+<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="124" height="124" rx="14" fill="#363d52" stroke="#212532" stroke-width="4"/><g transform="scale(.101) translate(122 122)"><g fill="#fff"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 813 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H447l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c3 34 55 34 58 0v-86c-3-34-55-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></g></svg>

+ 37 - 0
engine/assets/icon.svg.import

@@ -0,0 +1,37 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://uxjhy0m5hoin"
+path="res://.godot/imported/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icon.svg"
+dest_files=["res://.godot/imported/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false

BIN
engine/assets/launch/background.jpeg


+ 34 - 0
engine/assets/launch/background.jpeg.import

@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d05rp7emahb2e"
+path="res://.godot/imported/background.jpeg-5639b05a789575f90a2f9972dfc49a59.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/launch/background.jpeg"
+dest_files=["res://.godot/imported/background.jpeg-5639b05a789575f90a2f9972dfc49a59.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1

+ 40 - 0
engine/project.godot

@@ -0,0 +1,40 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+;   [section] ; section goes between []
+;   param=value ; assign values to parameters
+
+config_version=5
+
+[application]
+
+config/name="Mir of Godot"
+config/version="1.0.0"
+run/main_scene="res://scenes/launch/launch.tscn"
+config/features=PackedStringArray("4.2", "Mobile")
+boot_splash/bg_color=Color(0, 0, 0, 1)
+config/icon="res://assets/icon.svg"
+
+[autoload]
+
+Global="*res://scripts/framework/global.gd"
+Server="*res://scripts/framework/server/server.gd"
+Client="*res://scripts/framework/client/client.gd"
+Request="*res://scripts/framework/utils/request.gd"
+
+[display]
+
+window/size/viewport_width=1280
+window/size/viewport_height=720
+window/stretch/scale_mode="integer"
+
+[filesystem]
+
+import/blender/enabled=false
+
+[rendering]
+
+renderer/rendering_method="mobile"
+environment/defaults/default_clear_color=Color(0, 0, 0, 1)

+ 22 - 0
engine/scenes/launch/launch.tscn

@@ -0,0 +1,22 @@
+[gd_scene load_steps=2 format=3 uid="uid://i6g3y6btijjm"]
+
+[ext_resource type="Texture2D" uid="uid://d05rp7emahb2e" path="res://assets/launch/background.jpeg" id="1_5xji2"]
+
+[node name="Launch" type="Control"]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+
+[node name="Background" type="TextureRect" parent="."]
+layout_mode = 1
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+texture = ExtResource("1_5xji2")
+expand_mode = 2
+stretch_mode = 6

+ 28 - 0
engine/scripts/framework/client/client.gd

@@ -0,0 +1,28 @@
+#*****************************************************************************
+# @file    client.gd
+# @author  MakerYang(https://www.makeryang.com)
+# @statement 免费课程配套开源项目,任何形式收费均为盗版
+#*****************************************************************************
+extends Node
+
+# 初始化自定义数据
+var client_peer:ENetMultiplayerPeer
+
+# 初始化数据结构
+var data = {
+	"client_id": 0
+}
+
+# 创建客户端并返回客户端状态
+func create_client() -> int:
+	client_peer = ENetMultiplayerPeer.new()
+	var error = client_peer.create_client(Global.get_server_address(), Global.get_server_port())
+	if error == OK:
+		multiplayer.multiplayer_peer = client_peer
+		# 更新客户端ID
+		update_client_id(multiplayer.get_unique_id())
+	return error
+
+# 更新客户端ID
+func update_client_id(client_id: int) -> void:
+	data["client_id"] = client_id

+ 53 - 0
engine/scripts/framework/global.gd

@@ -0,0 +1,53 @@
+#*****************************************************************************
+# @file    global.gd
+# @author  MakerYang(https://www.makeryang.com)
+# @statement 免费课程配套开源项目,任何形式收费均为盗版
+#*****************************************************************************
+extends Node
+
+# 初始化数据结构
+var data = {
+	"varsion": "1.0.0",
+	"mode": "",
+	"server": {
+		"port": 7020,
+		"address": "game.makeryang.com"
+	},
+	"account": {
+		"token": ""
+	}
+}
+
+func _ready() -> void:
+	# 服务器模式检测
+	if OS.has_feature("dedicated_server"):
+		print("[服务器模式]")
+		data["mode"] = "server"
+		var error = Server.create_server()
+		if error != OK:
+			printerr("[服务器创建失败]")
+	else:
+		print("[客户端模式]")
+		data["mode"] = "client"
+		var error = Client.create_client()
+		if error != OK:
+			printerr("[服务器连接失败]")
+
+# 是否为服务器模式
+func is_server() -> bool:
+	var server = false
+	if data["mode"] == "server":
+		server = true
+	return server
+
+# 获取服务器端口
+func get_server_port() -> int:
+	return data["server"]["port"]
+
+# 获取服务器端口
+func get_server_address() -> String:
+	return data["server"]["address"]
+
+# 获取用户Token
+func get_account_token() -> String:
+	return data["account"]["token"]

+ 29 - 0
engine/scripts/framework/server/server.gd

@@ -0,0 +1,29 @@
+#*****************************************************************************
+# @file    server.gd
+# @author  MakerYang(https://www.makeryang.com)
+# @statement 免费课程配套开源项目,任何形式收费均为盗版
+#*****************************************************************************
+extends Node
+
+# 初始化自定义数据
+var server_peer:ENetMultiplayerPeer
+
+# 创建服务器并返回服务器状态
+func create_server() -> int:
+	print("[创建服务器...]")
+	server_peer = ENetMultiplayerPeer.new()
+	var error = server_peer.create_server(Global.get_server_port())
+	if error == OK:
+		multiplayer.multiplayer_peer = server_peer
+		multiplayer.peer_connected.connect(_on_peer_connected)
+		multiplayer.peer_disconnected.connect(_on_peer_disconnected)
+		print("[服务器创建成功]")
+	return error
+
+# 客户端连接服务器时回调函数
+func _on_peer_connected(id: int) -> void:
+	print("[新的客户端连接 " + str(id) + "]")
+
+# 客户端断开服务器时回调函数
+func _on_peer_disconnected(id: int) -> void:
+	print("[客户端连接断开 " + str(id) + "]")

+ 30 - 0
engine/scripts/framework/utils/request.gd

@@ -0,0 +1,30 @@
+#*****************************************************************************
+# @file    request.gd
+# @author  MakerYang(https://www.makeryang.com)
+# @statement 免费课程配套开源项目,任何形式收费均为盗版
+#*****************************************************************************
+extends Node
+
+# 初始化自定义数据
+var http_request:HTTPRequest = HTTPRequest.new()
+var http_callback = null
+
+# 初始化数据结构
+var data = {
+	"headers": [
+		"Content-Type: application/json",
+		"Account-Token: ",
+	]
+}
+
+# 请求服务器接口
+func on_server(path: String, method: int, parameter, callback) -> void:
+	if !http_request.is_inside_tree():
+		add_child(http_request)
+	var parameter_json = JSON.stringify(parameter)
+	data["headers"][1] = "Account-Token: " + Global.get_account_token()
+	if http_callback and http_request.is_connected("request_completed", http_callback):
+		http_request.request_completed.disconnect(http_callback)
+	http_request.request_completed.connect(callback)
+	http_callback = callback
+	http_request.request("https://" + Global.get_server_address() + path, data["headers"], method, parameter_json)

+ 49 - 0
readme.md

@@ -0,0 +1,49 @@
+# 🛠️ Engine2D
+
+⚡ 基于Godot的2D游戏开发框架 ⚡
+
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
+
+
+### 🔦 源码下载
+
+> 随着框架不断的迭代,仓库的历史提交数据逐渐庞大,你可以使用下面的命令来加速源码的下载。
+
+```shell
+git clone --depth=1 git@github.com:makeryangcom/Engine2D.git
+```
+
+### 🛸 技术栈
+
+> 构建一个完整的游戏需要多种技术栈的整合,本框架涉及的技术栈如下:
+
+| Software | Version | Describe |
+| - | - | - |
+| Godot | 4.2.1+ | 游戏引擎 |
+| Golang | 1.19.4+ | 后端服务 |
+| NodeJS | 18.13.0+ | 桌面管理工具 |
+
+### ✨ 目录结构
+
+> 框架包含游戏引擎、后端服务、桌面管理工具等核心模块,详见下面的目录结构说明:
+
+```html
+/Engine2D/
+├─engine <!--Godot游戏引擎源码-->
+├─server <!--Golang后端服务源码-->
+├─desktop <!--桌面管理工具源码-->
+```
+
+### 🚀 配套课程
+
+> 框架配套的相关的课程可以在`https://www.makeryang.com`获取。
+
+### 💡 关于作者
+
+🔗 Wechat: `makeryang8080`
+
+🔗 WebSite: `https://www.makeryang.com`
+
+🔗 Bilibili: `https://space.bilibili.com/596334734`
+
+🔗 DouYin&Tiktok: `MakerYang`

+ 52 - 0
server/framework/config/config.go

@@ -0,0 +1,52 @@
+/**
+ ******************************************************************************
+ * @file    config.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Config
+
+import "time"
+
+var Get = &config{}
+
+type config struct {
+	Service  service  `json:"service"`
+	Database database `json:"database"`
+	Hash     hash     `json:"hash"`
+}
+
+type service struct {
+	Mode         string        `json:"mode"`
+	HttpPort     int           `json:"http_port"`
+	ReadTimeout  time.Duration `json:"read_timeout"`
+	WriteTimeout time.Duration `json:"write_timeout"`
+}
+
+type database struct {
+	Type     string `json:"type"`
+	User     string `json:"user"`
+	Password string `json:"password"`
+	Host     string `json:"host"`
+	Name     string `json:"name"`
+}
+
+type hash struct {
+	Salt string `json:"salt"`
+}
+
+func Init() {
+	Get.Service.Mode = "debug"
+	Get.Service.HttpPort = 7000
+	Get.Service.ReadTimeout = 60 * time.Second
+	Get.Service.WriteTimeout = 60 * time.Second
+
+	Get.Database.Name = "database"
+	Get.Database.Type = "mysql"
+	Get.Database.Host = "localhost"
+	Get.Database.User = "root"
+	Get.Database.Password = "88888888"
+
+	Get.Hash.Salt = "game_$@#godot_@$salt_$@$service%#^#%@%#"
+}

+ 61 - 0
server/framework/controller/controller.go

@@ -0,0 +1,61 @@
+/**
+ ******************************************************************************
+ * @file    controller.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Controller
+
+import (
+	"Game/framework/config"
+	"Game/framework/controller/ping"
+	"context"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/gookit/color"
+	"log"
+	"net/http"
+	"os"
+	"os/signal"
+	"time"
+)
+
+func router() *gin.Engine {
+	router := gin.New()
+
+	gin.SetMode(Config.Get.Service.Mode)
+
+	router.GET("/ping", PingController.Ping)
+
+	return router
+}
+
+func Init() {
+	routers := router()
+
+	var HttpServer = &http.Server{
+		Addr:           fmt.Sprintf(":%d", Config.Get.Service.HttpPort),
+		Handler:        routers,
+		ReadTimeout:    Config.Get.Service.ReadTimeout,
+		WriteTimeout:   Config.Get.Service.WriteTimeout,
+		MaxHeaderBytes: 1 << 20,
+	}
+
+	go func() {
+		if err := HttpServer.ListenAndServe(); err != nil {
+		}
+	}()
+
+	log.Println("[game]", color.Green.Text("server..."))
+
+	quit := make(chan os.Signal)
+	signal.Notify(quit, os.Interrupt)
+	<-quit
+
+	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+	defer cancel()
+
+	if err := HttpServer.Shutdown(ctx); err != nil {
+	}
+}

+ 18 - 0
server/framework/controller/ping/ping.go

@@ -0,0 +1,18 @@
+/**
+ ******************************************************************************
+ * @file    ping.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package PingController
+
+import (
+	"Game/framework/utils"
+	"github.com/gin-gonic/gin"
+)
+
+func Ping(c *gin.Context) {
+	Utils.Success(c, Utils.EmptyData{})
+	return
+}

+ 74 - 0
server/framework/database/database.go

@@ -0,0 +1,74 @@
+/**
+ ******************************************************************************
+ * @file    database.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Database
+
+import (
+	"Game/framework/config"
+	"fmt"
+	"github.com/gookit/color"
+	"github.com/jinzhu/gorm"
+	_ "github.com/jinzhu/gorm/dialects/mysql"
+	"log"
+	"time"
+)
+
+var Get *gorm.DB
+
+type DefaultField struct {
+	CreateAt int `gorm:"Column:create_at" json:"create_at"`
+	UpdateAt int `gorm:"Column:update_at" json:"update_at"`
+	DeleteAt int `gorm:"Column:delete_at" json:"delete_at"`
+}
+
+func Init() {
+
+	var err error
+
+	Get, err = gorm.Open(Config.Get.Database.Type, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", Config.Get.Database.User, Config.Get.Database.Password, Config.Get.Database.Host, Config.Get.Database.Name))
+	if err != nil {
+		log.Println("[database]", color.Red.Text(err.Error()))
+	}
+
+	if Config.Get.Service.Mode == "release" {
+		Get.LogMode(false)
+	} else {
+		Get.LogMode(true)
+	}
+
+	gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
+		return defaultTableName
+	}
+
+	Get.SingularTable(true)
+
+	Get.Callback().Create().Replace("gorm:update_time_stamp", func(scope *gorm.Scope) {
+		if !scope.HasError() {
+			nowTime := time.Now().Unix()
+			if createTimeField, ok := scope.FieldByName("CreateAt"); ok {
+				if createTimeField.IsBlank {
+					err := createTimeField.Set(nowTime)
+					if err != nil {
+					}
+				}
+			}
+
+			if modifyTimeField, ok := scope.FieldByName("UpdateAt"); ok {
+				if modifyTimeField.IsBlank {
+					err := modifyTimeField.Set(nowTime)
+					if err != nil {
+					}
+				}
+			}
+		}
+	})
+
+	Get.DB().SetMaxIdleConns(1000)
+	Get.DB().SetMaxOpenConns(10000)
+
+	Get.DB().SetConnMaxLifetime(time.Second * 45)
+}

+ 65 - 0
server/framework/database/interface.go

@@ -0,0 +1,65 @@
+/**
+ ******************************************************************************
+ * @file    interface.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Database
+
+import (
+	"github.com/jinzhu/gorm"
+	"time"
+)
+
+type Base struct {
+	TableName string
+}
+
+func New(table string) *Base {
+	return &Base{
+		TableName: table,
+	}
+}
+
+func (base *Base) CreateData(data interface{}) error {
+	err := Get.Table(base.TableName).Create(data).Error
+	return err
+}
+
+func (base *Base) UpdateData(query interface{}, data map[string]interface{}) error {
+	data["update_at"] = time.Now().Unix()
+	err := Get.Table(base.TableName).Where(query).Updates(data).Error
+	return err
+}
+
+func (base *Base) ExprData(query interface{}, field string, operation string, data int) error {
+	err := Get.Table(base.TableName).Where(query).Update(field, gorm.Expr(field+" "+operation+" ?", data)).Error
+	return err
+}
+
+func (base *Base) GetData(dataStruct interface{}, query interface{}, order string) error {
+	err := Get.Table(base.TableName).Where(query).Order(order).First(dataStruct).Error
+	return err
+}
+
+func (base *Base) ListData(dataStruct interface{}, query interface{}, order string, limit int) error {
+	err := Get.Table(base.TableName).Where(query).Order(order).Limit(limit).Find(dataStruct).Error
+	return err
+}
+
+func (base *Base) PageData(dataStruct interface{}, query interface{}, order string, limit int, page int) error {
+	err := Get.Table(base.TableName).Where(query).Order(order).Limit(limit).Offset(page * limit).Find(dataStruct).Error
+	return err
+}
+
+func (base *Base) CountData(query interface{}) (int, error) {
+	count := 0
+	err := Get.Table(base.TableName).Where(query).Count(&count).Error
+	return count, err
+}
+
+func (base *Base) DeleteData(dataStruct interface{}, query interface{}) error {
+	err := Get.Table(base.TableName).Where(query).Delete(dataStruct).Error
+	return err
+}

+ 23 - 0
server/framework/framework.go

@@ -0,0 +1,23 @@
+/**
+ ******************************************************************************
+ * @file    framework.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Framework
+
+import (
+	"Game/framework/config"
+	"Game/framework/controller"
+	"Game/framework/database"
+)
+
+func Init() {
+	// 初始化配置
+	Config.Init()
+	// 初始化数据库
+	Database.Init()
+	// 初始化控制器
+	Controller.Init()
+}

+ 3 - 0
server/framework/utils/empty_data.go

@@ -0,0 +1,3 @@
+package Utils
+
+type EmptyData struct{}

+ 27 - 0
server/framework/utils/hashids.go

@@ -0,0 +1,27 @@
+package Utils
+
+import (
+	"Game/framework/config"
+	"github.com/speps/go-hashids"
+)
+
+func EncodeId(len int, id ...int) string {
+	hd := hashids.NewData()
+	hd.Salt = Config.Get.Hash.Salt
+	hd.MinLength = len
+	h := hashids.NewWithData(hd)
+	e, _ := h.Encode(id)
+	return e
+}
+
+func DecodeId(len int, encodedId string) ([]int, error) {
+	hd := hashids.NewData()
+	hd.Salt = Config.Get.Hash.Salt
+	hd.MinLength = len
+	h := hashids.NewWithData(hd)
+	d, err := h.DecodeWithError(encodedId)
+	if err != nil {
+		return nil, err
+	}
+	return d, nil
+}

+ 49 - 0
server/framework/utils/header.go

@@ -0,0 +1,49 @@
+package Utils
+
+import "strings"
+
+func CheckUserAgent(userAgent string) bool {
+	Status := false
+
+	if strings.Contains(userAgent, "GodotEngine") {
+		Status = true
+	}
+
+	return Status
+}
+
+func CheckGame(token string) (int, int, bool) {
+	Status := false
+	GameId := 0
+	GameAccountId := 0
+
+	if token != "" {
+		tokenMap, _ := DecodeId(128, token)
+		if len(tokenMap) == 2 {
+			GameId = tokenMap[0]
+			GameAccountId = tokenMap[1]
+			Status = true
+		}
+	}
+
+	if GameId == 0 || GameAccountId == 0 {
+		Status = false
+	}
+
+	return GameId, GameAccountId, Status
+}
+
+func CheckUser(token string) (int, bool) {
+	Status := false
+	Uid := 0
+
+	if token != "" {
+		tokenMap, _ := DecodeId(32, token)
+		if len(tokenMap) == 3 {
+			Uid = tokenMap[0]
+			Status = true
+		}
+	}
+
+	return Uid, Status
+}

+ 17 - 0
server/framework/utils/mailbox.go

@@ -0,0 +1,17 @@
+package Utils
+
+import "gopkg.in/gomail.v2"
+
+func SendMail(to string, subject string, content string) bool {
+	status := true
+	mail := gomail.NewMessage()
+	mail.SetHeader("From", mail.FormatAddress("open@wileho.com", "GEEKROS"))
+	mail.SetHeader("To", to)
+	mail.SetHeader("Subject", subject)
+	mail.SetBody("text/html", content)
+	send := gomail.NewDialer("smtp.qq.com", 587, "open@wileho.com", "")
+	if err := send.DialAndSend(mail); err != nil {
+		status = false
+	}
+	return status
+}

+ 27 - 0
server/framework/utils/markdown.go

@@ -0,0 +1,27 @@
+package Utils
+
+import (
+	"regexp"
+	"strings"
+)
+
+func FilterMarkdown(input string) string {
+	quoteBlockRegex := regexp.MustCompile(`^\s*>[ \t]*(.*)$`)
+	lines := strings.Split(input, "\n")
+	var quoteLines []string
+	for _, line := range lines {
+		if quoteBlockRegex.MatchString(line) {
+			match := quoteBlockRegex.FindStringSubmatch(line)
+			quoteLines = append(quoteLines, match[1])
+		}
+	}
+	return strings.Join(quoteLines, "")
+}
+
+func FilterSummary(input string, maxLength int) string {
+	text := strings.TrimSpace(input)
+	if len(text) <= maxLength {
+		return text
+	}
+	return text[:maxLength]
+}

+ 22 - 0
server/framework/utils/md5.go

@@ -0,0 +1,22 @@
+/**
+ ******************************************************************************
+ * @file    md5.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package Utils
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+)
+
+func MD5Hash(text string) string {
+	hash := md5.Sum([]byte(text))
+	return hex.EncodeToString(hash[:])
+}
+
+func VerifyPassword(storedPassword, inputPassword string) bool {
+	return MD5Hash(inputPassword) == storedPassword
+}

+ 18 - 0
server/framework/utils/order.go

@@ -0,0 +1,18 @@
+package Utils
+
+import (
+	"math/rand"
+	"time"
+)
+
+func CreateOrderNum() string {
+	str := "0123456789"
+	bytes := []byte(str)
+	result := make([]byte, 0)
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+	for i := 0; i < 8; i++ {
+		result = append(result, bytes[r.Intn(len(bytes))])
+	}
+	order := time.Now().Format("20060102150405") + string(result)
+	return order
+}

+ 69 - 0
server/framework/utils/phone.go

@@ -0,0 +1,69 @@
+package Utils
+
+import (
+	"bytes"
+	"encoding/json"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"regexp"
+)
+
+func MobileFormat(str string) string {
+	re, _ := regexp.Compile("(\\d{3})(\\d{6})(\\d{2})")
+	return re.ReplaceAllString(str, "$1******$3")
+}
+
+func SendMessage(form string, phone string, info string) bool {
+	status := true
+	if form == "" || phone == "" || info == "" {
+		status = false
+		return status
+	}
+	desc := ""
+	if form == "express" {
+		desc = "【GEEKROS】Hi," + info + " ,你在GEEKROS的订单已经发货,请留意快递信息,及时查收。"
+	}
+	if form == "account" {
+		desc = "【GEEKROS】你的验证码为:" + info + " ,有效期10分钟,工作人员绝不会索取此验证码,切勿告知他人。"
+	}
+
+	apiUrl := "https://smssh1.253.com/msg/v1/send/json"
+	params := make(map[string]interface{})
+	params["account"] = ""
+	params["password"] = ""
+	params["phone"] = phone
+	params["msg"] = desc
+	params["report"] = "false"
+
+	bytesData, err := json.Marshal(params)
+	if err != nil {
+		status = false
+		return status
+	}
+
+	reader := bytes.NewReader(bytesData)
+	request, err := http.NewRequest("POST", apiUrl, reader)
+	if err != nil {
+		status = false
+		return status
+	}
+
+	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
+	client := http.Client{}
+	resp, err := client.Do(request)
+	if err != nil {
+		status = false
+		return status
+	}
+
+	respBytes, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		status = false
+		return status
+	}
+
+	log.Println("[PhoneMessage]", string(respBytes))
+
+	return true
+}

+ 7 - 0
server/framework/utils/price.go

@@ -0,0 +1,7 @@
+package Utils
+
+import "fmt"
+
+func PriceConvert(num int) string {
+	return fmt.Sprintf("%.2f", float64(num)/100)
+}

+ 20 - 0
server/framework/utils/rand.go

@@ -0,0 +1,20 @@
+package Utils
+
+import (
+	"fmt"
+	"math/rand"
+	"time"
+)
+
+func RandInt(min, max int) int {
+	if min >= max || min == 0 || max == 0 {
+		return max
+	}
+	return rand.Intn(max-min) + min
+}
+
+func RandCode() string {
+	randNumber := rand.New(rand.NewSource(time.Now().UnixNano()))
+	code := fmt.Sprintf("%06v", randNumber.Int31n(1000000))
+	return code
+}

+ 105 - 0
server/framework/utils/return.go

@@ -0,0 +1,105 @@
+package Utils
+
+import (
+	"encoding/json"
+	"github.com/gin-gonic/gin"
+	"log"
+	"net/http"
+	"os"
+	"strconv"
+	"time"
+)
+
+type logData struct {
+	Timestamp       int64  `json:"timestamp"`
+	TimestampFormat string `json:"timestamp_format"`
+	ClientMethod    string `json:"client_method"`
+	ClientIp        string `json:"client_ip"`
+	ClientParameter string `json:"client_parameter"`
+	ServerParameter string `json:"server_parameter"`
+	ServerUrl       string `json:"server_url"`
+	ServerName      string `json:"server_name"`
+	ServerYear      string `json:"server_year"`
+	ServerMonth     string `json:"server_month"`
+	ServerDay       string `json:"server_day"`
+	ServerTime      string `json:"server_time"`
+	TimeLength      string `json:"time_length"`
+}
+
+func recordLog(c *gin.Context, serverParameter string) {
+	data := &logData{}
+	data.Timestamp = time.Now().Unix()
+	data.TimestampFormat = time.Now().Format("2006-01-02 15:04:05")
+	data.ClientMethod = c.Request.Method
+	data.ClientIp = c.ClientIP()
+	if data.ClientMethod == "GET" {
+		data.ClientParameter = c.Request.RequestURI
+	}
+	if data.ClientMethod == "POST" {
+		clientParam, err := json.Marshal(c.Request.PostForm)
+		if err != nil {
+			data.ClientParameter = ""
+		}
+		if err == nil {
+			data.ClientParameter = string(clientParam)
+		}
+	}
+	scheme := "http://"
+	if c.Request.TLS != nil {
+		scheme = "https://"
+	}
+	serverUrl := scheme + c.Request.Host + c.Request.URL.Path
+	serverName, _ := os.Hostname()
+	data.ServerUrl = serverUrl
+	data.ServerName = serverName
+	data.ClientParameter = c.GetString("client_parameter")
+	data.ServerParameter = serverParameter
+	data.ServerYear = time.Now().Format("2006")
+	data.ServerMonth = time.Now().Format("01")
+	data.ServerDay = time.Now().Format("02")
+	data.ServerTime = time.Now().Format("15:04:05")
+	data.TimeLength = strconv.FormatFloat(float64(time.Now().UnixNano())/1000000-c.GetFloat64("start_time"), 'f', 2, 64)
+	dataString, _ := json.Marshal(data)
+
+	log.Println("[Log]", string(dataString))
+}
+
+func Success(c *gin.Context, data interface{}) {
+	c.JSON(http.StatusOK, gin.H{
+		"code": 0,
+		"msg":  "success",
+		"data": data,
+	})
+	logJson, _ := json.Marshal(gin.H{"code": 0, "msg": "success", "data": data})
+	recordLog(c, string(logJson))
+}
+
+func Error(c *gin.Context, data interface{}) {
+	c.JSON(http.StatusOK, gin.H{
+		"code": 10000,
+		"msg":  "error",
+		"data": data,
+	})
+	logJson, _ := json.Marshal(gin.H{"code": 10000, "msg": "error", "data": data})
+	recordLog(c, string(logJson))
+}
+
+func Warning(c *gin.Context, code int, msg string, data interface{}) {
+	c.JSON(http.StatusOK, gin.H{
+		"code": code,
+		"msg":  msg,
+		"data": data,
+	})
+	logJson, _ := json.Marshal(gin.H{"code": code, "msg": msg, "data": data})
+	recordLog(c, string(logJson))
+}
+
+func AuthError(c *gin.Context, code int, msg string, data interface{}) {
+	c.JSON(http.StatusUnauthorized, gin.H{
+		"code": code,
+		"msg":  msg,
+		"data": data,
+	})
+	logJson, _ := json.Marshal(gin.H{"code": code, "msg": msg, "data": data})
+	recordLog(c, string(logJson))
+}

+ 33 - 0
server/framework/utils/time.go

@@ -0,0 +1,33 @@
+package Utils
+
+import (
+	"strconv"
+	"time"
+)
+
+func TimeFormat(unix int) (string, string) {
+	timeInt := time.Unix(int64(unix), 0)
+	return timeInt.Format("2006年01月02日"), timeInt.Format("2006-01-02 15:04:05")
+}
+
+func DateFormat(times int) string {
+	createTime := time.Unix(int64(times), 0)
+	now := time.Now().Unix()
+
+	difTime := now - int64(times)
+
+	str := ""
+	if difTime < 60 {
+		str = "刚刚"
+	} else if difTime < 3600 {
+		M := difTime / 60
+		str = strconv.Itoa(int(M)) + "分钟前"
+	} else if difTime < 3600*24 {
+		H := difTime / 3600
+		str = strconv.Itoa(int(H)) + "小时前"
+	} else {
+		str = createTime.Format("2006-01-02 15:04:05")
+	}
+
+	return str
+}

+ 42 - 0
server/go.mod

@@ -0,0 +1,42 @@
+module Game
+
+go 1.19
+
+require (
+	github.com/gin-gonic/gin v1.9.1
+	github.com/gookit/color v1.5.4
+	github.com/jinzhu/gorm v1.9.16
+	github.com/speps/go-hashids v1.0.0
+	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
+)
+
+require (
+	github.com/bytedance/sonic v1.9.1 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.14.0 // indirect
+	github.com/go-sql-driver/mysql v1.5.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/jinzhu/inflection v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
+	github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/crypto v0.9.0 // indirect
+	golang.org/x/net v0.10.0 // indirect
+	golang.org/x/sys v0.10.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
+	google.golang.org/protobuf v1.30.0 // indirect
+	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 126 - 0
server/go.sum

@@ -0,0 +1,126 @@
+github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
+github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
+github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
+github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
+github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
+github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
+github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
+github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
+github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
+github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
+github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
+github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
+github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M=
+github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
+github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
+github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
+github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/speps/go-hashids v1.0.0 h1:jdFC07PrExRM4Og5Ev4411Tox75aFpkC77NlmutadNI=
+github.com/speps/go-hashids v1.0.0/go.mod h1:P7hqPzMdnZOfyIk+xrlG1QaSMw+gCBdHKsBDnhpaZvc=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
+github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
+golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
+golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
+gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
+gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

+ 15 - 0
server/main.go

@@ -0,0 +1,15 @@
+/**
+ ******************************************************************************
+ * @file    main.go
+ * @author  MakerYang
+ ******************************************************************************
+ */
+
+package main
+
+import "Game/framework"
+
+func main() {
+	// 初始化核心框架
+	Framework.Init()
+}

+ 0 - 0
tools/centos/data/wwwroot/default/index.html


+ 41 - 0
tools/centos/etc/nginx/conf.d/game.makeryang.com.conf

@@ -0,0 +1,41 @@
+server {
+    listen 80;
+    listen [::]:80;
+    listen 443 ssl http2;
+    listen [::]:443 ssl http2;
+    ssl_certificate /etc/nginx/ssl/game.makeryang.com.pem;
+    ssl_certificate_key /etc/nginx/ssl/game.makeryang.com.key;
+    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
+    ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
+    ssl_prefer_server_ciphers on;
+    ssl_session_timeout 10m;
+    ssl_session_cache builtin:1000 shared:SSL:10m;
+    ssl_buffer_size 1400;
+    add_header Strict-Transport-Security max-age=15768000;
+    ssl_stapling on;
+    ssl_stapling_verify on;
+    server_name game.makeryang.com;
+    access_log off;
+    if ($ssl_protocol = "") { return 301 https://$host$request_uri; }
+    location / {
+        client_max_body_size 100m;
+        proxy_set_header X-Forwarded-Host $host;
+        proxy_set_header X-Forwarded-Server $host;
+        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+        proxy_pass http://localhost:7000/;
+        proxy_ignore_client_abort on;
+        proxy_set_header Cookie $http_cookie;
+        proxy_set_header Host $host;
+    }
+    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
+        expires 60s;
+        access_log off;
+    }
+    location ~ .*\.(js|css)?$ {
+        expires 60s;
+        access_log off;
+    }
+    location ~ /(\.user\.ini|\.ht|\.git|\.svn|\.project|LICENSE|README\.md) {
+        deny all;
+    }
+}

+ 30 - 0
tools/centos/etc/nginx/nginx.conf

@@ -0,0 +1,30 @@
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log;
+pid /run/nginx.pid;
+
+events {
+    worker_connections 1024;
+}
+
+http {
+    gzip on;
+    gzip_vary on;
+    gzip_proxied any;
+    gzip_min_length 1000;
+    gzip_comp_level 6;
+    gzip_types text/plain application/xml application/json application/javascript text/css;
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+    access_log  /var/log/nginx/access.log  main;
+    sendfile            on;
+    tcp_nopush          on;
+    tcp_nodelay         on;
+    keepalive_timeout   65;
+    types_hash_max_size 4096;
+    include             /etc/nginx/mime.types;
+    default_type        application/octet-stream;
+    include /etc/nginx/conf.d/*.conf;
+}
+

+ 27 - 0
tools/centos/etc/nginx/ssl/game.makeryang.com.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAjNDUW/WYlpctqVq0+kRwknV+pZsWWN95sqErhls7047CnWoA
+V/RxUUj8aIOCVgBX91wDXPSRVuPqmu6Eqc/E+5KIvLCZxg6hoj0aTV+Od1+7Ane2
+PgFAUNNTTeNYpDUAIsvejQTBSxhpWYvx+MKXgGL4C9ysLRBYfZOFy9jGwsd5kxM0
+tqZY1jByyX7p/HAEJVCZe8jdfOZssZjoj+NPXRIivsU+vO3Lv0Pr7yY2vsRi3Aa+
+RUCL45t8nbRf9RRA1EkHxnmnuG6QWng/Td5xUbEEkrdreizqH6f08aNJAmyeH9kE
+F61MU7nxfpAG5Pu2Bcj7jZo0eXLz+oDjIKlnkwIDAQABAoIBAAcogHsSP4j8M2aG
+BWgpfX18eo0plpe6+IFDnyZL0f09pxgAcPcHppEGwEoB0WjUyKP66fLaPd8oY98v
+W9AUD0PonYnWAmMmkEHikEk5n9DirWuBMWLyhlX1gCkX8wQZ66FZMr2BbeAG5CgY
+rJrELZZpsYlM1PXPfGgZzTXhFa2GChCeLKla0Z9eQmn5J/eGfaolbrjFeSDAlWOA
+IZHO7cm3vSvNWfsfkKmO/s8dzwlVC86rw0Wpx5crLGVsFXTFlOYTVLIOciXeN2vc
+gfvYD9E/S+HEYAiYtT+J82QVbkxzvdJ8tzqCmD4gUjl4ORRdxNsHZX23mxAcJ0gi
+zXfWsFUCgYEAw7oO0M3TYZpVB5HmU4nWrPXy4HS9L4N2HJMjxX4ihfG53t1cHi2T
+oTuOHtL4H/FZHnhBt2++2W142AeHFvSDsbeCLACZe7zxfVJyWid1EWBUtJEtLJ7n
+rJbuyvR5OsC9TSgijotafet9J+IJGMlv2Z5rJdULJe4k6256bJNbk1cCgYEAuC3o
+0iMv8lcHqIT4h6Q+CZBVZUD4PwkFfcuU5+fMHRbaylAZpolRCc8A4uLilG2+egJK
+Mt7M8dJnEONxffUmlJg0zIdG2xTvDC+3rnz4jtTOEUw/1tB0oCRj84sk4LyNcjkG
+ls2w/tbY08VLwf5H9CnflNt551aJNdLAh1TGRCUCgYEAriJjugvVK7oGOnTo6Zvx
+vfIXwvC5vIMGW0fhhHzDNE4qowhoQ4UjGkiFGhFypeCw/DXbqdsmfgUyhWi1HIww
+erWcf4+M/hTM+UWX7XO7aNk+o2OiQFekIN4r16+IB+igwvuZOx7qRKt1rz0gAMh+
+1atnAsK3Z2inujqRevXjfIMCgYEAjy4BhPsd1wOZTISywKAKKl0uRdzQIBDfV//f
+7rjgkOynggfrKPAvM7TdN4SyKDl4jlkhXZKfOI8c2KA4JndiWrpIsYeoqcAIZizi
+Wp+Ei2UcHY5tQo4jXCtuGHLfZGawf0+ds7aMFlDnlxoV3uXTAhlbWtmUVyeK23DP
+g2WADJECgYAPux2BixHtl0pYDgw2sk1wrV94+hBAVjxIXq5B1jABYP6vKYe6ry40
+BP26LVCcPDHSuhWBUYasKe3OFlXrcBRInnz8HvD0cPsZ2OUTw0muA98S0TL/NAz9
+WMY04UX0LkFroAmZ4OpsN5dnaYUyyLtE4fL1YzY4yaQm2cAjL4503g==
+-----END RSA PRIVATE KEY-----

+ 61 - 0
tools/centos/etc/nginx/ssl/game.makeryang.com.pem

@@ -0,0 +1,61 @@
+-----BEGIN CERTIFICATE-----
+MIIF/DCCBOSgAwIBAgIQBoJL0yXtOOlqcGZrSYZ7/jANBgkqhkiG9w0BAQsFADBu
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
+RFYgVExTIENBIC0gRzIwHhcNMjQwMjE3MDAwMDAwWhcNMjQwNTE3MjM1OTU5WjAd
+MRswGQYDVQQDExJnYW1lLm1ha2VyeWFuZy5jb20wggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQCM0NRb9ZiWly2pWrT6RHCSdX6lmxZY33myoSuGWzvTjsKd
+agBX9HFRSPxog4JWAFf3XANc9JFW4+qa7oSpz8T7koi8sJnGDqGiPRpNX453X7sC
+d7Y+AUBQ01NN41ikNQAiy96NBMFLGGlZi/H4wpeAYvgL3KwtEFh9k4XL2MbCx3mT
+EzS2pljWMHLJfun8cAQlUJl7yN185myxmOiP409dEiK+xT687cu/Q+vvJja+xGLc
+Br5FQIvjm3ydtF/1FEDUSQfGeae4bpBaeD9N3nFRsQSSt2t6LOofp/Txo0kCbJ4f
+2QQXrUxTufF+kAbk+7YFyPuNmjR5cvP6gOMgqWeTAgMBAAGjggLlMIIC4TAfBgNV
+HSMEGDAWgBR435GQX+7erPbFdevVTFVT7yRKtjAdBgNVHQ4EFgQU6CVLerV8rRvI
+fdoqmcaWm4fsq7YwHQYDVR0RBBYwFIISZ2FtZS5tYWtlcnlhbmcuY29tMD4GA1Ud
+IAQ3MDUwMwYGZ4EMAQIBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNl
+cnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
+CCsGAQUFBwMCMIGABggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v
+Y3NwLmRpZ2ljZXJ0LmNvbTBKBggrBgEFBQcwAoY+aHR0cDovL2NhY2VydHMuZGln
+aWNlcnQuY29tL0VuY3J5cHRpb25FdmVyeXdoZXJlRFZUTFNDQS1HMi5jcnQwDAYD
+VR0TAQH/BAIwADCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA7s3QZNXbGs7F
+XLedtM0TojKHRny87N7DUUhZRnEftZsAAAGNtbUunQAABAMARzBFAiAoHm9oq5Du
+j0gXKhJHx3CAUASFmepG+Jz5tEp5Zp/aUgIhAKH9B4MIkeX4XVg7g74me98+CBJp
+dB3Fl71y13Lj0vK+AHUASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznYhHMA
+AAGNtbUt/gAABAMARjBEAiAYaTJ6DJNwpYdjHaDuxLZNxDca+4iFb5s3ZH/g5v3R
+3QIgT2V0+vR4/d0IS2X/BN9g2xtdXKM57AS4t1hl3nO6QpAAdwDatr9rP7W2Ip+b
+wrtca+hwkXFsu1GEhTS9pD0wSNf7qwAAAY21tS3XAAAEAwBIMEYCIQCBAcmOf56D
+/zT2t+M17f9HJCuaAAO640nSaEkC23p2jQIhAJbfBeNyZRUwz1hFbzsOMrTrRGIt
+bLtxLEjydi/ChMMSMA0GCSqGSIb3DQEBCwUAA4IBAQCGwgJRgCUSzVHVsxFxHpEW
+9U3iK9abAq215/wG4F1rXOrnlSXANxkyH/5LCbSvLWEAOiOnBQOIWx7dUcNqk6eq
+oh6XF8IDm5U3VFLawpdYEevcn+L4iFGEMtZl368s4EBjLGt5sUsgwKpo4n+ttMVL
+C7np4+ENPa1PS44PZGUEAWakeZwoTNo+5CVRl++XP9ce+PxcROhJ7/msfcf04s2C
+NmzGIkP6xnDmgekGRcjkivbzqPttx75R5yr73voNW2UJ0XH+UWLWZClWnc5MIne8
+3n1bTFuKKeN15V6lOUSFl+DfdJ1C91Oxf03j9miYJ3nnxPgQYqqQTbisgLarUB4J
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIQDeD/te5iy2EQn2CMnO1e0zANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xNzExMjcxMjQ2NDBaFw0yNzExMjcxMjQ2NDBaMG4xCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
+MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO8Uf46i/nr7pkgTDqnE
+eSIfCFqvPnUq3aF1tMJ5hh9MnO6Lmt5UdHfBGwC9Si+XjK12cjZgxObsL6Rg1njv
+NhAMJ4JunN0JGGRJGSevbJsA3sc68nbPQzuKp5Jc8vpryp2mts38pSCXorPR+sch
+QisKA7OSQ1MjcFN0d7tbrceWFNbzgL2csJVQeogOBGSe/KZEIZw6gXLKeFe7mupn
+NYJROi2iC11+HuF79iAttMc32Cv6UOxixY/3ZV+LzpLnklFq98XORgwkIJL1HuvP
+ha8yvb+W6JislZJL+HLFtidoxmI7Qm3ZyIV66W533DsGFimFJkz3y0GeHWuSVMbI
+lfsCAwEAAaOCAU8wggFLMB0GA1UdDgQWBBR435GQX+7erPbFdevVTFVT7yRKtjAf
+BgNVHSMEGDAWgBROIlQgGJXm427mD/r6uRLtBhePOTAOBgNVHQ8BAf8EBAMCAYYw
+HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
+AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
+Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
+Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
+/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
+MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAoBs1eCLKakLtVRPFRjBIJ9LJ
+L0s8ZWum8U8/1TMVkQMBn+CPb5xnCD0GSA6L/V0ZFrMNqBirrr5B241OesECvxIi
+98bZ90h9+q/X5eMyOD35f8YTaEMpdnQCnawIwiHx06/0BfiTj+b/XQih+mqt3ZXe
+xNCJqKexdiB2IWGSKcgahPacWkk/BAQFisKIFYEqHzV974S3FAz/8LIfD58xnsEN
+GfzyIDkH3JrwYZ8caPTf6ZX9M1GrISN8HnWTtdNCH2xEajRa/h9ZBXjUyFKQrGk2
+n2hcLrfZSbynEC/pSw/ET7H5nWwckjmAJ1l9fcnbqkU/pf6uMQmnfl0JQjJNSg==
+-----END CERTIFICATE-----

+ 13 - 0
tools/centos/etc/systemd/system/game.service

@@ -0,0 +1,13 @@
+[Unit]
+Description=Game
+After=syslog.target network.target
+
+[Service]
+Type=simple
+Environment=GODOT_SILENCE_ROOT_WARNING=1
+WorkingDirectory=/data/wwwroot/game/
+ExecStart=/data/wwwroot/game/server.x86_64 --headless
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target

+ 12 - 0
tools/centos/etc/systemd/system/server.service

@@ -0,0 +1,12 @@
+[Unit]
+Description=Server
+After=syslog.target network.target
+
+[Service]
+Type=simple
+WorkingDirectory=/data/wwwroot/server/
+ExecStart=/data/wwwroot/server/main
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target

+ 27 - 0
tools/update.sh

@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -e
+
+# 复制Nginx、服务配置配置
+sudo cp -r ./tools/centos/* /
+
+# 复制后端服务到运行目录
+sudo cp -r ./server /data/wwwroot/
+
+# 创建游戏引擎服务端运行目录
+if [ ! -d "/data/wwwroot/game" ]; then
+    mkdir -p /data/wwwroot/game
+fi
+
+# 编译后端服务
+cd /data/wwwroot/server/
+/usr/local/go/bin/go env -w GOSUMDB=off
+export GO111MODULE=on && export GOPROXY=https://goproxy.io && /usr/local/go/bin/go build main.go
+
+# 重启Nginx服务
+sudo systemctl restart nginx.service
+
+# 重启后端服务和游戏服务
+sudo systemctl daemon-reload
+sudo systemctl restart server.service
+sudo systemctl restart game.service

+ 5 - 0
update.bat

@@ -0,0 +1,5 @@
+@echo off
+
+scp -r ./engine/release/server* root@172.21.255.206:/data/wwwroot/game/
+
+ssh root@172.21.255.206 "chmod +x /data/wwwroot/game/* && cd /opt/Engine2D && sudo ./tools/update.sh"

+ 100 - 0
wiki/course/0001.md

@@ -0,0 +1,100 @@
+## 第一课
+
+> 第一课时操作引导文档。
+
+### 一、游戏资源下载
+
+> 1、访问:[GitHub](https://www.github.com)
+
+> 2、下载安装Git:[Git](https://git-scm.com)
+
+````shell
+# 生成GitHub SSH KEY
+ssh-keygen -t rsa -C "你的GitHub登录账号"
+````
+
+```shell
+git config -global user.name "你的GitHub用户名"
+git config -global user.email "你的GitHub登录账号"
+```
+```shell
+# 下载游戏源码
+git clone --depth=1 git@github.com:makeryangcom/Engine2D.git
+```
+
+### 二、虚拟机的安装和配置
+
+> 1、CentOS系统镜像下载地址:[CentOS-8.5.2111-x86_64-dvd1.iso](https://mirrors.aliyun.com/centos/8/isos/x86_64/CentOS-8.5.2111-x86_64-dvd1.iso)
+
+> 2、切换到root用户,密码为`root`
+
+```shell
+su
+```
+
+> 3、修改SSH配置,防止后续SSH远程登录时因连接超时自动断开
+
+```shell
+vim /etc/ssh/sshd_config
+```
+
+> 4、获取虚拟机服务器内网IP地址
+
+```shell
+ifconfig
+```
+
+> 5、在本地电脑的命令行工具中通过SSH远程登录到虚拟机服务器
+
+```shell
+ssh root@服务器内网IP地址
+```
+
+> 6、更新软件源
+
+```shell
+sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
+sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
+# 设置阿里云软件源
+wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
+# 清理缓存
+yum clean all
+yum makecache
+```
+
+> 7、切换到root用户
+
+```shell
+yum update -y
+```
+
+> 8、安装常用的软件和组件
+
+```shell
+yum install -y vim curl git openssl openssl-devel
+```
+
+> 9、安装Nginx
+
+```shell
+yum install -y nginx
+```
+
+``` bash
+# 启动Nginx服务
+sudo systemctl start nginx.service
+```
+
+``` bash
+# 设置Nginx服务开机启动
+sudo systemctl enable nginx.service
+```
+
+``` bash
+# 常用维护命令-重启Nginx服务
+sudo systemctl restart nginx.service
+# 常用维护命令-停止Nginx服务
+sudo systemctl stop nginx.service
+# 常用维护命令-启动Nginx服务
+sudo systemctl start nginx.service
+```