Support operate regions on the fly
This commit is contained in:
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
// Region contain 32*32 chunks in one .mca file
|
// Region contain 32*32 chunks in one .mca file
|
||||||
type Region struct {
|
type Region struct {
|
||||||
f *os.File
|
f io.ReadWriteSeeker
|
||||||
offsets [32][32]int32
|
offsets [32][32]int32
|
||||||
timestamps [32][32]int32
|
timestamps [32][32]int32
|
||||||
|
|
||||||
@ -27,21 +27,30 @@ func In(cx, cy int) (int, int) {
|
|||||||
return cx & 31, cy & 31
|
return cx & 31, cy & 31
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open open a .mca file and read the head.
|
// Open a .mca file and read the head.
|
||||||
// Close the Region after used.
|
// Close the Region after used.
|
||||||
func Open(name string) (r *Region, err error) {
|
func Open(name string) (r *Region, err error) {
|
||||||
r = new(Region)
|
f, err := os.OpenFile(name, os.O_RDWR, 0666)
|
||||||
r.sectors = make(map[int32]bool)
|
|
||||||
|
|
||||||
r.f, err = os.OpenFile(name, os.O_RDWR, 0666)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
r, err = Load(f)
|
||||||
|
if err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load works like Open but read from an io.ReadWriteSeeker.
|
||||||
|
func Load(f io.ReadWriteSeeker) (r *Region, err error) {
|
||||||
|
r = &Region{
|
||||||
|
f: f,
|
||||||
|
sectors: make(map[int32]bool),
|
||||||
|
}
|
||||||
|
|
||||||
// read the offsets
|
// read the offsets
|
||||||
err = binary.Read(r.f, binary.BigEndian, &r.offsets)
|
err = binary.Read(r.f, binary.BigEndian, &r.offsets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = r.f.Close()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.sectors[0] = true
|
r.sectors[0] = true
|
||||||
@ -49,7 +58,6 @@ func Open(name string) (r *Region, err error) {
|
|||||||
// read the timestamps
|
// read the timestamps
|
||||||
err = binary.Read(r.f, binary.BigEndian, &r.timestamps)
|
err = binary.Read(r.f, binary.BigEndian, &r.timestamps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = r.f.Close()
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.sectors[1] = true
|
r.sectors[1] = true
|
||||||
@ -78,18 +86,18 @@ func Create(name string) (r *Region, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the offsets
|
// write the offsets
|
||||||
err = binary.Write(r.f, binary.BigEndian, &r.offsets)
|
err = binary.Write(r.f, binary.BigEndian, &r.offsets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = r.f.Close()
|
_ = r.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.sectors[0] = true
|
r.sectors[0] = true
|
||||||
|
|
||||||
// read the timestamps
|
// write the timestamps
|
||||||
err = binary.Write(r.f, binary.BigEndian, &r.timestamps)
|
err = binary.Write(r.f, binary.BigEndian, &r.timestamps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = r.f.Close()
|
_ = r.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.sectors[1] = true
|
r.sectors[1] = true
|
||||||
@ -97,9 +105,15 @@ func Create(name string) (r *Region, err error) {
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close close the region file
|
// Close the region file if possible.
|
||||||
|
// The responsibility for Close the file with who Open it.
|
||||||
|
// If you made the Region with Load(),
|
||||||
|
// this method close the file only if your io.ReadWriteSeeker implement io.Close
|
||||||
func (r *Region) Close() error {
|
func (r *Region) Close() error {
|
||||||
return r.f.Close()
|
if closer, ok := r.f.(io.Closer); ok {
|
||||||
|
return closer.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sectorLoc(offset int32) (sec, num int32) {
|
func sectorLoc(offset int32) (sec, num int32) {
|
||||||
@ -211,16 +225,27 @@ func (r *Region) setHead(x, y int, offset, timestamp uint32) (err error) {
|
|||||||
var buf [4]byte
|
var buf [4]byte
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(buf[:], offset)
|
binary.BigEndian.PutUint32(buf[:], offset)
|
||||||
_, err = r.f.WriteAt(buf[:], 4*(int64(x)*32+int64(y)))
|
_, err = r.writeAt(buf[:], 4*(int64(x)*32+int64(y)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(buf[:], timestamp)
|
binary.BigEndian.PutUint32(buf[:], timestamp)
|
||||||
_, err = r.f.WriteAt(buf[:], 4096+4*(int64(x)*32+int64(y)))
|
_, err = r.writeAt(buf[:], 4096+4*(int64(x)*32+int64(y)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Region) writeAt(p []byte, off int64) (n int, err error) {
|
||||||
|
if f, ok := r.f.(io.WriterAt); ok {
|
||||||
|
return f.WriteAt(p, off)
|
||||||
|
}
|
||||||
|
_, err = r.f.Seek(off, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return r.f.Write(p)
|
||||||
|
}
|
||||||
|
@ -44,7 +44,7 @@ func TestReadRegion(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
//t.Log(b)
|
t.Log(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user