move some stuff and add registercritical

This commit is contained in:
adman
2026-03-19 22:28:20 +01:00
parent 8c6172dcda
commit abc0f6aebb
7 changed files with 113 additions and 57 deletions
+1 -48
View File
@@ -7,7 +7,6 @@ import (
"io"
"log/slog"
"reflect"
"slices"
"sync"
"github.com/admin-else/strom/data"
@@ -60,54 +59,8 @@ type Conn struct {
packetCh chan proto_base.EncodeDecodeAble
}
func (c *Conn) RegisterUntilLatest(h any) {
c.RegisterUntil(h, LatestVersion)
}
func (c *Conn) RegisterUntil(h any, until string) {
hv, eventType := event.ValidateHandler(h)
c.RegisterDirect(eventType, hv)
if !eventType.Implements(reflect.TypeFor[proto_base.EncodeDecodeAble]()) {
panic("expected method with argument that implements proto_base.EncodeDecodeAble")
}
packetInfo, found := LookupPacketInfoByType(reflect.Zero(eventType).Interface().(proto_base.EncodeDecodeAble))
if !found {
panic("packet not found")
}
versionInfo, err := data.LookUpVersionByProtocolVersion(packetInfo.ProtocolVersion)
if err != nil {
panic("protocol version not found")
}
startIndex := slices.Index(proto_generated.SupportedVersions, versionInfo.MinecraftVersion)
endIndex := slices.Index(proto_generated.SupportedVersions, until)
for i := startIndex + 1; i <= endIndex; i++ {
versionName := proto_generated.SupportedVersions[i]
versionInfo, err = data.LookUpVersionByName(versionName)
if err != nil {
panic("protocol version not found")
}
var newPacketInfo proto_base.PacketInfo
newPacketInfo, found = LookupPacketInfoByNameProtocolVersionAndState(packetInfo.Name, versionInfo.Version, packetInfo.State)
if !found {
panic("packet not found")
}
newT := reflect.TypeOf(newPacketInfo.Type)
if !SmartConvertibleTo(newT, reflect.TypeOf(packetInfo.Type)) {
panic(fmt.Sprintf("packet %v is not convertible to %v", newT, reflect.TypeOf(packetInfo.Type)))
}
handleFunc := func(packet any) error {
v := hv.Call([]reflect.Value{SmartConvert(reflect.ValueOf(packet), reflect.TypeOf(packetInfo.Type))})[0]
if v.IsNil() {
return nil
}
return v.Interface().(error)
}
c.RegisterDirect(newT, reflect.ValueOf(handleFunc))
}
}
func (c *Conn) OnStart() (err error) {
c.Register(c.OnTick)
c.RegisterCritical(c.OnTick)
return c.handler.OnStart()
}
+79
View File
@@ -1,7 +1,14 @@
package proto
import (
"fmt"
"reflect"
"slices"
"github.com/admin-else/strom/data"
"github.com/admin-else/strom/event"
"github.com/admin-else/strom/proto_base"
"github.com/admin-else/strom/proto_generated"
)
func SmartConvertibleTo(from, to reflect.Type) bool {
@@ -40,3 +47,75 @@ func SmartConvert(from reflect.Value, to reflect.Type) (ret reflect.Value) {
return from.Convert(to)
}
}
// RegisterUntilLatest registers a handler for all versions between the passed in packet version and the latest supported version.
// Warning: If a bad handler is passed in, the program will panic.
func (c *Conn) RegisterUntilLatest(h any) {
c.registerUntil(h, LatestVersion, false)
}
// RegisterUntil registers a handler for all versions between the passed in packet version and the specified version.
// Warning: If a bad handler is passed in, the program will panic.
func (c *Conn) RegisterUntil(h any, until string) {
c.registerUntil(h, until, false)
}
// RegisterCriticalUntilLatest registers a handler for all versions between the passed in packet version and the latest supported version.
// If this handler returns an error, the connection will be closed.
// Warning: If a bad handler is passed in, the program will panic.
func (c *Conn) RegisterCriticalUntilLatest(h any) {
c.registerUntil(h, LatestVersion, true)
}
// RegisterCriticalUntil registers a handler for all versions between the passed in packet version and the specified version.
// If this handler returns an error, the connection will be closed.
// Warning: If a bad handler is passed in, the program will panic.
func (c *Conn) RegisterCriticalUntil(h any, until string) {
c.registerUntil(h, until, true)
}
func (c *Conn) registerUntil(h any, until string, critical bool) {
eventType, hv := event.ValidateHandler(h)
c.RegisterDirect(eventType, hv)
if !eventType.Implements(reflect.TypeFor[proto_base.EncodeDecodeAble]()) {
panic("expected method with argument that implements proto_base.EncodeDecodeAble")
}
packetInfo, found := LookupPacketInfoByType(reflect.Zero(eventType).Interface().(proto_base.EncodeDecodeAble))
if !found {
panic("packet not found")
}
versionInfo, err := data.LookUpVersionByProtocolVersion(packetInfo.ProtocolVersion)
if err != nil {
panic("protocol version not found")
}
startIndex := slices.Index(proto_generated.SupportedVersions, versionInfo.MinecraftVersion)
endIndex := slices.Index(proto_generated.SupportedVersions, until)
for i := startIndex + 1; i <= endIndex; i++ {
versionName := proto_generated.SupportedVersions[i]
versionInfo, err = data.LookUpVersionByName(versionName)
if err != nil {
panic("protocol version not found")
}
var newPacketInfo proto_base.PacketInfo
newPacketInfo, found = LookupPacketInfoByNameProtocolVersionAndState(packetInfo.Name, versionInfo.Version, packetInfo.State)
if !found {
panic("packet not found")
}
newT := reflect.TypeOf(newPacketInfo.Type)
if !SmartConvertibleTo(newT, reflect.TypeOf(packetInfo.Type)) {
panic(fmt.Sprintf("packet %v is not convertible to %v", newT, reflect.TypeOf(packetInfo.Type)))
}
handleFunc := func(packet any) error {
v := hv.Call([]reflect.Value{SmartConvert(reflect.ValueOf(packet), reflect.TypeOf(packetInfo.Type))})[0]
if v.IsNil() {
return nil
}
return v.Interface().(error)
}
if critical {
c.RegisterCustomType(newT, reflect.ValueOf(handleFunc))
} else {
c.RegisterDirect(newT, reflect.ValueOf(handleFunc))
}
}
}