current work

This commit is contained in:
Merith 2025-05-06 11:29:20 -07:00
commit 431a417948
11 changed files with 494 additions and 0 deletions

9
config.json Normal file
View file

@ -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
}
]

117
conversion.go Normal file
View file

@ -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)
}
}
}

12
definitions.json Normal file
View file

@ -0,0 +1,12 @@
[
{
"block": "minecraft:stone",
"color": "#bfbfbf",
"blockType": "LargeHeavyBlockArmorBlock"
},
{
"block": "minecraft:oak_planks",
"color": "#835432",
"blockType": "LargeHeavyBlockArmorBlock"
}
]

10
go.mod Normal file
View file

@ -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
)

8
go.sum Normal file
View file

@ -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=

82
main.go Normal file
View file

@ -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)
}
}

84
output.xml Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0"?>
<Definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ShipBlueprints>
<ShipBlueprint xsi:type="MyObjectBuilder_ShipBlueprintDefinition">
<Id Type="MyObjectBuilder_ShipBlueprintDefinition" Subtype="minecraft:oak_stairs" />
<DisplayName>minecraft:oak_stairs</DisplayName>
<CubeGrids>
<CubeGrid>
<SubtypeName />
<EntityId>0</EntityId>
<PersistentFlags>CastShadows InScene</PersistentFlags>
<PositionAndOrientation>
<Position x="0" y="0" z="0" />
<Forward x="0" y="0" z="0" />
<Up x="0" y="0" z="0" />
<Orientation>
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<W>0</W>
</Orientation>
</PositionAndOrientation>
<LocalPositionAndOrientation xsi:nil="true" />
<GridSizeEnum>Large</GridSizeEnum>
<CubeBlocks>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="0" y="0" z="0" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="0" y="0" z="1" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="0" y="0" z="2" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="1" y="0" z="0" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="1" y="0" z="1" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
</CubeBlocks>
<LinearVelocity x="0" y="0" z="0" />
<AngularVelocity x="0" y="0" z="0" />
<DisplayName>minecraft:oak_stairs</DisplayName>
<DestructibleBlocks>true</DestructibleBlocks>
<IsRespawnGrid>false</IsRespawnGrid>
<LocalCoordSys>0</LocalCoordSys>
<TargetingTargets />
</CubeGrid>
</CubeGrids>
<EnvironmentType>None</EnvironmentType>
<WorkshopId>0</WorkshopId>
<OwnerSteamId>0</OwnerSteamId>
<Points>0</Points>
</ShipBlueprint>
</ShipBlueprints>
</Definitions>

85
se-blueprint.go Normal file
View file

@ -0,0 +1,85 @@
package main
import (
"strconv"
"strings"
)
var xmlHeader = `<?xml version="1.0"?>
<Definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ShipBlueprints>
<ShipBlueprint xsi:type="MyObjectBuilder_ShipBlueprintDefinition">
<Id Type="MyObjectBuilder_ShipBlueprintDefinition" Subtype="{NAME}" />
<DisplayName>{NAME}</DisplayName>
<CubeGrids>
<CubeGrid>
<SubtypeName />
<EntityId>0</EntityId>
<PersistentFlags>CastShadows InScene</PersistentFlags>
<PositionAndOrientation>
<Position x="0" y="0" z="0" />
<Forward x="0" y="0" z="0" />
<Up x="0" y="0" z="0" />
<Orientation>
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<W>0</W>
</Orientation>
</PositionAndOrientation>
<LocalPositionAndOrientation xsi:nil="true" />
<GridSizeEnum>Large</GridSizeEnum>
<CubeBlocks>
`
var xmlFooter = `
</CubeBlocks>
<LinearVelocity x="0" y="0" z="0" />
<AngularVelocity x="0" y="0" z="0" />
<DisplayName>{NAME}</DisplayName>
<DestructibleBlocks>true</DestructibleBlocks>
<IsRespawnGrid>false</IsRespawnGrid>
<LocalCoordSys>0</LocalCoordSys>
<TargetingTargets />
</CubeGrid>
</CubeGrids>
<EnvironmentType>None</EnvironmentType>
<WorkshopId>0</WorkshopId>
<OwnerSteamId>0</OwnerSteamId>
<Points>0</Points>
</ShipBlueprint>
</ShipBlueprints>
</Definitions>
`
// <SubtypeName>LargeBlockArmorBlock</SubtypeName>
// <SubtypeName>LargeHeavyBlockArmorBlock</SubtypeName>
var blockTemplate = `
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>{BLOCKTYPE}</SubtypeName>
<ColorMaskHSV x="{COLOR1}" y="{COLOR2}" z="{COLOR3}" />
<SkinSubtypeId>{SKIN}</SkinSubtypeId>
<Min x="{POSX}" y="{POSY}" z="{POSZ}" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
`
// 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
}

BIN
test.litematic Normal file

Binary file not shown.

84
test.sbc Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0"?>
<Definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ShipBlueprints>
<ShipBlueprint xsi:type="MyObjectBuilder_ShipBlueprintDefinition">
<Id Type="MyObjectBuilder_ShipBlueprintDefinition" Subtype="minecraft:oak_stairs" />
<DisplayName>minecraft:oak_stairs</DisplayName>
<CubeGrids>
<CubeGrid>
<SubtypeName />
<EntityId>0</EntityId>
<PersistentFlags>CastShadows InScene</PersistentFlags>
<PositionAndOrientation>
<Position x="0" y="0" z="0" />
<Forward x="0" y="0" z="0" />
<Up x="0" y="0" z="0" />
<Orientation>
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<W>0</W>
</Orientation>
</PositionAndOrientation>
<LocalPositionAndOrientation xsi:nil="true" />
<GridSizeEnum>Large</GridSizeEnum>
<CubeBlocks>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="0" y="0" z="0" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="0" y="0" z="1" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="0" y="0" z="2" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="1" y="0" z="0" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
<MyObjectBuilder_CubeBlock xsi:type="MyObjectBuilder_CubeBlock">
<SubtypeName>LargeBlockArmorBlock</SubtypeName>
<ColorMaskHSV x="0.472222" y="-0.776471" z="0.550000" />
<SkinSubtypeId>Concrete_Armor</SkinSubtypeId>
<Min x="1" y="0" z="1" />
<BuiltBy>0</BuiltBy>
</MyObjectBuilder_CubeBlock>
</CubeBlocks>
<LinearVelocity x="0" y="0" z="0" />
<AngularVelocity x="0" y="0" z="0" />
<DisplayName>minecraft:oak_stairs</DisplayName>
<DestructibleBlocks>true</DestructibleBlocks>
<IsRespawnGrid>false</IsRespawnGrid>
<LocalCoordSys>0</LocalCoordSys>
<TargetingTargets />
</CubeGrid>
</CubeGrids>
<EnvironmentType>None</EnvironmentType>
<WorkshopId>0</WorkshopId>
<OwnerSteamId>0</OwnerSteamId>
<Points>0</Points>
</ShipBlueprint>
</ShipBlueprints>
</Definitions>

3
todo Normal file
View file

@ -0,0 +1,3 @@
allow assigning texture
read from config file for block ID conversions