Skip to content

Commit

Permalink
Implemented format version 2.0.0 of export target:
Browse files Browse the repository at this point in the history
- Available 'target' property values - 'development', 'exact', 'world' and 'local'
- The 'local' and 'exact' targets work the same as in the previous version
- The 'development' exports to development_resource_packs and development_behavior_packs of specified build type - 'standard', 'edu' or 'preview'
- The 'world' exports to the world in specified build path - 'standard', edu' or 'preview'
- The vesions before 2.0.0 or unspecified wrok the same as before the update.
  • Loading branch information
Nusiq committed Aug 20, 2024
1 parent 2518a28 commit b76d2ac
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 24 deletions.
15 changes: 12 additions & 3 deletions regolith/compatibility_other_os.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package regolith

import (
"os"

"github.com/Bedrock-OSS/go-burrito/burrito"
)

Expand Down Expand Up @@ -50,22 +51,30 @@ func (d *DirWatcher) Close() error {
return burrito.WrappedError(notImplementedOnThisSystemError)
}

func FindMojangDir() (string, error) {
func FindStandardMojangDir() (string, error) {
comMojang := os.Getenv("COM_MOJANG")
if comMojang == "" {
return "", burrito.WrappedError(comMojangEnvUnsetError)
return "", burrito.WrappedError(comMojangEnvUnsetError)
}
return comMojang, nil
}

func FindPreviewDir() (string, error) {
comMojangPreview := os.Getenv("COM_MOJANG_PREVIEW")
if comMojangPreview == "" {
return "", burrito.WrappedError(comMojangPreviewEnvUnsetError)
return "", burrito.WrappedError(comMojangPreviewEnvUnsetError)
}
return comMojangPreview, nil
}

func FindEduDir() (string, error) {
comMojangEdu := os.Getenv("COM_MOJANG_EDU")
if comMojangEdu == "" {
return "", burrito.WrappedError(comMojangEduEnvUnsetError)
}
return comMojangEdu, nil
}

func CheckSuspiciousLocation() error {
return nil
}
25 changes: 22 additions & 3 deletions regolith/compatibility_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,9 @@ func (d *DirWatcher) Close() error {
return windows.CloseHandle(d.handle)
}

// FindMojangDir returns path to the com.mojang folder.
func FindMojangDir() (string, error) {
// FindStandardMojangDir returns path to the com.mojang folder in the standard
// Minecraft build.
func FindStandardMojangDir() (string, error) {
result := filepath.Join(
os.Getenv("LOCALAPPDATA"), "Packages",
"Microsoft.MinecraftUWP_8wekyb3d8bbwe", "LocalState", "games",
Expand All @@ -161,6 +162,8 @@ func FindMojangDir() (string, error) {
return result, nil
}

// FindPreviewDir returns path to the com.mojang folder in the preview
// Minecraft build.
func FindPreviewDir() (string, error) {
result := filepath.Join(
os.Getenv("LOCALAPPDATA"), "Packages",
Expand All @@ -176,13 +179,29 @@ func FindPreviewDir() (string, error) {
return result, nil
}

// FindEduDir returns path to the com.mojang folder in the education
// edition Minecraft build.
func FindEduDir() (string, error) {
result := filepath.Join(
os.Getenv("APPDATA"), "Minecraft Education Edition", "games",
"com.mojang")
if _, err := os.Stat(result); err != nil {
if os.IsNotExist(err) {
return "", burrito.WrapErrorf(err, osStatErrorIsNotExist, result)
}
return "", burrito.WrapErrorf(
err, osStatErrorAny, result)
}
return result, nil
}

func CheckSuspiciousLocation() error {
path, err := os.Getwd()
if err != nil {
return burrito.WrapErrorf(err, osGetwdError)
}
// Check if project directory is within mojang dir
dir, err := FindMojangDir()
dir, err := FindStandardMojangDir()
if err == nil {
dir1 := filepath.Join(dir, "development_behavior_packs")
if isPathWithinDirectory(path, dir1) {
Expand Down
8 changes: 6 additions & 2 deletions regolith/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ type ExportTarget struct {
BpName string `json:"bpName,omitempty"`
WorldName string `json:"worldName,omitempty"`
WorldPath string `json:"worldPath,omitempty"`
ReadOnly bool `json:"readOnly"` // Whether the exported files should be read-only
ReadOnly bool `json:"readOnly"` // Whether the exported files should be read-only
Build string `json:"build,omitempty"` // The type of Minecraft build for the 'develop'
}

// Packs is a part of "config.json" that points to the source behavior and
Expand Down Expand Up @@ -115,7 +116,7 @@ func RegolithProjectFromObject(
}
// FormatVersion
if version, ok := obj["formatVersion"]; !ok {
Logger.Warnf("Format version is missing. Defaulting to 1.0.0")
Logger.Warn("Format version is missing. Defaulting to 1.0.0")
result.FormatVersion = "1.0.0"
} else {
formatVersion, ok := version.(string)
Expand Down Expand Up @@ -229,5 +230,8 @@ func ExportTargetFromObject(obj map[string]interface{}) (ExportTarget, error) {
// ReadOnly - can be empty
readOnly, _ := obj["readOnly"].(bool)
result.ReadOnly = readOnly
// Build - can be empty
build, _ := obj["build"].(string)
result.Build = build
return result, nil
}
16 changes: 16 additions & 0 deletions regolith/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ const (
// Error used when env variable COM_MOJANG_PREVIEW is not set on non Windows system
comMojangPreviewEnvUnsetError = "COM_MOJANG_PREVIEW environment variable is not set."

// Error used when env variable COM_MOJANG_EDU is not set on non Windows system
comMojangEduEnvUnsetError = "COM_MOJANG_EDU environment variable is not set."

// Error used when SetupTmpFiles function fails
setupTmpFilesError = "Failed to setup temporary files.\n" +
"Regolith files path: %s" // .regolith
Expand Down Expand Up @@ -222,4 +225,17 @@ const (

resolverResolveUrlError = "Failed to resolve the URL of the resolver file for the download.\n" +
"Short URL: %s"

// findMojangDirError is used when the FindMojangDir function fails
findMojangDirError = "Failed to find \"com.mojang\" directory."

// findPreviewDirError is used when the FindPreviewDir function fails
findPreviewDirError = "Failed to find the preview \"com.mojang\" directory."

// findEduDirError is used when the FindEduDir function fails
findEduDirError = "Failed to find the \"com.mojang\" directory."

invalidExportPathError = "The build property of the export is invalid:\n" +
"Current value: %q\n" +
"Valid values are: %s"
)
101 changes: 86 additions & 15 deletions regolith/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/Bedrock-OSS/go-burrito/burrito"
"golang.org/x/mod/semver"
)

// GetExportPaths returns file paths for exporting behavior pack and
Expand All @@ -15,24 +16,65 @@ func GetExportPaths(
exportTarget ExportTarget, ctx RunContext,
) (bpPath string, rpPath string, err error) {
bpName, rpName, err := GetExportNames(exportTarget, ctx)
if err != nil {
return "", "", burrito.WrapError(
err, "Failed to get the export names.")
}
if semver.Compare(ctx.Config.FormatVersion, "v2.0.0") < 0 {
bpPath, rpPath, err = getExportPathsV1_0_0(
exportTarget, bpName, rpName)
} else {
bpPath, rpPath, err = getExportPathsV2_0_0(
exportTarget, bpName, rpName)
}
return
}

func FindMojangDir(build string) (string, error) {
if build == "standard" {
return FindStandardMojangDir()
} else if build == "preview" {
return FindPreviewDir()
} else if build == "edu" {
return FindEduDir()
// WARNING: If for some reason we will expand this in the future to
// match a new format version, we need to split this into versioned
// functions.
} else {
return "", burrito.WrappedErrorf(
invalidExportPathError,
// current value; valid values
build, "standard, preview, edu")
}
}

// getExportPathsV1_0_0 handles GetExportPaths for Regolith format versions
// below 2.0.0.
func getExportPathsV1_0_0(
exportTarget ExportTarget, bpName string, rpName string,
) (bpPath string, rpPath string, err error) {
if exportTarget.Target == "development" {
comMojang, err := FindMojangDir()
comMojang, err := FindStandardMojangDir()
if err != nil {
return "", "", burrito.WrapError(
err, "Failed to find \"com.mojang\" directory.")
err, findMojangDirError)
}
return GetDevelopmentExportPaths(bpName, rpName, comMojang)
} else if exportTarget.Target == "preview" {
comMojang, err := FindPreviewDir()
if err != nil {
return "", "", burrito.WrapError(
err, "Failed to find preview \"com.mojang\" directory.")
err, findPreviewDirError)
}
return GetDevelopmentExportPaths(bpName, rpName, comMojang)
} else if exportTarget.Target == "exact" {
return GetExactExportPaths(exportTarget)
} else if exportTarget.Target == "world" {
return GetWorldExportPaths(exportTarget, bpName, rpName)
return GetWorldExportPaths(
exportTarget.WorldPath,
exportTarget.WorldName,
"standard",
bpName, rpName)
} else if exportTarget.Target == "local" {
bpPath = "build/" + bpName + "/"
rpPath = "build/" + rpName + "/"
Expand All @@ -46,12 +88,39 @@ func GetExportPaths(
return
}

func GetDevelopmentExportPaths(bpName, rpName, comMojang string) (bpPath string, rpPath string, err error) {
if err != nil {
return "", "", burrito.WrapError(
err, "Failed to find \"com.mojang\" directory.")
// getExportPathsV2_0_0 handles GetExportPaths for Regolith format version
// 2.0.0.
func getExportPathsV2_0_0(
exportTarget ExportTarget, bpName string, rpName string,
) (bpPath string, rpPath string, err error) {
if exportTarget.Target == "development" {
comMojang, err := FindMojangDir(exportTarget.Build)
if err != nil {
return "", "", burrito.PassError(err)
}
return GetDevelopmentExportPaths(bpName, rpName, comMojang)
} else if exportTarget.Target == "world" {
return GetWorldExportPaths(
exportTarget.WorldPath,
exportTarget.WorldName,
exportTarget.Build,
bpName, rpName)
} else if exportTarget.Target == "exact" {
return GetExactExportPaths(exportTarget)
} else if exportTarget.Target == "local" {
bpPath = "build/" + bpName + "/"
rpPath = "build/" + rpName + "/"
} else if exportTarget.Target == "none" {
bpPath = ""
rpPath = ""
} else {
err = burrito.WrappedErrorf(
"Export target %q is not valid", exportTarget.Target)
}
return
}

func GetDevelopmentExportPaths(bpName, rpName, comMojang string) (bpPath string, rpPath string, err error) {
bpPath = comMojang + "/development_behavior_packs/" + bpName
rpPath = comMojang + "/development_resource_packs/" + rpName
return
Expand All @@ -71,14 +140,16 @@ func GetExactExportPaths(exportTarget ExportTarget) (bpPath string, rpPath strin
return
}

func GetWorldExportPaths(exportTarget ExportTarget, bpName, rpName string) (bpPath string, rpPath string, err error) {
if exportTarget.WorldPath != "" {
if exportTarget.WorldName != "" {
func GetWorldExportPaths(
worldPath, worldName, build, bpName, rpName string,
) (bpPath string, rpPath string, err error) {
if worldPath != "" {
if worldName != "" {
return "", "", burrito.WrappedError(
"Using both \"worldName\" and \"worldPath\" is not" +
" allowed.")
}
wPath, err := ResolvePath(exportTarget.WorldPath)
wPath, err := ResolvePath(worldPath)
if err != nil {
return "", "", burrito.WrapError(
err, "Failed to resolve world path.")
Expand All @@ -87,8 +158,8 @@ func GetWorldExportPaths(exportTarget ExportTarget, bpName, rpName string) (bpPa
wPath, "behavior_packs", bpName)
rpPath = filepath.Join(
wPath, "resource_packs", rpName)
} else if exportTarget.WorldName != "" {
dir, err := FindMojangDir()
} else if worldName != "" {
dir, err := FindMojangDir(build)
if err != nil {
return "", "", burrito.WrapError(
err, "Failed to find \"com.mojang\" directory.")
Expand All @@ -98,7 +169,7 @@ func GetWorldExportPaths(exportTarget ExportTarget, bpName, rpName string) (bpPa
return "", "", burrito.WrapError(err, "Failed to list worlds.")
}
for _, world := range worlds {
if world.Name == exportTarget.WorldName {
if world.Name == worldName {
bpPath = filepath.Join(
world.Path, "behavior_packs", bpName)
rpPath = filepath.Join(
Expand Down
4 changes: 3 additions & 1 deletion test/export_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ func TestMoveFilesAcl(t *testing.T) {
if os.Getenv("CI") != "" {
t.Skip("Skipping test on local machine")
}
regolith.InitLogging(true)

// Switch to current working directory at the end of the test
defer os.Chdir(getWdOrFatal(t))

Expand All @@ -33,7 +35,7 @@ func TestMoveFilesAcl(t *testing.T) {

// Find path to com.mojang
t.Log("Finding the path to com.mojang...")
mojangDir, err := regolith.FindMojangDir()
mojangDir, err := regolith.FindStandardMojangDir()
if err != nil {
t.Fatal(err.Error())
}
Expand Down

0 comments on commit b76d2ac

Please sign in to comment.