dim manager test 2
This commit is contained in:
@ -3,51 +3,100 @@ package dimension
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
"github.com/Tnze/go-mc/level"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/Tnze/go-mc/server"
|
||||
"github.com/Tnze/go-mc/server/clientinfo"
|
||||
"github.com/Tnze/go-mc/server/internal/bvh"
|
||||
)
|
||||
|
||||
type vec2d = bvh.Vec2[float64]
|
||||
type sphere2d = bvh.Sphere[float64, vec2d]
|
||||
|
||||
type manager struct {
|
||||
storage
|
||||
elements map[level.ChunkPos]*list.Element
|
||||
activeChunks *list.List
|
||||
|
||||
chunkLoadQueue []level.ChunkPos
|
||||
chunkUnloadQueue []level.ChunkPos
|
||||
chunkElement map[level.ChunkPos]*list.Element
|
||||
players bvh.Tree[float64, sphere2d, *server.Player]
|
||||
clients *clientinfo.ClientInformation
|
||||
}
|
||||
|
||||
type chunkHandler struct {
|
||||
level.ChunkPos
|
||||
*level.Chunk
|
||||
// records all players loaded this chunk
|
||||
players map[*server.Player]struct{}
|
||||
}
|
||||
|
||||
func (m *manager) refresh(players [][2]int) {
|
||||
m.chunkLoadQueue = m.chunkLoadQueue[:0]
|
||||
m.chunkUnloadQueue = m.chunkUnloadQueue[:0]
|
||||
|
||||
newActives := list.New()
|
||||
const N = 16
|
||||
for _, p := range players {
|
||||
for i := 1 - N; i < N; i++ {
|
||||
for j := 1 - N; j < N; j++ {
|
||||
func (m *manager) refresh() error {
|
||||
all := func(b sphere2d) bool { return true }
|
||||
m.players.Find(all, func(n *bvh.Node[float64, sphere2d, *server.Player]) bool {
|
||||
p := n.Value
|
||||
v := m.clients.Players[p.UUID].ViewDistance
|
||||
for i := 1 - v; i < v; i++ {
|
||||
for j := 1 - v; j < v; j++ {
|
||||
pos := level.ChunkPos{
|
||||
X: p[0] + i,
|
||||
Z: p[1] + j,
|
||||
X: int(n.Box.Center[0]) >> 4,
|
||||
Z: int(n.Box.Center[1]) >> 4,
|
||||
}
|
||||
if e := m.elements[pos]; e != nil {
|
||||
// chunk exist, move into newActives
|
||||
v := m.activeChunks.Remove(e)
|
||||
m.elements[pos] = newActives.PushBack(v)
|
||||
} else {
|
||||
// not exist, load from storage
|
||||
m.chunkLoadQueue = append(m.chunkLoadQueue, pos)
|
||||
point := vec2d{float64(pos.X + i), float64(pos.Z + j)}
|
||||
if _, exist := m.chunkElement[pos]; !exist && n.Box.WithIn(point) {
|
||||
c, err := m.GetChunk(pos)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
m.chunkElement[pos] = m.activeChunks.PushBack(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
for e := m.activeChunks.Front(); e != nil; {
|
||||
ch := e.Value.(*chunkHandler)
|
||||
point := vec2d{float64(ch.X), float64(ch.Z)}
|
||||
filter := bvh.TouchPoint[vec2d, sphere2d](point)
|
||||
newPlayers := make(map[*server.Player]struct{})
|
||||
m.players.Find(filter, func(n *bvh.Node[float64, sphere2d, *server.Player]) bool {
|
||||
p := n.Value
|
||||
if _, ok := ch.players[p]; ok {
|
||||
delete(ch.players, p)
|
||||
} else {
|
||||
playerLoadChunk(p, ch)
|
||||
}
|
||||
newPlayers[p] = struct{}{}
|
||||
return true
|
||||
})
|
||||
for p := range ch.players {
|
||||
playerUnloadChunk(p, ch)
|
||||
}
|
||||
if len(newPlayers) > 0 {
|
||||
ch.players = newPlayers
|
||||
e = e.Next()
|
||||
} else {
|
||||
// no player around this chunk, unload it
|
||||
if err := m.PutChunk(ch.ChunkPos, ch.Chunk); err != nil {
|
||||
return err
|
||||
}
|
||||
next := e.Next()
|
||||
m.activeChunks.Remove(e)
|
||||
delete(m.chunkElement, ch.ChunkPos)
|
||||
e = next
|
||||
}
|
||||
}
|
||||
for e := m.activeChunks.Front(); e != nil; e = e.Next() {
|
||||
pos := e.Value.(chunkHandler).ChunkPos
|
||||
m.chunkUnloadQueue = append(m.chunkUnloadQueue, pos)
|
||||
m.elements[pos] = newActives.PushBack(e.Value)
|
||||
}
|
||||
m.activeChunks = newActives
|
||||
return nil
|
||||
}
|
||||
|
||||
func playerLoadChunk(p *server.Player, c *chunkHandler) {
|
||||
p.WritePacket(server.Packet758(pk.Marshal(
|
||||
packetid.ClientboundLevelChunkWithLight,
|
||||
c.ChunkPos, c.Chunk,
|
||||
)))
|
||||
}
|
||||
|
||||
func playerUnloadChunk(p *server.Player, c *chunkHandler) {
|
||||
p.WritePacket(server.Packet758(pk.Marshal(
|
||||
packetid.ClientboundForgetLevelChunk,
|
||||
c.ChunkPos,
|
||||
)))
|
||||
}
|
||||
|
Reference in New Issue
Block a user