diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/flate.go | 171 | ||||
| -rw-r--r-- | server/map.go | 8 | ||||
| -rw-r--r-- | server/player.go | 6 |
3 files changed, 115 insertions, 70 deletions
diff --git a/server/flate.go b/server/flate.go index 99517c1..e2d87f4 100644 --- a/server/flate.go +++ b/server/flate.go @@ -2,6 +2,7 @@ package server import ( "io" + "math/bits" "encoding/binary" ) @@ -12,17 +13,18 @@ import ( // compressor, translate it directly into DEFLATE func deflateRuns( wr io.Writer, runs []blockData, changes []blockData, - levelSize uint32) error { - var err error + levelSize uint32) (length uint32, err error) { bw := bitsWriter {wr: wr} - bw.Write(0b01, 2) // fixed huffman - writeCode(&bw, 0xff & levelSize) - writeCode(&bw, 0xff & (levelSize >> 8)) + + bw.Write(0b011, 3) // BFINAL, fixed huffman + writeCode(&bw, 0xff & (levelSize >> 24)) writeCode(&bw, 0xff & (levelSize >> 16)) - err = writeCode(&bw, 0xff & levelSize >> 24) + writeCode(&bw, 0xff & (levelSize >> 8)) + err = writeCode(&bw, 0xff & levelSize) if err != nil { - return err + return } + for i, data := range runs { var nextPos uint32 if i < len(runs) - 1 { @@ -40,74 +42,113 @@ func deflateRuns( writeRun(&bw, byte(data.Block), ch.Pos - curPos) err = writeRun(&bw, byte(ch.Block), 1) if err != nil { - return err + return } curPos = ch.Pos + 1 } if curPos < nextPos { err = writeRun(&bw, byte(data.Block), nextPos - curPos) if err != nil { - return err + return } } } - return writeCode(&bw, 256) // end of block + writeCode(&bw, 256) + return levelSize + 4, bw.Close() +} + +var lengthExtraBits = [...]uint8{ + /* 257 */ 0, 0, 0, + /* 260 */ 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, + /* 270 */ 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, + /* 280 */ 4, 5, 5, 5, 5, 0, +} + +var lengthBase = [...]uint32{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, + 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 255, +} + +var lengthCodes = [...]uint32{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, + 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, + 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 28, } func writeRun(bw *bitsWriter, value byte, totalLen uint32) error { var err error for totalLen > 0 { len := min(totalLen, 258) - if len < 3 { + if len < 4 { for i := 0; i < int(len); i++ { err = writeCode(bw, uint32(value)) } } else { writeCode(bw, uint32(value)) - err = writeRunLength(bw, len) + writeLength(bw, len - 1) + err = bw.Write(0b00000, 5) // distance: 1 } totalLen -= len } return err } -func writeRunLength(bw *bitsWriter, length uint32) error { +func writeLength(bw *bitsWriter, length uint32) error { length -= 3 - if length < 11 { - writeCode(bw, 257 + length) - } else if length < 19 { - writeCode(bw, 265 + length >> 1) - bw.Write(length & 0b1, 1) - } else if length < 35 { - writeCode(bw, 269 + length >> 2) - bw.Write(length & 0b11, 2) - } else if length < 115 { - writeCode(bw, 273 + length >> 3) - bw.Write(length & 0b111, 3) - } else if length < 131 { - writeCode(bw, 273 + length >> 4) - bw.Write(length & 0b1111, 4) - } else if length < 285 { - writeCode(bw, 281 + length >> 5) - bw.Write(length & 0b11111, 5) - } else if length == 258 { - writeCode(bw, 285) - } else { - panic("length out of range") - } - return writeCode(bw, 0) + code := lengthCodes[length] + writeCode(bw, 257 + code) + return bw.Write(length - lengthBase[code], lengthExtraBits[code]) } func writeCode(bw *bitsWriter, v uint32) error { - if v < 144 { - return bw.Write(0b00110000 + v, 8) - } else if v < 256 { - return bw.Write(0b110010000 + v, 9) - } else if v < 280 { - return bw.Write(v, 7) - } else { - return bw.Write(0b11000000, 8) + var code uint32 + var size uint8 + switch { + case v < 144: + // size 8, 000110000 .. 10111111 + code = v + 48 + size = 8 + case v < 256: + // size 9, 110010000 .. 111111111 + code = v + 400 - 144 + size = 9 + case v < 280: + // size 7, 0000000 .. 0010111 + code = v - 256 + size = 7 + case v < 288: + // size 8, 11000000 .. 11000111 + code = v + 192 - 280 + size = 8 + default: + panic("code value out of range") } + code = bits.Reverse32(code << (32 - size)) + return bw.Write(code, size) } type bitsWriter struct { @@ -115,22 +156,34 @@ type bitsWriter struct { buf uint64 nbuf byte } -func (bw *bitsWriter) Write(bits uint32, n byte) error { - bw.buf |= uint64(bits & ((1<<n)-1)) << bw.nbuf - bw.nbuf += n - if bw.nbuf < 32 { - return nil + +func (bw *bitsWriter) Write(v uint32, n uint8) error { + if 64 - bw.nbuf < n { + err := bw.writeBuf() + if err != nil { + return err + } } + bw.buf |= uint64(v & ((1<<n)-1)) << bw.nbuf + bw.nbuf += n + return nil +} + +func (bw *bitsWriter) writeBuf() error { var bytes [8]byte binary.LittleEndian.PutUint64(bytes[:], bw.buf) - _, err := bw.wr.Write(bytes[:bw.nbuf / 8]) - bw.buf >>= bw.nbuf / 8 - bw.nbuf -= bw.nbuf / 8 + nbytes := bw.nbuf / 8 + _, err := bw.wr.Write(bytes[:nbytes]) + bw.buf >>= nbytes * 8 + bw.nbuf -= nbytes * 8 return err } -func (bw *bitsWriter) Flush() error { - return bw.Write(0, 0) +func (bw *bitsWriter) Close() error { + if bw.nbuf > 0 { + bw.Write(0, 8 - (bw.nbuf % 8)) + } + return bw.writeBuf() } func writePointlessGzipHeader(wr io.Writer) error { @@ -147,13 +200,9 @@ func writePointlessGzipHeader(wr io.Writer) error { } func writePointlessGzipTrailer(wr io.Writer, length uint32) error { - var trailer = [8]byte { - 0, 0, 0, 0, - byte(length), - byte(length >> 8), - byte(length >> 16), - byte(length >> 24), - } + var trailer [8]byte + binary.LittleEndian.PutUint32(trailer[0:], 0xffffffff) + binary.LittleEndian.PutUint32(trailer[4:], length) _, err := wr.Write(trailer[:]) return err } diff --git a/server/map.go b/server/map.go index f210d42..345a62c 100644 --- a/server/map.go +++ b/server/map.go @@ -201,14 +201,16 @@ func (v *blockVolume) unsyncBlocksInRange(min, max blockPos) []blockType { func (v *blockVolume) syncCompressForNetwork(/*highBits bool*/) io.ReadCloser { rd, wr := io.Pipe() go func() { + defer wr.Close() v.RLock() defer v.RUnlock() bw := bufio.NewWriter(wr) defer bw.Flush() + writePointlessGzipHeader(bw) - len := uint32(v.size.X*v.size.Y*v.size.Z) - deflateRuns(wr, v.blockRuns, v.changes, len) - writePointlessGzipTrailer(bw, len) + size := uint32(v.size.X*v.size.Y*v.size.Z) + dataLen, _ := deflateRuns(bw, v.blockRuns, v.changes, size) + writePointlessGzipTrailer(bw, dataLen) }() return rd } diff --git a/server/player.go b/server/player.go index a6219cc..d2c6722 100644 --- a/server/player.go +++ b/server/player.go @@ -272,12 +272,6 @@ func (p *player) OnLevelData(from *level, info levelInfo, data io.ReadCloser) { } packets := func(yield func(classic.Packet) bool) { defer data.Close() - dbg, err := os.OpenFile("./debug.gz", os.O_CREATE | os.O_WRONLY, 0777) - if err != nil { - panic(err) - } - defer dbg.Close() - data := io.TeeReader(data, dbg) for { var packet classic.LevelDataChunk n, err := io.ReadFull(data, packet.Data[:]) |
