func WithinWorld(x, y int) bool {
	return x <= MaxX && x >= 0 && y >= 0 && y <= MaxY
}
IsValid Returns true if the tile at x,y is within world boundaries, false otherwise.
package world
import (
	"math"
	"sync"
	"time"
	"github.com/spkaeros/rscgo/pkg/isaac"
	"github.com/spkaeros/rscgo/pkg/tasks"
	"github.com/spkaeros/rscgo/pkg/game/entity"
	"github.com/spkaeros/rscgo/pkg/log"
	rscRand "github.com/spkaeros/rscgo/pkg/rand"
)
const (
	TicksDay         = 135000
	TicksHour        = 5625
	TicksTwentyMin   = 1875
	TicksMinute      = 100
	TickMinute       = TicksMinute * TickMillis
	TickHour         = TicksHour * TickMillis
	TickDay          = TicksDay * TickMillis
	TickMillis       = 640 * time.Millisecond
	ClientTickMillis = TickMillis >> 5
	MaxX = 944
	MaxY = 944 * 4  
)
func CurrentTick() int {
	return int(tasks.Ticks.Load())
}
const (
	RegionSize = 48
	HorizontalPlanes = MaxX/RegionSize + 1
	VerticalPlanes = MaxY/RegionSize + 1
	LowerBound = RegionSize / 2
)
var UpdateTime time.Time
type indexQueue []int
func (q *indexQueue) Push(i int) {
	*q = append([]int{i}, *q...)
}
func (q *indexQueue) Pop() int {
	if len(*q) <= 0 {
		return -1
	}
	idx := (*q)[0]
	if len(*q) == 1 {
		*q = (*q)[:0]
	} else {
		*q = (*q)[1:]
	}
	return idx
}
type PlayersList map[*Player]struct{}
type PlayerList struct {
	sync.RWMutex
	PlayersList
	free   indexQueue
	curIdx int
}
var Players = &PlayerList{free: make(indexQueue, 0, 1250), PlayersList: make(PlayersList)}
func (m *PlayerList) FindHash(hash uint64) (*Player, bool) {
	m.RLock()
	defer m.RUnlock()
	for player := range m.PlayersList {
		if player.UsernameHash() == hash {
			return player, true
		}
	}
	return nil, false
}
func (m *PlayerList) FindIndex(index int) (*Player, bool) {
	if index < 0 {
		return nil, false
	}
	m.RLock()
	defer m.RUnlock()
	for player := range m.PlayersList {
		if player.ServerIndex() == index {
			return player, true
		}
	}
	return nil, false
}
func (m *PlayerList) Find(player *Player) int {
	return m.ForEach(func(p *Player) bool {
		return p == player
	})
}
func (m *PlayerList) Contains(player *Player) bool {
	return m.Find(player) > -1
}
func (m *PlayerList) ContainsHash(hash uint64) bool {
	_, ret := m.FindHash(hash)
	return ret
}
func (m *PlayerList) Put(player *Player) {
	if m.Contains(player) {
		log.Warn("Player list double-entry attempted!")
		return
	}
	player.SetServerIndex(m.nextSlot())
	m.Lock()
	defer m.Unlock()
	m.PlayersList[player] = struct{}{} 
}
func (m *PlayerList) Remove(player *Player) {
	slot := player.ServerIndex()
	if slot == -1 {
		log.Warn("Error: Player with non-valid index being removed!")
		return
	}
	player.SetServerIndex(-1)
	m.Lock()
	defer m.Unlock()
	delete(m.PlayersList, player)
	m.free.Push(slot)
}
func (m *PlayerList) Range(action func(*Player)) {
	m.RLock()
	defer m.RUnlock()
	for p := range m.PlayersList {
		if p != nil {
			action(p)
		}
	}
}
func (m *PlayerList) ForEach(action func(*Player) bool) int {
	m.RLock()
	defer m.RUnlock()
	for p := range m.PlayersList {
		if p != nil {
			if action(p) {
				return p.ServerIndex()
			}
		}
	}
	return -1
}
func (m *PlayerList) Size() int {
	m.RLock()
	defer m.RUnlock()
	return len(m.PlayersList)
}
func (m *PlayerList) nextSlot() int {
	m.Lock()
	defer m.Unlock()
	idx := m.free.Pop()
	if idx == -1 {
		defer func() { m.curIdx += 1 }()
		return m.curIdx
	}
	return idx
}
func (m *PlayerList) Set() []*Player {
	keys := make([]*Player, m.Size())
	i := 0
	for k := range m.PlayersList {
	    keys[i] = k
	    i++
	}
	return keys
}
func (m *PlayerList) AsyncRange(fn func(*Player)) {
	m.RLock()
	sz := len(m.PlayersList)
	done := make(chan struct{}, sz)
	for player := range m.PlayersList {
		go func(player *Player) {
			fn(player)
			done <- struct{}{}
		}(player)
	}
	m.RUnlock()
	defer close(done)
	for i := 0; i < sz; i += 1 {
		select {
		case _, ok := <-done:
			if !ok {
				log.Debug("premature AsyncRange done-signal")
				break
			}
			continue
		}
	}
}
type region struct {
	x       int
	y       int
	Players *MobList
	NPCs    *MobList
	Objects *entityList
	Items   *entityList
}
var regions [HorizontalPlanes][VerticalPlanes]*region