minewebgen - internal/generator/main.go
1 package main // import "vimagination.zapto.org/minewebgen/internal/generator"
2
3 import (
4 "encoding/json"
5 "image/color"
6 "os"
7 "path"
8
9 "vimagination.zapto.org/byteio"
10 "vimagination.zapto.org/minecraft"
11 "vimagination.zapto.org/minewebgen/internal/data"
12 "vimagination.zapto.org/ora"
13 )
14
15 func LoadGenerator(f *os.File) (*generator, error) {
16 g := new(generator)
17 err := json.NewDecoder(f).Decode(&g.generator)
18 if err != nil {
19 return nil, err
20 }
21 if len(g.generator.Terrain) == 0 {
22 g.generator.Terrain = []data.ColourBlocks{{Name: "Empty"}}
23 }
24 if len(g.generator.Biomes) == 0 {
25 g.generator.Biomes = []data.ColourBiome{{Name: "Plains", Biome: 1}}
26 }
27 if len(g.generator.Plants) == 0 {
28 g.generator.Plants = []data.ColourBlocks{{Name: "Empty"}}
29 }
30
31 g.Terrain.Blocks = make([]data.Blocks, len(g.generator.Terrain)+1)
32 g.Terrain.Palette = make(color.Palette, len(g.generator.Terrain))
33 for i := range g.generator.Terrain {
34 g.Terrain.Blocks[i] = g.generator.Terrain[i].Blocks
35 g.Terrain.Palette[i] = g.generator.Terrain[i].Colour
36 }
37 g.Terrain.Blocks[len(g.Terrain.Blocks)-1].Base.ID = 9
38
39 g.Biomes.Values = make([]minecraft.Biome, len(g.generator.Biomes))
40 g.Biomes.Palette = make(color.Palette, len(g.generator.Biomes))
41 for i := range g.generator.Biomes {
42 g.Biomes.Values[i] = g.generator.Biomes[i].Biome
43 g.Biomes.Palette[i] = g.generator.Biomes[i].Colour
44 }
45
46 g.Plants.Blocks = make([]data.Blocks, len(g.generator.Plants))
47 g.Plants.Palette = make(color.Palette, len(g.generator.Plants))
48 for i := range g.generator.Plants {
49 g.Plants.Blocks[i] = g.generator.Plants[i].Blocks
50 g.Plants.Palette[i] = g.generator.Plants[i].Colour
51 }
52 return g, nil
53 }
54
55 func main() {
56 r := byteio.StickyLittleEndianReader{Reader: os.Stdin}
57 w := byteio.StickyLittleEndianWriter{Writer: os.Stdout}
58 if err := generate(&r, &w, os.NewFile(3, "data.ora")); err != nil {
59 w.WriteUint8(0)
60 data.WriteString(&w, err.Error())
61 os.Exit(1)
62 }
63 }
64
65 func generate(r *byteio.StickyLittleEndianReader, w *byteio.StickyLittleEndianWriter, of *os.File) error {
66 memoryLimit := r.ReadUint64()
67 size := r.ReadInt64()
68 gPath := data.ReadString(r)
69 levelName := data.ReadString(r)
70 mapPath := data.ReadString(r)
71 if r.Err != nil {
72 return r.Err
73 }
74 o, err := ora.Open(of, size)
75 if err != nil {
76 return err
77 }
78 f, err := os.Open(path.Join(gPath, "data.gen"))
79 if err != nil {
80 return err
81 }
82 g, err := LoadGenerator(f)
83 if e := f.Close(); e != nil {
84 return e
85 }
86 if err != nil {
87 return err
88 }
89
90 b := o.Bounds()
91 w.WriteUint8(2)
92 w.WriteInt32(int32(b.Max.X) >> 4)
93 w.WriteInt32(int32(b.Max.Y) >> 4)
94
95 c := make(chan paint, 1024)
96 m := make(chan string, 4)
97 e := make(chan struct{}, 0)
98 go func() {
99 defer close(e)
100 defer close(m)
101 defer close(c)
102 for {
103 select {
104 case message := <-m:
105 w.WriteUint8(3)
106 data.WriteString(w, message)
107 case p := <-c:
108 w.WriteUint8(4)
109 w.WriteInt32(p.X)
110 w.WriteInt32(p.Y)
111 r, g, b, a := p.RGBA()
112 w.WriteUint8(uint8(r >> 8))
113 w.WriteUint8(uint8(g >> 8))
114 w.WriteUint8(uint8(b >> 8))
115 w.WriteUint8(uint8(a >> 8))
116 case <-e:
117 return
118 }
119 }
120 }()
121
122 err = g.Generate(levelName, mapPath, o, c, m, memoryLimit)
123
124 e <- struct{}{}
125 <-e
126 return err
127 }
128
129 type paint struct {
130 color.Color
131 X, Y int32
132 }