func (s *Session) UUID() uuid.UUID {
	return s.uuid
}
UUID returns the UUID from the session's connection.
package session
import (
	"errors"
	"github.com/google/uuid"
	"github.com/paroxity/portal/event"
	"github.com/paroxity/portal/query"
	"github.com/paroxity/portal/server"
	"github.com/sandertv/gophertunnel/minecraft"
	"github.com/sandertv/gophertunnel/minecraft/protocol"
	"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
	"github.com/scylladb/go-set/b16set"
	"github.com/scylladb/go-set/i32set"
	"github.com/scylladb/go-set/i64set"
	"github.com/scylladb/go-set/strset"
	"github.com/sirupsen/logrus"
	"go.uber.org/atomic"
	"strings"
	"sync"
	"time"
)
var (
	emptyChunkData = make([]byte, 257)
	sessions, nameToUUID sync.Map
)
type Session struct {
	*translator
	conn *minecraft.Conn
	hMutex sync.RWMutex
	h Handler
	serverMu       sync.RWMutex
	server         *server.Server
	serverConn     *minecraft.Conn
	tempServerConn *minecraft.Conn
	entities    *i64set.Set
	playerList  *b16set.Set
	effects     *i32set.Set
	bossBars    *i64set.Set
	scoreboards *strset.Set
	uuid uuid.UUID
	transferring atomic.Bool
	postTransfer atomic.Bool
	once         sync.Once
}
func All() []*Session {
	var s []*Session
	sessions.Range(func(_, v interface{}) bool {
		s = append(s, v.(*Session))
		return true
	})
	return s
}
func Lookup(v uuid.UUID) (*Session, bool) {
	s, ok := sessions.Load(v)
	if !ok {
		return nil, false
	}
	return s.(*Session), true
}
func LookupByName(name string) (*Session, bool) {
	v, ok := nameToUUID.Load(strings.ToLower(name))
	if !ok {
		return nil, false
	}
	return Lookup(v.(uuid.UUID))
}
func New(conn *minecraft.Conn) (_ *Session, err error) {
	s := &Session{
		conn: conn,
		entities:    i64set.New(),
		playerList:  b16set.New(),
		effects:     i32set.New(),
		bossBars:    i64set.New(),
		scoreboards: strset.New(),
		h:    NopHandler{},
		uuid: uuid.MustParse(conn.IdentityData().Identity),
	}
	sessions.Store(s.uuid, s)
	nameToUUID.Store(strings.ToLower(conn.IdentityData().DisplayName), s.uuid)
	defer func() {
		if err != nil {
			sessions.Delete(s.uuid)
			nameToUUID.Delete(strings.ToLower(conn.IdentityData().DisplayName))
		}
	}()
	srv := LoadBalancer()(s)
	if srv == nil {
		return nil, errors.New("load balancer did not return a server for the player to join")
	}
	s.server = srv
	srvConn, err := s.dial(srv)
	if err != nil {
		return nil, err
	}
	s.serverConn = srvConn
	if err = s.login(); err != nil {
		_ = srvConn.Close()
		return nil, err
	}
	s.translator = newTranslator(conn.GameData())
	handlePackets(s)
	srv.IncrementPlayerCount()
	query.IncrementPlayerCount()
	return s, nil
}
func (s *Session) dial(srv *server.Server) (*minecraft.Conn, error) {
	i := s.conn.IdentityData()
	i.XUID = ""
	return minecraft.Dialer{
		ClientData:   s.conn.ClientData(),
		IdentityData: i,
	}.Dial("raknet", srv.Address())
}
func (s *Session) login() (err error) {
	var g sync.WaitGroup
	g.Add(2)
	go func() {
		err = s.conn.StartGameTimeout(s.ServerConn().GameData(), time.Minute)
		g.Done()
	}()
	go func() {
		err = s.ServerConn().DoSpawnTimeout(time.Minute)
		g.Done()
	}()
	g.Wait()
	return
}
func (s *Session) Conn() *minecraft.Conn {
	return s.conn
}
func (s *Session) Server() *server.Server {
	s.serverMu.RLock()
	defer s.serverMu.RUnlock()
	return s.server
}
func (s *Session) ServerConn() *minecraft.Conn {
	s.serverMu.RLock()
	defer s.serverMu.RUnlock()
	return s.serverConn
}