265 lines
7.3 KiB
Go
265 lines
7.3 KiB
Go
package gitService
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"g-launcher/pkg/constant"
|
|
"g-launcher/pkg/logger"
|
|
"g-launcher/pkg/models"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/wailsapp/wails/v3/pkg/application"
|
|
)
|
|
|
|
func (g *GitService) GetLatestServerVersion() (bool, string, string) {
|
|
client := &http.Client{Timeout: 15 * time.Second}
|
|
resp, err := client.Get(constant.ServerGitUrl)
|
|
if err != nil {
|
|
return false, "", err.Error()
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return false, "", err.Error()
|
|
}
|
|
|
|
var releases []models.ReleaseType
|
|
err = json.Unmarshal(body, &releases)
|
|
if err != nil {
|
|
return false, "", err.Error()
|
|
}
|
|
|
|
if len(releases) == 0 {
|
|
return false, "", "no releases found"
|
|
}
|
|
|
|
return true, releases[0].TagName, ""
|
|
}
|
|
|
|
func (g *GitService) DownloadServerProgress(version string) (bool, string) {
|
|
client := &http.Client{Timeout: 15 * time.Second}
|
|
resp, err := client.Get(constant.ServerGitUrl)
|
|
if err != nil {
|
|
return false, fmt.Sprintf("fetch server releases: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return false, fmt.Sprintf("read server releases: %v", err)
|
|
}
|
|
|
|
var releases []*models.ReleaseType
|
|
if err := json.Unmarshal(body, &releases); err != nil || len(releases) == 0 {
|
|
return false, "no releases found on server repository"
|
|
}
|
|
|
|
var targetRelease *models.ReleaseType
|
|
for _, rel := range releases {
|
|
if rel.TagName == version {
|
|
targetRelease = rel
|
|
break
|
|
}
|
|
}
|
|
if targetRelease == nil && len(releases) > 0 {
|
|
targetRelease = releases[0]
|
|
}
|
|
if targetRelease == nil {
|
|
return false, "could not find server release matching version " + version
|
|
}
|
|
|
|
if err := os.MkdirAll(constant.ServerStorageUrl, 0755); err != nil {
|
|
return false, err.Error()
|
|
}
|
|
|
|
// 1. Search for .zip asset
|
|
var zipAsset *models.AssetType
|
|
for _, asset := range targetRelease.Assets {
|
|
if strings.HasSuffix(strings.ToLower(asset.Name), ".zip") {
|
|
aCopy := asset
|
|
zipAsset = &aCopy
|
|
break
|
|
}
|
|
}
|
|
|
|
if zipAsset != nil {
|
|
// Case A: ZIP archive found
|
|
saveZipPath := filepath.Join(constant.ServerStorageUrl, zipAsset.Name)
|
|
tmpPath, err := g.downloadFileParallel(saveZipPath, zipAsset.BrowserDownloadURL, 4, func(percent float64, speed string) {
|
|
application.Get().Event.Emit("download:server", map[string]interface{}{
|
|
"percent": fmt.Sprintf("%.2f", percent),
|
|
"speed": speed,
|
|
})
|
|
})
|
|
if err != nil {
|
|
return false, fmt.Sprintf("download server zip: %v", err)
|
|
}
|
|
|
|
renamed := false
|
|
for i := 0; i < 3; i++ {
|
|
if err := os.Rename(tmpPath, saveZipPath); err == nil {
|
|
renamed = true
|
|
break
|
|
}
|
|
time.Sleep(300 * time.Millisecond)
|
|
}
|
|
if !renamed {
|
|
os.Remove(tmpPath)
|
|
return false, "failed to rename downloaded server zip"
|
|
}
|
|
|
|
// Unzip immediately
|
|
if err := g.unzipParallel(saveZipPath, constant.ServerStorageUrl); err != nil {
|
|
return false, fmt.Sprintf("unzip server: %v", err)
|
|
}
|
|
os.Remove(saveZipPath)
|
|
g.organizeExtractedServer(constant.ServerStorageUrl)
|
|
return true, ""
|
|
}
|
|
|
|
// Case B: No ZIP archive, download sdkserver and server executables
|
|
var sdkAsset, serverAsset *models.AssetType
|
|
for _, asset := range targetRelease.Assets {
|
|
nameLower := strings.ToLower(asset.Name)
|
|
if strings.Contains(nameLower, "sdkserver") {
|
|
aCopy := asset
|
|
sdkAsset = &aCopy
|
|
} else if strings.Contains(nameLower, "server") {
|
|
aCopy := asset
|
|
serverAsset = &aCopy
|
|
}
|
|
}
|
|
|
|
if sdkAsset == nil && serverAsset == nil {
|
|
return false, "no zip or server executable assets found in release"
|
|
}
|
|
|
|
if sdkAsset != nil {
|
|
saveSdk := filepath.Join(constant.ServerStorageUrl, sdkAsset.Name)
|
|
tmpPath, err := g.downloadFileParallel(saveSdk, sdkAsset.BrowserDownloadURL, 4, func(percent float64, speed string) {
|
|
application.Get().Event.Emit("download:server", map[string]interface{}{
|
|
"percent": fmt.Sprintf("%.2f", percent*0.5),
|
|
"speed": speed,
|
|
})
|
|
})
|
|
if err == nil {
|
|
_ = os.Rename(tmpPath, saveSdk)
|
|
}
|
|
}
|
|
|
|
if serverAsset != nil {
|
|
saveServer := filepath.Join(constant.ServerStorageUrl, serverAsset.Name)
|
|
tmpPath, err := g.downloadFileParallel(saveServer, serverAsset.BrowserDownloadURL, 4, func(percent float64, speed string) {
|
|
application.Get().Event.Emit("download:server", map[string]interface{}{
|
|
"percent": fmt.Sprintf("%.2f", 50.0+percent*0.5),
|
|
"speed": speed,
|
|
})
|
|
})
|
|
if err == nil {
|
|
_ = os.Rename(tmpPath, saveServer)
|
|
}
|
|
}
|
|
|
|
return true, ""
|
|
}
|
|
|
|
func (g *GitService) UnzipServer() {
|
|
entries, err := os.ReadDir(constant.ServerStorageUrl)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, entry := range entries {
|
|
if !entry.IsDir() && strings.HasSuffix(strings.ToLower(entry.Name()), ".zip") {
|
|
zipPath := filepath.Join(constant.ServerStorageUrl, entry.Name())
|
|
_ = g.unzipParallel(zipPath, constant.ServerStorageUrl)
|
|
_ = os.Remove(zipPath)
|
|
}
|
|
}
|
|
g.organizeExtractedServer(constant.ServerStorageUrl)
|
|
}
|
|
|
|
func (g *GitService) organizeExtractedServer(dest string) {
|
|
forShipPath := filepath.Join(dest, "for ship")
|
|
if info, err := os.Stat(forShipPath); err == nil && info.IsDir() {
|
|
logger.Info("organizeExtractedServer: found 'for ship' subdirectory in %s, synchronizing files", dest)
|
|
entries, err := os.ReadDir(forShipPath)
|
|
if err == nil {
|
|
for _, entry := range entries {
|
|
src := filepath.Join(forShipPath, entry.Name())
|
|
dst := filepath.Join(dest, entry.Name())
|
|
if !entry.IsDir() {
|
|
if _, err := os.Stat(dst); os.IsNotExist(err) {
|
|
data, readErr := os.ReadFile(src)
|
|
if readErr == nil {
|
|
_ = os.WriteFile(dst, data, 0755)
|
|
logger.Info("organizeExtractedServer: copied %s -> %s", entry.Name(), dst)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *GitService) FindServerExecutables() (string, string) {
|
|
var candidateRoots []string
|
|
|
|
if exePath, err := os.Executable(); err == nil {
|
|
exeDir := filepath.Dir(exePath)
|
|
candidateRoots = append(candidateRoots, filepath.Join(exeDir, "server"))
|
|
candidateRoots = append(candidateRoots, filepath.Join(filepath.Dir(exeDir), "server"))
|
|
}
|
|
candidateRoots = append(candidateRoots, constant.ServerStorageUrl, "./bin/server", "server", "bin/server")
|
|
|
|
var gameServer, sdkServer string
|
|
seen := make(map[string]bool)
|
|
|
|
for _, root := range candidateRoots {
|
|
absRoot, err := filepath.Abs(root)
|
|
if err != nil || seen[absRoot] {
|
|
continue
|
|
}
|
|
seen[absRoot] = true
|
|
|
|
if info, err := os.Stat(absRoot); err != nil || !info.IsDir() {
|
|
continue
|
|
}
|
|
|
|
_ = filepath.Walk(absRoot, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil || info.IsDir() {
|
|
return nil
|
|
}
|
|
nameLower := strings.ToLower(info.Name())
|
|
|
|
// Search SDK server
|
|
if sdkServer == "" {
|
|
if nameLower == "sdkserver-go.exe" || nameLower == "sdkserver.exe" || (strings.Contains(nameLower, "sdkserver") && strings.HasSuffix(nameLower, ".exe")) {
|
|
sdkServer = path
|
|
}
|
|
}
|
|
|
|
// Search Game server
|
|
if gameServer == "" {
|
|
if nameLower == "gameserver-go.exe" || nameLower == "server.exe" || nameLower == "gameserver.exe" || nameLower == "firefly-go_win.exe" || (strings.Contains(nameLower, "gameserver") && strings.HasSuffix(nameLower, ".exe")) {
|
|
gameServer = path
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if gameServer != "" && sdkServer != "" {
|
|
break
|
|
}
|
|
}
|
|
|
|
logger.Info("FindServerExecutables: found gameServer=%s, sdkServer=%s", gameServer, sdkServer)
|
|
return gameServer, sdkServer
|
|
}
|