Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f758a10575 | ||
|
|
41d1ab4c45 | ||
|
|
032fa26927 |
+10
-5
@@ -53,6 +53,7 @@ type BlockState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var BlocksCache = make(map[string][]*Block)
|
var BlocksCache = make(map[string][]*Block)
|
||||||
|
var BlocksCacheIdMap = make(map[string]map[int32]*Block)
|
||||||
|
|
||||||
func BlocksForVersion(v string) (ret []*Block) {
|
func BlocksForVersion(v string) (ret []*Block) {
|
||||||
var ok bool
|
var ok bool
|
||||||
@@ -66,13 +67,17 @@ func BlocksForVersion(v string) (ret []*Block) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func LookupBlockByStateId(version string, stateId int32) (block *Block, ok bool) {
|
func LookupBlockByStateId(version string, stateId int32) (block *Block, ok bool) {
|
||||||
for _, b := range BlocksForVersion(version) {
|
idmap, found := BlocksCacheIdMap[version]
|
||||||
if b.MinStateId <= stateId && stateId <= b.MaxStateId {
|
if !found {
|
||||||
block = b
|
idmap = make(map[int32]*Block)
|
||||||
ok = true
|
for _, b := range BlocksForVersion(version) {
|
||||||
return
|
for i := range b.MaxStateId - b.MinStateId + 1 {
|
||||||
|
idmap[b.MinStateId+i] = b
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BlocksCacheIdMap[version] = idmap
|
||||||
}
|
}
|
||||||
|
block, ok = idmap[stateId]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package data
|
package data
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// "id": 2,
|
// "id": 2,
|
||||||
// "name": "granite",
|
// "name": "granite",
|
||||||
@@ -15,15 +17,21 @@ type Item struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ItemsCache = make(map[string][]*Item)
|
var ItemsCache = make(map[string][]*Item)
|
||||||
|
var ItemsCacheMutex = &sync.RWMutex{}
|
||||||
|
|
||||||
func ItemsForVersion(v string) (ret []*Item) {
|
func ItemsForVersion(v string) (ret []*Item) {
|
||||||
var ok bool
|
var ok bool
|
||||||
|
ItemsCacheMutex.RLock()
|
||||||
if ret, ok = ItemsCache[v]; ok {
|
if ret, ok = ItemsCache[v]; ok {
|
||||||
|
ItemsCacheMutex.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
ItemsCacheMutex.RUnlock()
|
||||||
var b []*Item
|
var b []*Item
|
||||||
must(LoadVersionedJson(v, "items", &b))
|
must(LoadVersionedJson(v, "items", &b))
|
||||||
|
ItemsCacheMutex.Lock()
|
||||||
ItemsCache[v] = b
|
ItemsCache[v] = b
|
||||||
|
ItemsCacheMutex.Unlock()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-7
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LoopsPerSecond = 100 // i dunno seems reasonable
|
LoopsPerSecond = 10000 // this is just so the cpu doesn't burn itself in an unlimited infinite loop
|
||||||
TimePerLoop = time.Second / LoopsPerSecond
|
TimePerLoop = time.Second / LoopsPerSecond
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,16 +35,16 @@ type (
|
|||||||
Tick struct{}
|
Tick struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandlerDoneErr will stop the event loop and return the error if provided.
|
|
||||||
type HandlerDoneErr struct {
|
|
||||||
Return error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close is fired when the loop shuts down.
|
// Close is fired when the loop shuts down.
|
||||||
type Close struct {
|
type Close struct {
|
||||||
Reason error
|
Reason error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandlerDoneErr will stop the event loop and return the error if provided.
|
||||||
|
type HandlerDoneErr struct {
|
||||||
|
Return error
|
||||||
|
}
|
||||||
|
|
||||||
func (e HandlerDoneErr) Error() string {
|
func (e HandlerDoneErr) Error() string {
|
||||||
return "HandlerDoneErr"
|
return "HandlerDoneErr"
|
||||||
}
|
}
|
||||||
@@ -53,12 +53,26 @@ func (e HandlerDoneErr) Unwrap() error {
|
|||||||
return e.Return
|
return e.Return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MainHandlerErr is a special error used to tell the event loop that the main loop has exited
|
||||||
|
type MainHandlerErr struct {
|
||||||
|
Return error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MainHandlerErr) Error() string {
|
||||||
|
return "MainHandlerErr"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e MainHandlerErr) Unwrap() error {
|
||||||
|
return e.Return
|
||||||
|
}
|
||||||
|
|
||||||
// DontForwardErr will stop the event from being forwarded to other handlers, including anything handlers.
|
// DontForwardErr will stop the event from being forwarded to other handlers, including anything handlers.
|
||||||
var DontForwardErr = errors.New("dont forward")
|
var DontForwardErr = errors.New("dont forward")
|
||||||
var WhileClosingErr = errors.New("error while closing")
|
var WhileClosingErr = errors.New("error while closing")
|
||||||
|
|
||||||
// CloseNonCriticalErr will close even when the event is non-critical
|
// CloseNonCriticalErr will close even when the event is non-critical
|
||||||
var CloseNonCriticalErr = errors.New("close non-critical")
|
var CloseNonCriticalErr = errors.New("close non-critical")
|
||||||
|
var ContextDoneErr = errors.New("context done")
|
||||||
|
|
||||||
func ValidateHandler(h any) (eventType reflect.Type, hv reflect.Value) {
|
func ValidateHandler(h any) (eventType reflect.Type, hv reflect.Value) {
|
||||||
hv = reflect.ValueOf(h)
|
hv = reflect.ValueOf(h)
|
||||||
@@ -146,6 +160,15 @@ func (l *Loop) Fire(event any) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Loop) OnTick(_ Tick) (err error) {
|
||||||
|
select {
|
||||||
|
case <-l.Ctx.Done():
|
||||||
|
err = ContextDoneErr
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Loop) startLoop() (err error) {
|
func (l *Loop) startLoop() (err error) {
|
||||||
_ = *l // exit early on nil loop
|
_ = *l // exit early on nil loop
|
||||||
for {
|
for {
|
||||||
@@ -168,10 +191,17 @@ func (l *Loop) startLoop() (err error) {
|
|||||||
|
|
||||||
func (l *Loop) StartLoop() (err error) {
|
func (l *Loop) StartLoop() (err error) {
|
||||||
go func() {
|
go func() {
|
||||||
l.ErrChan <- l.startLoop()
|
l.ErrChan <- MainHandlerErr{l.startLoop()}
|
||||||
}()
|
}()
|
||||||
err = <-l.ErrChan
|
err = <-l.ErrChan
|
||||||
l.cancel()
|
l.cancel()
|
||||||
|
errMaybe := MainHandlerErr{}
|
||||||
|
if errors.As(err, &errMaybe) {
|
||||||
|
err = errors.Unwrap(err)
|
||||||
|
} else {
|
||||||
|
for !errors.Is(<-l.ErrChan, MainHandlerErr{}) {
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/admin-else/strom/data"
|
"github.com/admin-else/strom/data"
|
||||||
"github.com/admin-else/strom/level"
|
"github.com/admin-else/strom/level"
|
||||||
@@ -42,10 +43,9 @@ type Region struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Region) GetBlockAt(x, y, z int32) (name string, properties map[string]string, err error) {
|
func (r *Region) GetBlockAt(x, y, z int32) (name string, properties map[string]string, err error) {
|
||||||
uintSlice := make([]uint64, len(r.BlockStates))
|
|
||||||
for i, v := range r.BlockStates {
|
// this is probably fine
|
||||||
uintSlice[i] = uint64(v)
|
uintSlice := unsafe.Slice((*uint64)(unsafe.Pointer(unsafe.SliceData(r.BlockStates))), len(r.BlockStates))
|
||||||
}
|
|
||||||
if r.Size.X < 0 {
|
if r.Size.X < 0 {
|
||||||
r.Size.X *= -1
|
r.Size.X *= -1
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ func (r *Region) GetBlockAt(x, y, z int32) (name string, properties map[string]s
|
|||||||
r.Size.Z *= -1
|
r.Size.Z *= -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if x >= r.Size.X || y >= r.Size.Y || z >= r.Size.Z {
|
if x >= r.Size.X || y >= r.Size.Y || z >= r.Size.Z || x < 0 || y < 0 || z < 0 {
|
||||||
err = OutOfBoundsErr
|
err = OutOfBoundsErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-5
@@ -2,6 +2,7 @@ package proto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -19,7 +20,6 @@ var (
|
|||||||
BadPacketTypeErr = errors.New("bad packet type")
|
BadPacketTypeErr = errors.New("bad packet type")
|
||||||
BadPacketIdErr = errors.New("bad packet id")
|
BadPacketIdErr = errors.New("bad packet id")
|
||||||
PacketNotFullyDecodedErr = errors.New("packet not fully decoded")
|
PacketNotFullyDecodedErr = errors.New("packet not fully decoded")
|
||||||
ContextDoneErr = errors.New("context done")
|
|
||||||
WrongStateErr = errors.New("wrong state")
|
WrongStateErr = errors.New("wrong state")
|
||||||
WrongDirectionErr = errors.New("wrong direction")
|
WrongDirectionErr = errors.New("wrong direction")
|
||||||
CantTranslateErr = errors.New("cant translate packet")
|
CantTranslateErr = errors.New("cant translate packet")
|
||||||
@@ -222,11 +222,10 @@ func (c *Conn) OnTick(_ event.Tick) (err error) {
|
|||||||
if c.receiveRoutine {
|
if c.receiveRoutine {
|
||||||
select {
|
select {
|
||||||
case packet = <-c.packetCh:
|
case packet = <-c.packetCh:
|
||||||
slog.Debug("receive", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
|
if slog.Default().Enabled(context.Background(), slog.LevelDebug) {
|
||||||
|
slog.Debug("receive", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
|
||||||
|
}
|
||||||
err = c.Loop.Fire(packet)
|
err = c.Loop.Fire(packet)
|
||||||
case <-c.Ctx.Done():
|
|
||||||
err = ContextDoneErr
|
|
||||||
return
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import "math/rand/v2"
|
||||||
|
|
||||||
|
func ShuffleSlice[T any](s []T) (ret []T) {
|
||||||
|
rand.Shuffle(len(s), func(i, j int) { s[i], s[j] = s[j], s[i] })
|
||||||
|
return s
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user