From 431a417948f3cf47a230aa07323d64370a712449 Mon Sep 17 00:00:00 2001 From: Merith Date: Tue, 6 May 2025 11:29:20 -0700 Subject: [PATCH] current work --- config.json | 9 ++++ conversion.go | 117 +++++++++++++++++++++++++++++++++++++++++++++++ definitions.json | 12 +++++ go.mod | 10 ++++ go.sum | 8 ++++ main.go | 82 +++++++++++++++++++++++++++++++++ output.xml | 84 ++++++++++++++++++++++++++++++++++ se-blueprint.go | 85 ++++++++++++++++++++++++++++++++++ test.litematic | Bin 0 -> 493 bytes test.sbc | 84 ++++++++++++++++++++++++++++++++++ todo | 3 ++ 11 files changed, 494 insertions(+) create mode 100644 config.json create mode 100644 conversion.go create mode 100644 definitions.json create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 output.xml create mode 100644 se-blueprint.go create mode 100644 test.litematic create mode 100644 test.sbc create mode 100644 todo 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 0000000000000000000000000000000000000000..4ee4d35e0ccc80c8cf97bdaaba400b396709296c GIT binary patch literal 493 zcmV5^TWv9Ss^kw!JLuuJ z18k^3&t&l!yc&XeEwL2RrK26XAS;)6zeAXKZ7YKb%%4Qs8LBEQATE{h0!~VmOB`ZP z4cBm_z8n0GDH0PJ;w*s+UA*4I2;v)REJvsM zZ4rZh$T3|t>j!jR3JAY9w;deL|3R*E}@vKjmVKHjPw>H`1(B1h)V literal 0 HcmV?d00001 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