func (p *_player) sendWorldData() { go func() { for { for i, chunk := range p.chunkSet { x, z := chunk.X, chunk.Z dx, dz := (int32(p.stored.Position[0])>>4)-x, (int32(p.stored.Position[2])>>4)-z if dx > 10 || dx < -10 || dz > 10 || dz < -10 { storage.ReleaseChunk(x, z) sendChunk(p, x, z, nil) delete(p.chunkSet, i) } } for i := int32(1); i <= 8; i++ { middleX, middleZ := int32(p.stored.Position[0]/16), int32(p.stored.Position[2]/16) for x := middleX - i; x < middleX+i; x++ { for z := middleZ - i; z < middleZ+i; z++ { id := uint64(uint32(x))<<32 | uint64(uint32(z)) if _, ok := p.chunkSet[id]; !ok { p.chunkSet[id] = storage.GetChunk(x, z) sendChunk(p, x, z, p.chunkSet[id]) runtime.Gosched() } } } if i == 2 && !p.spawned { p.sendSpawnPacket() p.spawned = true } } time.Sleep(100 * time.Millisecond) } }() }
func ticker() { for { time.Sleep(50 * time.Millisecond) updateLock.Lock() queue := updateQueue updateQueue = make(map[struct{ x, y, z int32 }]bool) updateLock.Unlock() updateCount := 0 for loc, _ := range queue { x, y, z := loc.x, loc.y, loc.z blockType := GetBlockAt(x, y, z) switch blockType { case block.Water: if !spreadWater(x, y, z) && GetBlockAt(x, y, z) == block.Water { setBlockNoUpdate(x, y, z, block.StationaryWater, GetBlockDataAt(x, y, z)) } case block.Sand, block.Gravel, block.LongGrass, block.RedFlower, block.YellowFlower: if GetBlockAt(x, y-1, z).Passable() { blockData := GetBlockDataAt(x, y, z) SetBlockAt(x, y, z, GetBlockAt(x, y-1, z), GetBlockDataAt(x, y-1, z)) SetBlockAt(x, y-1, z, blockType, blockData) } case block.Sponge: switch GetBlockAt(x, y+1, z) { case block.Water, block.StationaryWater: decrementWater(x, y+1, z) } } updateCount++ delete(queue, loc) runtime.Gosched() // Don't cause too much lag if updateCount >= 10000 { log.Print("> 10000 updates. Waiting for the next tick to resume updating.") break } } for loc, _ := range queue { queueUpdate(loc.x, loc.y, loc.z) } blockSendLock.Lock() for chunk, blocks := range blockSendQueue { c := storage.GetChunk(chunk.x, chunk.z) packet := protocol.MultiBlockChange{X: chunk.x, Z: chunk.z, Blocks: make([]uint32, 0, len(blocks))} for block, _ := range blocks { packet.Blocks = append(packet.Blocks, uint32(block.x&0xF)<<28|uint32(block.z&0xF)<<24|uint32(block.y)<<16|uint32(c.GetBlock(block.x, block.y, block.z))<<4|uint32(c.GetData(block.x, block.y, block.z))) } storage.ReleaseChunk(chunk.x, chunk.z) SendToAll(packet) delete(blockSendQueue, chunk) } blockSendLock.Unlock() } }