Euskal Encounter Hack-it 27 (2019). Level 3. Extract minecraft coordinates from protocol and creates an image
package main | |
import ( | |
"bytes" | |
"encoding/binary" | |
// "encoding/hex" | |
"fmt" | |
"image" | |
"image/color" | |
"image/png" | |
"io/ioutil" | |
"math" | |
"os" | |
) | |
type Packet struct { | |
ID uint64 | |
Data []byte | |
} | |
func readPacket(r *bytes.Reader) (*Packet, error) { | |
l, err := binary.ReadUvarint(r) | |
if err != nil { | |
return nil, err | |
} | |
buf := make([]byte, l) | |
if _, err := r.Read(buf); err != nil { | |
return nil, err | |
} | |
pr := bytes.NewReader(buf) | |
_, err = binary.ReadUvarint(pr) | |
if err != nil { | |
return nil, err | |
} | |
id, err := binary.ReadUvarint(pr) | |
if err != nil { | |
return nil, err | |
} | |
packet := &Packet{ | |
ID: id, | |
Data: make([]byte, pr.Len()), | |
} | |
if _, err := pr.Read(packet.Data); err != nil { | |
return nil, err | |
} | |
return packet, nil | |
} | |
func readString(data []byte) string { | |
r := bytes.NewReader(data) | |
if _, err := binary.ReadUvarint(r); err != nil { | |
return "" | |
} | |
buf := make([]byte, r.Len()) | |
if _, err := r.Read(buf); err != nil { | |
return "" | |
} | |
return string(buf) | |
} | |
const ymul = 200.0 | |
const ysub = 4.0 | |
const xzmul = 5.0 | |
const xsub = 925.298677 | |
const zsub = 683.356262 | |
func main() { | |
file := os.Args[1] | |
content, err := ioutil.ReadFile(file) | |
if err != nil { | |
fmt.Println("Error reading file:", err) | |
os.Exit(1) | |
} | |
r := bytes.NewReader(content) | |
xmax := 0.0 | |
xmin := 1000000.0 | |
ymax := 0.0 | |
ymin := 1000000.0 | |
zmax := 0.0 | |
zmin := 1000000.0 | |
outImg := image.NewRGBA(image.Rectangle{ | |
Min: image.Point{0, 0}, | |
Max: image.Point{1000, 100}, | |
}) | |
for { | |
var packet *Packet | |
packet, err = readPacket(r) | |
if err != nil { | |
break | |
} | |
//fmt.Printf("%02x\n", packet.ID) | |
if packet.ID == 0x30 { | |
//fmt.Println(string(packet.Data[len(packet.Data)-1:])) | |
//fmt.Println(hex.EncodeToString(packet.Data)) | |
} else if packet.ID == 0x10 { | |
pr := bytes.NewReader(packet.Data) | |
xb := make([]byte, 8) | |
yb := make([]byte, 8) | |
zb := make([]byte, 8) | |
if _, err = pr.Read(xb); err != nil { | |
break | |
} | |
if _, err = pr.Read(yb); err != nil { | |
break | |
} | |
if _, err = pr.Read(zb); err != nil { | |
break | |
} | |
var onGround byte | |
if onGround, err = pr.ReadByte(); err != nil { | |
break | |
} | |
/* | |
y := math.Float64frombits(binary.BigEndian.Uint64(yb)) | |
if y == 4.0 { | |
fmt.Println(0) | |
} else if y == 5.0 { | |
fmt.Println(1) | |
} | |
*/ | |
x := math.Float64frombits(binary.BigEndian.Uint64(xb)) | |
y := math.Float64frombits(binary.BigEndian.Uint64(yb)) | |
z := math.Float64frombits(binary.BigEndian.Uint64(zb)) | |
fmt.Printf("x: %f\n", x) | |
fmt.Printf("y: %f\n", y) | |
fmt.Printf("z: %f\n", z) | |
fmt.Printf("onGround: %d\n", onGround) | |
yint := uint8(math.Round((y - ysub) * ymul)) | |
colour := color.RGBA{yint, yint, yint, 255} | |
xint := int(math.Round((x - xsub) * xzmul)) | |
zint := int(math.Round((z - zsub) * xzmul)) | |
outImg.Set(zint, xint, colour) | |
if x > xmax { | |
xmax = x | |
} | |
if x < xmin { | |
xmin = x | |
} | |
if y > ymax { | |
ymax = y | |
} | |
if y < ymin { | |
ymin = y | |
} | |
if z > zmax { | |
zmax = z | |
} | |
if z < zmin { | |
zmin = z | |
} | |
} | |
} | |
fmt.Printf("xmax: %f\nxmin: %f\n", xmax, xmin) | |
fmt.Printf("ymax: %f\nymin: %f\n", ymax, ymin) | |
fmt.Printf("zmax: %f\nzmin: %f\n", zmax, zmin) | |
f, err := os.Create("image.png") | |
if err != nil { | |
fmt.Println("error creating image file:", err) | |
os.Exit(1) | |
} | |
if err = png.Encode(f, outImg); err != nil { | |
fmt.Println("error writing image:", err) | |
os.Exit(1) | |
} | |
fmt.Println(err) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment