Skip to content

Commit

Permalink
server provider factory
Browse files Browse the repository at this point in the history
  • Loading branch information
nothub committed Sep 7, 2022
1 parent 621bb68 commit 687489d
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 103 deletions.
71 changes: 42 additions & 29 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func init() {
rootCmd.Flags().String("server-dir", "mc", "Server directory path")
rootCmd.Flags().String("server-file", "", "Server jar file name")
rootCmd.Flags().String("proxy", "", "Use a proxy to download")
rootCmd.Flags().Int("download-thread", 8, "Download threads")
rootCmd.Flags().Int("download-threads", 8, "Download threads")
rootCmd.Flags().Int("retry-times", 3, "Number of retries when a download fails")
}

Expand Down Expand Up @@ -52,7 +52,7 @@ var rootCmd = &cobra.Command{
log.Fatalln(err)
}
}
downloadThreads, err := cmd.Flags().GetInt("download-thread")
downloadThreads, err := cmd.Flags().GetInt("download-threads")
if err != nil || downloadThreads > 64 {
downloadThreads = 8
log.Println(err)
Expand All @@ -75,7 +75,7 @@ var rootCmd = &cobra.Command{
}

archivePath := ""
if util.FileExists(input) {
if util.PathIsFile(input) {
archivePath = input

} else if util.IsValidUrl(input) {
Expand Down Expand Up @@ -141,59 +141,72 @@ var rootCmd = &cobra.Command{
log.Printf("Flavor dependencies: %+v\n", index.Dependencies)

// download server if not present
if serverFile != "" && !util.FileExists(path.Join(serverDir, serverFile)) {
// Determine server platform
var provider server.Provider = nil
if !util.PathIsFile(path.Join(serverDir, serverFile)) {
log.Println("Server file not present, downloading...")
log.Println("(Point --server-dir and --server-file flags for an existing server file to skip this step.)")

var provider server.Provider
if index.Dependencies.Fabric != "" {
provider = &server.Fabric{
MinecraftVersion: index.Dependencies.Minecraft,
FabricVersion: index.Dependencies.Fabric,
provider, err = server.NewProvider("fabric", index.Dependencies.Minecraft, index.Dependencies.Fabric)
if err != nil {
log.Fatalln(err)
}
} else if index.Dependencies.Quilt != "" {
provider, err = server.NewProvider("quilt", index.Dependencies.Minecraft, index.Dependencies.Quilt)
if err != nil {
log.Fatalln(err)
}
} else if index.Dependencies.Forge != "" {
provider, err = server.NewProvider("forge", index.Dependencies.Minecraft, index.Dependencies.Forge)
if err != nil {
log.Fatalln(err)
}
} else if index.Dependencies.Quilt != "" || index.Dependencies.Forge != "" {
log.Fatalln("Automatic server deployment not yet implemented for this flavor! Supply the path to an existing server jar file with the --server-dir and --server-file flags.")
} else {
// TODO: vanilla server download
provider, err = server.NewProvider("vanilla", index.Dependencies.Minecraft, "")
if err != nil {
log.Fatalln(err)
}
}

// Download server
err := provider.Provide(serverDir, serverFile)
err = provider.Provide(serverDir, serverFile)
if err != nil {
log.Fatalln(err)
}
} else {
log.Println("Server jar file already present, skipping download...")
log.Println("Server file already present, proceeding...")
}

// download mods
// mod downloads
log.Printf("Downloading %v dependencies...\n", len(index.Files))
var downloadPoolArray []*requester.DownloadPool
var downloadPoolArray []*requester.Download
for i := range index.Files {
file := index.Files[i]
if file.Env.Server == modrinth.UnsupportedEnvSupport {
continue
}
downloadPoolArray = append(downloadPoolArray, requester.NewDownloadPool(file.Downloads, map[string]string{"sha1": string(file.Hashes.Sha1)}, filepath.Base(file.Path), path.Join(serverDir, filepath.Dir(file.Path))))
}

downloadPools := requester.NewDownloadPools(requester.DefaultHttpClient, downloadPoolArray, downloadThreads, retryTimes)
downloadPools.Do()
log.Println("Extracting overrides...")
err = mrpack.ExtractOverrides(archivePath, serverDir)
if err != nil {
log.Fatalln(err)
}
uncleanNotification := false
for i := range downloadPools.DownloadPool {
dl := downloadPools.DownloadPool[i]
modsUnclean := false
for i := range downloadPools.Downloads {
dl := downloadPools.Downloads[i]
if !dl.Success {
uncleanNotification = true
modsUnclean = true
log.Println("Dependency downloaded Fail:", dl.FileName)
}
}
if uncleanNotification {
log.Fatalln("Download failed,You can fix the error manually")

// overrides
log.Println("Extracting overrides...")
err = mrpack.ExtractOverrides(archivePath, serverDir)
if err != nil {
log.Fatalln(err)
}

if modsUnclean {
log.Println("There have been problems downloading downloading mods, you probably have to fix some dependency problems manually!")
}
log.Println("Done :) Have a nice day ✌️")
},
}
Expand Down
36 changes: 4 additions & 32 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,39 +52,11 @@ var serverCmd = &cobra.Command{
minecraftVersion = latestMinecraftVersion
}

var provider server.Provider = nil
switch args[0] {
case "vanilla":
provider = &server.Vanilla{
MinecraftVersion: minecraftVersion,
}
case "fabric":
provider = &server.Fabric{
MinecraftVersion: minecraftVersion,
FabricVersion: flavorVersion,
}
case "quilt":
provider = &server.Quilt{
MinecraftVersion: minecraftVersion,
QuiltVersion: flavorVersion,
}
case "forge":
provider = &server.Forge{
MinecraftVersion: minecraftVersion,
ForgeVersion: flavorVersion,
}
case "paper":
provider = &server.Paper{
MinecraftVersion: minecraftVersion,
PaperVersion: flavorVersion,
}
case "spigot":
provider = &server.Spigot{
MinecraftVersion: minecraftVersion,
SpigotVersion: flavorVersion,
}
flavor := args[0]
provider, err := server.NewProvider(flavor, minecraftVersion, flavorVersion)
if err != nil {
log.Fatalln(err)
}

err = provider.Provide(serverDir, serverFile)
if err != nil {
log.Fatalln(err)
Expand Down
54 changes: 27 additions & 27 deletions requester/multiDownload.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,65 @@ import (
"sync"
)

type DownloadPool struct {
downloadLink []string
hash map[string]string
FileName string
downloadDir string
Success bool
type Download struct {
links []string
hash map[string]string
FileName string
downloadDir string
Success bool
}

type DownloadPools struct {
httpClient *HTTPClient
DownloadPool []*DownloadPool
downloadThreads int
retryTimes int
httpClient *HTTPClient
Downloads []*Download
threads int
retryTimes int
}

func NewDownloadPools(httpClient *HTTPClient, downloadPool []*DownloadPool, downloadThreads int, retryTimes int) *DownloadPools {
func NewDownloadPools(httpClient *HTTPClient, downloadPool []*Download, downloadThreads int, retryTimes int) *DownloadPools {
return &DownloadPools{httpClient, downloadPool, downloadThreads, retryTimes}
}

func NewDownloadPool(downloadLink []string, hash map[string]string, fileName string, downloadDir string) *DownloadPool {
return &DownloadPool{downloadLink, hash, fileName, downloadDir, false}
func NewDownloadPool(downloadLink []string, hash map[string]string, fileName string, downloadDir string) *Download {
return &Download{downloadLink, hash, fileName, downloadDir, false}
}

func (downloadPools *DownloadPools) Do() {
var wg sync.WaitGroup
ch := make(chan struct{}, downloadPools.downloadThreads)
for i := range downloadPools.DownloadPool {
file := downloadPools.DownloadPool[i]
ch := make(chan struct{}, downloadPools.threads)
for i := range downloadPools.Downloads {
dl := downloadPools.Downloads[i]

//goroutine
ch <- struct{}{}
wg.Add(1)
go func() {
defer wg.Done()
for _, downloadLink := range file.downloadLink {
// when download failed retry
for retryTime := 0; retryTime < downloadPools.retryTimes; retryTime++ {
for _, link := range dl.links {
// retry when download failed
for retries := 0; retries < downloadPools.retryTimes; retries++ {

//download file
f, err := downloadPools.httpClient.DownloadFile(downloadLink, file.downloadDir, file.FileName)
// download file
f, err := downloadPools.httpClient.DownloadFile(link, dl.downloadDir, dl.FileName)
if err != nil {
log.Println("Download failed for:", file.FileName, err, "retry times:", retryTime)
log.Println("Download failed for:", dl.FileName, err, "attempt:", retries+1)
continue
}

//check hashcode
if sha1code, ok := file.hash["sha1"]; ok {
// check hashcode
if sha1code, ok := dl.hash["sha1"]; ok {
_, err = util.CheckFileSha1(sha1code, f)
}
if err != nil {
log.Println("Hash check failed for:", file.FileName, err, "retry times:", retryTime)
log.Println("Hash check failed for:", dl.FileName, err, "attempt:", retries+1)
continue
}

log.Println("Downloaded:", f)
file.Success = true
dl.Success = true
break
}
if file.Success {
if dl.Success {
break
}
}
Expand Down
4 changes: 3 additions & 1 deletion server/forge.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package server

import "errors"
import (
"errors"
)

type Forge struct {
MinecraftVersion string
Expand Down
5 changes: 0 additions & 5 deletions server/interface.go

This file was deleted.

13 changes: 9 additions & 4 deletions server/paper.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@ func (supplier *Paper) Provide(serverDir string, serverFile string) error {
} `json:"downloads"`
} `json:"builds"`
}
err := requester.DefaultHttpClient.GetJson("https://api.papermc.io/v2/projects/paper/versions/"+supplier.MinecraftVersion+"/builds", &response, nil)

err := requester.DefaultHttpClient.GetJson("https://api.papermc.io/v2/projects/paper/versions/"+
supplier.MinecraftVersion+"/builds", &response, nil)
if err != nil {
return err
}

for i := range response.Builds {
i = len(response.Builds) - 1 - i
b := response.Builds[i]
if b.Channel == "default" {
u := "https://api.papermc.io/v2/projects/paper/versions/" + supplier.MinecraftVersion + "/builds/" + strconv.Itoa(b.Id) + "/downloads/" + b.Downloads.Application.Name
if response.Builds[i].Channel == "default" {
u := "https://api.papermc.io/v2/projects/paper/versions/" + supplier.MinecraftVersion +
"/builds/" + strconv.Itoa(response.Builds[i].Id) +
"/downloads/" + response.Builds[i].Downloads.Application.Name
file, err := requester.DefaultHttpClient.DownloadFile(u, serverDir, serverFile)
if err != nil {
return err
Expand All @@ -43,5 +47,6 @@ func (supplier *Paper) Provide(serverDir string, serverFile string) error {
return nil
}
}

return errors.New("no stable paper release found")
}
52 changes: 52 additions & 0 deletions server/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package server

import (
"errors"
"strings"
)

type Provider interface {
Provide(serverDir string, serverFile string) error
}

func NewProvider(flavor string, minecraftVersion string, flavorVersion string) (Provider, error) {
var provider Provider = nil

switch strings.ToLower(flavor) {
case "vanilla":
provider = &Vanilla{
MinecraftVersion: minecraftVersion,
}
case "fabric":
provider = &Fabric{
MinecraftVersion: minecraftVersion,
FabricVersion: flavorVersion,
}
case "quilt":
provider = &Quilt{
MinecraftVersion: minecraftVersion,
QuiltVersion: flavorVersion,
}
case "forge":
provider = &Forge{
MinecraftVersion: minecraftVersion,
ForgeVersion: flavorVersion,
}
case "paper":
provider = &Paper{
MinecraftVersion: minecraftVersion,
PaperVersion: flavorVersion,
}
case "spigot":
provider = &Spigot{
MinecraftVersion: minecraftVersion,
SpigotVersion: flavorVersion,
}
}

if provider == nil {
return nil, errors.New("no provider for this flavor")
}

return provider, nil
}
4 changes: 3 additions & 1 deletion server/quilt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type Quilt struct {
}

func (supplier *Quilt) Provide(serverDir string, serverFile string) error {
return errors.New("quilt provider not yet implemented")

err := os.MkdirAll("work/quilt", 0755)
if err != nil {
log.Fatalln(err)
Expand All @@ -20,5 +22,5 @@ func (supplier *Quilt) Provide(serverDir string, serverFile string) error {
// TODO: download https://maven.quiltmc.org/repository/release/org/quiltmc/quilt-installer/latest/quilt-installer-latest.jar
// TODO: java -jar quilt-installer-latest.jar install server ${minecraftVersion} --download-server

return errors.New("quilt provider not yet implemented")
return nil
}
4 changes: 3 additions & 1 deletion server/spigot.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type Spigot struct {
}

func (supplier *Spigot) Provide(serverDir string, serverFile string) error {
return errors.New("spigot provider not yet implemented")

err := os.MkdirAll("work/spigot", 0755)
if err != nil {
log.Fatalln(err)
Expand All @@ -21,5 +23,5 @@ func (supplier *Spigot) Provide(serverDir string, serverFile string) error {
// TODO: git config --global --unset core.autocrlf
// TODO: java -jar BuildTools.jar --rev ${minecraftVersion}

return errors.New("spigot provider not yet implemented")
return nil
}
Loading

0 comments on commit 687489d

Please sign in to comment.