github.com/df-mc/dragonfly@v0.9.13/server/internal/blockinternal/components.go (about) 1 package blockinternal 2 3 import ( 4 "github.com/df-mc/dragonfly/server/block" 5 "github.com/df-mc/dragonfly/server/block/cube" 6 "github.com/df-mc/dragonfly/server/block/customblock" 7 "github.com/df-mc/dragonfly/server/world" 8 "github.com/go-gl/mathgl/mgl64" 9 ) 10 11 // Components returns all the components for the custom block, including permutations and properties. 12 func Components(identifier string, b world.CustomBlock, blockID int32) map[string]any { 13 components := componentsFromProperties(b.Properties()) 14 builder := NewComponentBuilder(identifier, components, blockID) 15 if emitter, ok := b.(block.LightEmitter); ok { 16 builder.AddComponent("minecraft:block_light_emission", map[string]any{ 17 "emission": float32(emitter.LightEmissionLevel() / 15), 18 }) 19 } 20 if diffuser, ok := b.(block.LightDiffuser); ok { 21 builder.AddComponent("minecraft:block_light_filter", map[string]any{ 22 "lightLevel": int32(diffuser.LightDiffusionLevel()), 23 }) 24 } 25 if breakable, ok := b.(block.Breakable); ok { 26 info := breakable.BreakInfo() 27 builder.AddComponent("minecraft:destructible_by_mining", map[string]any{"value": float32(info.Hardness)}) 28 } 29 if frictional, ok := b.(block.Frictional); ok { 30 builder.AddComponent("minecraft:friction", map[string]any{"value": float32(frictional.Friction())}) 31 } 32 if flammable, ok := b.(block.Flammable); ok { 33 info := flammable.FlammabilityInfo() 34 builder.AddComponent("minecraft:flammable", map[string]any{ 35 "flame_odds": int32(info.Encouragement), 36 "burn_odds": int32(info.Flammability), 37 }) 38 } 39 if permutable, ok := b.(block.Permutable); ok { 40 for name, values := range permutable.States() { 41 builder.AddProperty(name, values) 42 } 43 for _, permutation := range permutable.Permutations() { 44 builder.AddPermutation(permutation.Condition, componentsFromProperties(permutation.Properties)) 45 } 46 } 47 if item, ok := b.(world.CustomItem); ok { 48 builder.SetMenuCategory(item.Category()) 49 } 50 return builder.Construct() 51 } 52 53 // componentsFromProperties builds a base components map that includes all the common data between a regular block and 54 // a custom permutation. 55 func componentsFromProperties(props customblock.Properties) map[string]any { 56 components := make(map[string]any) 57 if props.CollisionBox != (cube.BBox{}) { 58 components["minecraft:collision_box"] = bboxComponent(props.CollisionBox) 59 } 60 if props.SelectionBox != (cube.BBox{}) { 61 components["minecraft:selection_box"] = bboxComponent(props.SelectionBox) 62 } 63 if props.Geometry != "" { 64 components["minecraft:geometry"] = map[string]any{"identifier": props.Geometry} 65 } else if props.Cube { 66 components["minecraft:unit_cube"] = map[string]any{} 67 } 68 if props.MapColour != "" { 69 components["minecraft:map_color"] = map[string]any{"value": props.MapColour} 70 } 71 if props.Textures != nil { 72 materials := map[string]any{} 73 for target, material := range props.Textures { 74 materials[target] = material.Encode() 75 } 76 components["minecraft:material_instances"] = map[string]any{ 77 "mappings": map[string]any{}, 78 "materials": materials, 79 } 80 } 81 transformation := make(map[string]any) 82 if props.Rotation != (cube.Pos{}) { 83 transformation["RX"] = int32(props.Rotation.X()) 84 transformation["RY"] = int32(props.Rotation.Y()) 85 transformation["RZ"] = int32(props.Rotation.Z()) 86 } 87 if props.Translation != (mgl64.Vec3{}) { 88 transformation["TX"] = float32(props.Translation.X()) 89 transformation["TY"] = float32(props.Translation.Y()) 90 transformation["TZ"] = float32(props.Translation.Z()) 91 } 92 if props.Scale != (mgl64.Vec3{}) { 93 transformation["SX"] = float32(props.Scale.X()) 94 transformation["SY"] = float32(props.Scale.Y()) 95 transformation["SZ"] = float32(props.Scale.Z()) 96 } else if len(transformation) > 0 { 97 transformation["SX"] = float32(1.0) 98 transformation["SY"] = float32(1.0) 99 transformation["SZ"] = float32(1.0) 100 } 101 if len(transformation) > 0 { 102 components["minecraft:transformation"] = transformation 103 } 104 return components 105 } 106 107 // bboxComponent returns the component data for a bounding box. It translates the coordinates to the origin and size 108 // format that the client expects. 109 func bboxComponent(box cube.BBox) map[string]any { 110 min, max := box.Min(), box.Max() 111 originX, originY, originZ := min.X()*16, min.Y()*16, min.Z()*16 112 sizeX, sizeY, sizeZ := (max.X()-min.X())*16, (max.Y()-min.Y())*16, (max.Z()-min.Z())*16 113 return map[string]any{ 114 "enabled": true, 115 "origin": []float32{float32(originX) - 8, float32(originY), float32(originZ) - 8}, 116 "size": []float32{float32(sizeX), float32(sizeY), float32(sizeZ)}, 117 } 118 }