commit 431a417948f3cf47a230aa07323d64370a712449 Author: Merith Date: Tue May 6 11:29:20 2025 -0700 current work diff --git a/config.json b/config.json new file mode 100644 index 0000000..1f04c2d --- /dev/null +++ b/config.json @@ -0,0 +1,9 @@ +[ + // rotation, 0 = north, 1 = east, 2 = south, 3 = west + { + "id": "minecraft:chest", + "rotation": 0, + "color": "red", // HEX or minecraft color name + "texture" : "" // block skin, leave empty for default + } +] \ No newline at end of file diff --git a/conversion.go b/conversion.go new file mode 100644 index 0000000..0681915 --- /dev/null +++ b/conversion.go @@ -0,0 +1,117 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "os" + + "github.com/elvis972602/go-litematica-tools/schematic" + "github.com/lucasb-eyer/go-colorful" +) + +var validColorsHex = map[string]string{ + // known minecraft colors + "pink": "#f38baf", + "magenta": "#c74ebd", + "purple": "#8932b8", + "blue": "#3c44aa", + "light_blue": "#3ab3da", + "cyan": "#169c9c", + "green": "#5e7c16", + "lime": "#80c71f", + "yellow": "#f7e9a3", + "orange": "#f9801d", + "red": "#b02e26", + "brown": "#835432", + "black:": "#1d1d21", + "gray": "#474f52", + "light_gray": "#9d9d97", + "white": "#f9fffe", +} + +var validBlockTypes = map[string]string{ + "minecraft:wool": "LargeBlockArmorBlock", + "minecraft:concrete": "LargeHeavyBlockArmorBlock", +} + +// var string: value [int, int, int] +var validColorsHsv = map[string][]float64{ + // convert color name to HSV colors as three floats + +} + +func convertColors() { + // convert hex colors to HSV colors that + // are compatible with Space Engineers + for _, colorHex := range validColorsHex { + c, err := colorful.Hex(colorHex) + if err != nil { + continue + } + h, s, v := c.Hsv() + h = h / 360 + s = s - 0.8 + v = v - 0.45 + validColorsHsv[colorHex] = []float64{h, s, v} + } +} + +// convertBlock converts a block state into a color and a block type +// returns the color and the block type +func convertBlock(block schematic.BlockState) ([]float64, string) { + // first check if the block is a known block + for _, blockDef := range blockDefinitions { + if blockDef.Block == block.Name { + return validColorsHsv[blockDef.Color], blockDef.BlockType + } + } + // if the block is not known, return a default block + return validColorsHsv["#f9fffe"], "LargeBlockArmorBlock" +} + +var blockDefinitions []blockDefinition + +type blockDefinition struct { + Block string `json:"block"` + Color string `json:"color"` + BlockType string `json:"blockType"` +} + +func loadDefaultDefinitions() { + for i := 0; i < 2; i++ { + var mcType string + if i == 0 { + mcType = "minecraft:wool" + } else { + mcType = "minecraft:concrete" + } + for color, colorHex := range validColorsHex { + var blockDef []blockDefinition + blockDef = append(blockDef, struct { + Block string `json:"block"` + Color string `json:"color"` + BlockType string `json:"blockType"` + }{Block: mcType + "_" + color, Color: colorHex, BlockType: validBlockTypes[mcType]}) + blockDefinitions = append(blockDefinitions, blockDef...) + } + } +} + +func loadDefinitions() { + loadDefaultDefinitions() + if _, err := os.Stat("definitions.json"); os.IsNotExist(err) { + // generate default definitions for stone and oak_planks + exampleDefinitions := []blockDefinition{ + {Block: "minecraft:stone", Color: "#bfbfbf", BlockType: "LargeHeavyBlockArmorBlock"}, + {Block: "minecraft:oak_planks", Color: "#835432", BlockType: "LargeHeavyBlockArmorBlock"}, + } + jsonData, err := json.MarshalIndent(exampleDefinitions, "", " ") + if err != nil { + panic(err) + } + err = ioutil.WriteFile("definitions.json", jsonData, 0644) + if err != nil { + panic(err) + } + } +} diff --git a/definitions.json b/definitions.json new file mode 100644 index 0000000..9d2b078 --- /dev/null +++ b/definitions.json @@ -0,0 +1,12 @@ +[ + { + "block": "minecraft:stone", + "color": "#bfbfbf", + "blockType": "LargeHeavyBlockArmorBlock" + }, + { + "block": "minecraft:oak_planks", + "color": "#835432", + "blockType": "LargeHeavyBlockArmorBlock" + } +] \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..adf9d61 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module MC2SE + +go 1.20 + +require ( + github.com/Tnze/go-mc v1.19.3 // indirect + github.com/elvis972602/go-litematica-tools v0.0.0-20221205202416-31991f70bf3d // indirect + github.com/go-playground/colors v1.3.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..5afd757 --- /dev/null +++ b/go.sum @@ -0,0 +1,8 @@ +github.com/Tnze/go-mc v1.19.3 h1:vRRJSlqsN65+4Wgy/Sx9+Z1W3+S5BaQ1ZPcCp0TaXgs= +github.com/Tnze/go-mc v1.19.3/go.mod h1:uNMPHRugYj2nXIHbmm8XTQJ1NpQAC2p214es9BIC5Rc= +github.com/elvis972602/go-litematica-tools v0.0.0-20221205202416-31991f70bf3d h1:fl9IwOc2D0JYGuB/H5P48+rz9j9AMjnu0AQso31SEao= +github.com/elvis972602/go-litematica-tools v0.0.0-20221205202416-31991f70bf3d/go.mod h1:wUNmXYvCOkPnr6zxdXTHUXKNAG4XwpcSbF4JLvowtR4= +github.com/go-playground/colors v1.3.0 h1:B+jYkyTo36sREzsaXd3kawgG53rw0zqX9fSllGVoLdc= +github.com/go-playground/colors v1.3.0/go.mod h1:5rTAoESUkprj1EHZvzGti8xkb8XwAGYzYEFmW18B8es= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= diff --git a/main.go b/main.go new file mode 100644 index 0000000..431ab38 --- /dev/null +++ b/main.go @@ -0,0 +1,82 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + + "github.com/elvis972602/go-litematica-tools/schematic" +) + +func main() { + + // add flag for scale multiplier + // add flag for output file name + // add flag for input file name + + // flagScale := flag.Float64("scale", 1.0, "scale multiplier") + flagInput := flag.String("input", "test.litematic", "input file name") + flagOutput := flag.String("output", "output.xml", "output file name") + flag.Parse() + + file, err := os.Open(*flagInput) + if err != nil { + panic(err) + } + defer file.Close() + project, err := schematic.LoadFromFile(file) + if err != nil { + panic(err) + } else { + fmt.Println("Schematic loaded") + } + + // log.Println("Project metadata:", project.MetaData) + // log.Println("Project version:", project.Version) + // log.Println("Project minecraft data version:", project.MinecraftDataVersion) + // log.Println("Project region name:", project.RegionName) + + // Get the region size from the project.MetaData.EnclosingSize (vec3d) + xSize := project.MetaData.EnclosingSize.X + ySize := project.MetaData.EnclosingSize.Y + zSize := project.MetaData.EnclosingSize.Z + log.Println("Project region size:", xSize, ySize, zSize) + + loadDefinitions() + convertColors() + + var blocklist string + for x := 0; x < int(xSize); x++ { + for y := 0; y < int(ySize); y++ { + for z := 0; z < int(zSize); z++ { + blockState := project.GetBlock(x, y, z) + if blockState.Name == "minecraft:air" { + continue + } + log.Println("Converting block:", blockState.Name) + color, blockType := convertBlock(blockState) + log.Println("> ", blockType, color) + log.Println("> ", x, y, z) + log.Println("") + blocklist += writeBlock(blockType, color, []int{x, y, z}, blockState.Name) + } + } + } + + // write the blueprint + xmlOutput := xmlHeader + blocklist + xmlFooter + + // write the blueprint to file + f, err := os.Create(*flagOutput) + if err != nil { + panic(err) + } + defer f.Close() + + _, err = f.WriteString(xmlOutput) + if err != nil { + panic(err) + } + +} diff --git a/output.xml b/output.xml new file mode 100644 index 0000000..6d658aa --- /dev/null +++ b/output.xml @@ -0,0 +1,84 @@ + + + + + + minecraft:oak_stairs + + + + 0 + CastShadows InScene + + + + + + 0 + 0 + 0 + 0 + + + + Large + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + + + minecraft:oak_stairs + true + false + 0 + + + + None + 0 + 0 + 0 + + + diff --git a/se-blueprint.go b/se-blueprint.go new file mode 100644 index 0000000..2fc7852 --- /dev/null +++ b/se-blueprint.go @@ -0,0 +1,85 @@ +package main + +import ( + "strconv" + "strings" +) + +var xmlHeader = ` + + + + + {NAME} + + + + 0 + CastShadows InScene + + + + + + 0 + 0 + 0 + 0 + + + + Large + +` +var xmlFooter = ` + + + + {NAME} + true + false + 0 + + + + None + 0 + 0 + 0 + + + +` + +// LargeBlockArmorBlock +// LargeHeavyBlockArmorBlock +var blockTemplate = ` + + {BLOCKTYPE} + + {SKIN} + + 0 + +` + +// blocktype, HSV color as three floats +func writeBlock(blockType string, color []float64, pos []int, bpName string) string { + newBlock := blockTemplate + newBlock = strings.Replace(newBlock, "{BLOCKTYPE}", blockType, 1) + newBlock = strings.Replace(newBlock, "{COLOR1}", strconv.FormatFloat(color[0], 'f', 6, 64), 1) + newBlock = strings.Replace(newBlock, "{COLOR2}", strconv.FormatFloat(color[1], 'f', 6, 64), 1) + newBlock = strings.Replace(newBlock, "{COLOR3}", strconv.FormatFloat(color[2], 'f', 6, 64), 1) + newBlock = strings.Replace(newBlock, "{POSX}", strconv.Itoa(pos[0]), 1) + newBlock = strings.Replace(newBlock, "{POSY}", strconv.Itoa(pos[1]), 1) + newBlock = strings.Replace(newBlock, "{POSZ}", strconv.Itoa(pos[2]), 1) + + // TODO: do not hardcode {SKIN} + newBlock = strings.Replace(newBlock, "{SKIN}", "Concrete_Armor", 1) + + xmlFooter = strings.Replace(xmlFooter, "{NAME}", bpName, -1) + xmlHeader = strings.Replace(xmlHeader, "{NAME}", bpName, -1) + + return newBlock +} diff --git a/test.litematic b/test.litematic new file mode 100644 index 0000000..4ee4d35 Binary files /dev/null and b/test.litematic differ diff --git a/test.sbc b/test.sbc new file mode 100644 index 0000000..6d658aa --- /dev/null +++ b/test.sbc @@ -0,0 +1,84 @@ + + + + + + minecraft:oak_stairs + + + + 0 + CastShadows InScene + + + + + + 0 + 0 + 0 + 0 + + + + Large + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + LargeBlockArmorBlock + + Concrete_Armor + + 0 + + + + + + minecraft:oak_stairs + true + false + 0 + + + + None + 0 + 0 + 0 + + + diff --git a/todo b/todo new file mode 100644 index 0000000..b9d8e33 --- /dev/null +++ b/todo @@ -0,0 +1,3 @@ +allow assigning texture + +read from config file for block ID conversions