version compat system start
This commit is contained in:
+81
-24
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/admin-else/strom/data"
|
||||
@@ -13,10 +14,16 @@ import (
|
||||
"github.com/admin-else/strom/proto_base"
|
||||
)
|
||||
|
||||
var BadPacketTypeError = errors.New("bad packet type")
|
||||
var BadPacketIdError = errors.New("bad packet id")
|
||||
var PacketNotFullyDecodedError = errors.New("packet not fully decoded")
|
||||
var ErrContextDone = errors.New("context done")
|
||||
var (
|
||||
BadPacketTypeErr = errors.New("bad packet type")
|
||||
BadPacketIdErr = errors.New("bad packet id")
|
||||
PacketNotFullyDecodedErr = errors.New("packet not fully decoded")
|
||||
ContextDoneErr = errors.New("context done")
|
||||
WrongStateErr = errors.New("wrong state")
|
||||
WrongDirectionErr = errors.New("wrong direction")
|
||||
CantTranslateErr = errors.New("cant translate packet")
|
||||
PacketDoesntExistInFutureVersionErr = errors.New("packet doesnt exist in future version")
|
||||
)
|
||||
|
||||
// UnCodablePacket represents a packet that could not be decoded.
|
||||
type UnCodablePacket struct {
|
||||
@@ -77,42 +84,92 @@ func (c *Conn) State() proto_base.State {
|
||||
}
|
||||
|
||||
func (c *Conn) SetVersion(version string) (err error) {
|
||||
c.Version = version
|
||||
versionData, err := data.LookUpVersionByName(c.Version)
|
||||
versionData, err := data.LookUpVersionByName(version)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.ProtocolVersion = versionData.Version
|
||||
c.Version = version
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Conn) SetProtocolVersion(version int32) (err error) {
|
||||
versionData, err := data.LookUpVersionByProtocolVersion(version)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.ProtocolVersion = versionData.Version
|
||||
c.Version = versionData.MinecraftVersion
|
||||
return
|
||||
}
|
||||
|
||||
// ActivateReceiveRoutine activates the receive-routine.
|
||||
// It ensures that the receive-routine is only started once and creates a buffered channel for packet handling.
|
||||
func (c *Conn) ActivateReceiveRoutine() {
|
||||
if c.receiveRoutine {
|
||||
return
|
||||
}
|
||||
c.receiveRoutine = true
|
||||
c.packetCh = make(chan proto_base.EncodeDecodeAble, 100) // i dunno how many to buffer 100 seems reasonable
|
||||
go c.ReceiveJob()
|
||||
}
|
||||
|
||||
func (c *Conn) translatePacketVersion(packet proto_base.EncodeDecodeAble, packetInfo proto_base.PacketInfo) (convertedPacket proto_base.EncodeDecodeAble, err error) {
|
||||
packetInfoReal, found := LookupPacketInfoByNameProtocolVersionAndState(packetInfo.Name, c.ProtocolVersion, c.State())
|
||||
if !found {
|
||||
err = PacketDoesntExistInFutureVersionErr
|
||||
return
|
||||
}
|
||||
dstType := reflect.TypeOf(packetInfoReal.Type)
|
||||
if !reflect.TypeOf(packetInfo.Type).ConvertibleTo(dstType) {
|
||||
err = CantTranslateErr
|
||||
return
|
||||
}
|
||||
// can't fail cause pacetinfo.type is proto_base.EncodeDecodeAble
|
||||
convertedPacket = reflect.ValueOf(packet).Convert(dstType).Interface().(proto_base.EncodeDecodeAble)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Conn) sendRegisteredPacket(packet proto_base.EncodeDecodeAble) (err error) {
|
||||
i, ok := LookupPacketInfoByTypeAndState(packet, c.State())
|
||||
if !ok {
|
||||
err = BadPacketTypeErr
|
||||
return
|
||||
}
|
||||
if i.Direction != c.Actor.SendDirection() {
|
||||
err = WrongDirectionErr
|
||||
return
|
||||
}
|
||||
if i.State != c.State() {
|
||||
err = WrongStateErr
|
||||
return
|
||||
}
|
||||
if i.ProtocolVersion != c.ProtocolVersion {
|
||||
packet, err = c.translatePacketVersion(packet, i)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
var packetBuff = bytes.NewBuffer(nil)
|
||||
err = proto_base.EncodeVarInt(packetBuff, i.PacketId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = packet.Encode(packetBuff)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
slog.Debug("send", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
|
||||
return c.SendRaw(packetBuff.Bytes())
|
||||
}
|
||||
|
||||
func (c *Conn) Send(packet proto_base.EncodeDecodeAble) (err error) {
|
||||
slog.Debug("send", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
|
||||
switch packet := packet.(type) {
|
||||
case *UnCodablePacket:
|
||||
err = c.SendRaw(packet.Data)
|
||||
default:
|
||||
i, ok := LookupPacketInfoByTypeLookupPacketInfoByTypeAndMore(packet, c.State())
|
||||
if !ok {
|
||||
err = BadPacketTypeError
|
||||
}
|
||||
var packetBuff = bytes.NewBuffer(nil)
|
||||
err = proto_base.EncodeVarInt(packetBuff, i.PacketId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = packet.Encode(packetBuff)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = c.SendRaw(packetBuff.Bytes())
|
||||
return c.sendRegisteredPacket(packet)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -129,7 +186,7 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
|
||||
}
|
||||
packet, ok := LookUpTypeByPacketInfoAndCopyType(c.Actor.ReceiveDirection(), c.State(), id, c.ProtocolVersion)
|
||||
if !ok {
|
||||
packet = &UnCodablePacket{Err: BadPacketIdError, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
||||
packet = &UnCodablePacket{Err: BadPacketIdErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
||||
return
|
||||
}
|
||||
err = packet.Decode(b)
|
||||
@@ -140,7 +197,7 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
|
||||
}
|
||||
if b.Len() != 0 {
|
||||
err = nil
|
||||
packet = &UnCodablePacket{Err: PacketNotFullyDecodedError, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
||||
packet = &UnCodablePacket{Err: PacketNotFullyDecodedErr, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
||||
return
|
||||
}
|
||||
return
|
||||
@@ -154,7 +211,7 @@ func (c *Conn) OnTick(_ event.Tick) (err error) {
|
||||
slog.Debug("receive", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet))
|
||||
err = c.Loop.Fire(packet)
|
||||
case <-c.Ctx.Done():
|
||||
err = ErrContextDone
|
||||
err = ContextDoneErr
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
+13
-16
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/admin-else/strom/proto_generated"
|
||||
)
|
||||
|
||||
// I know this is in-performant and i dont care until it becomes a problem for somebody it will stay like this and it is pretty easy to make caches or simular to speed this up so yeah
|
||||
// I know this is in-performant and i dont care until it becomes a problem for somebody it will stay like this and it is pretty easy to make caches or similar to speed this up so yeah
|
||||
|
||||
func LookUpTypeByPacketInfo(direction proto_base.Direction, state proto_base.State, pid, version int32) (p proto_base.PacketInfo, ok bool) {
|
||||
for _, pin := range proto_generated.Packets {
|
||||
@@ -50,22 +50,19 @@ func LookupPacketInfoByType(packet proto_base.EncodeDecodeAble) (p proto_base.Pa
|
||||
return
|
||||
}
|
||||
|
||||
func LookupPacketInfoByTypeLookupPacketInfoByTypeAndMore(packet proto_base.EncodeDecodeAble, state proto_base.State) (p proto_base.PacketInfo, ok bool) {
|
||||
switch packet := packet.(type) {
|
||||
case *UnCodablePacket:
|
||||
p = proto_base.PacketInfo{
|
||||
Type: &UnCodablePacket{},
|
||||
Name: "undecodeable",
|
||||
Direction: packet.Direction,
|
||||
State: -1,
|
||||
PacketId: -1,
|
||||
ProtocolVersion: -1,
|
||||
func LookupPacketInfoByTypeAndState(packet proto_base.EncodeDecodeAble, state proto_base.State) (p proto_base.PacketInfo, ok bool) {
|
||||
for _, p := range proto_generated.Packets {
|
||||
if state == p.State && reflect.TypeOf(p.Type) == reflect.TypeOf(packet) {
|
||||
return p, true
|
||||
}
|
||||
default:
|
||||
for _, p := range proto_generated.Packets {
|
||||
if state == p.State && reflect.TypeOf(p.Type) == reflect.TypeOf(packet) {
|
||||
return p, true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func LookupPacketInfoByNameProtocolVersionAndState(name string, version int32, state proto_base.State) (p proto_base.PacketInfo, ok bool) {
|
||||
for _, p := range proto_generated.Packets {
|
||||
if state == p.State && p.Name == name && p.ProtocolVersion == version {
|
||||
return p, true
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user