Add registry implement
This commit is contained in:
@ -53,6 +53,7 @@ func (c *Client) Close() error {
|
|||||||
func NewClient() *Client {
|
func NewClient() *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
Auth: Auth{Name: "Steve"},
|
Auth: Auth{Name: "Steve"},
|
||||||
|
Registries: registry.NewNetworkCodec(),
|
||||||
Events: Events{handlers: make([][]PacketHandler, packetid.ClientboundPacketIDGuard)},
|
Events: Events{handlers: make([][]PacketHandler, packetid.ClientboundPacketIDGuard)},
|
||||||
LoginPlugin: make(map[string]CustomPayloadHandler),
|
LoginPlugin: make(map[string]CustomPayloadHandler),
|
||||||
ConfigHandler: NewDefaultConfigHandler(),
|
ConfigHandler: NewDefaultConfigHandler(),
|
||||||
|
@ -3,11 +3,11 @@ package bot
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
"github.com/Tnze/go-mc/nbt"
|
|
||||||
"github.com/Tnze/go-mc/net"
|
"github.com/Tnze/go-mc/net"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
)
|
)
|
||||||
@ -141,12 +141,7 @@ func (c *Client) joinConfiguration(conn *net.Conn) error {
|
|||||||
|
|
||||||
case packetid.ClientboundConfigRegistryData:
|
case packetid.ClientboundConfigRegistryData:
|
||||||
const ErrStage = "registry"
|
const ErrStage = "registry"
|
||||||
// err := p.Scan(pk.NBT(&c.ConfigData.Registries))
|
|
||||||
// if err != nil {
|
|
||||||
// return ConfigErr{"registry data", err}
|
|
||||||
// }
|
|
||||||
var registryID pk.Identifier
|
var registryID pk.Identifier
|
||||||
var length pk.VarInt
|
|
||||||
|
|
||||||
r := bytes.NewReader(p.Data)
|
r := bytes.NewReader(p.Data)
|
||||||
_, err := registryID.ReadFrom(r)
|
_, err := registryID.ReadFrom(r)
|
||||||
@ -154,40 +149,15 @@ func (c *Client) joinConfiguration(conn *net.Conn) error {
|
|||||||
return ConfigErr{ErrStage, err}
|
return ConfigErr{ErrStage, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = length.ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return ConfigErr{ErrStage, err}
|
|
||||||
}
|
|
||||||
|
|
||||||
registry := c.Registries.Registry(string(registryID))
|
registry := c.Registries.Registry(string(registryID))
|
||||||
if registry == nil {
|
if registry == nil {
|
||||||
return ConfigErr{ErrStage, errors.New("unknown registry: " + string(registryID))}
|
return ConfigErr{ErrStage, errors.New("unknown registry: " + string(registryID))}
|
||||||
}
|
}
|
||||||
|
fmt.Println(registry)
|
||||||
|
|
||||||
for i := 0; i < int(length); i++ {
|
_, err = registry.(pk.FieldDecoder).ReadFrom(r)
|
||||||
var entryId pk.Identifier
|
|
||||||
var hasData pk.Boolean
|
|
||||||
var data nbt.RawMessage
|
|
||||||
_, err = entryId.ReadFrom(r)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ConfigErr{ErrStage, err}
|
return ConfigErr{ErrStage, fmt.Errorf("failed to read registry %s: %w", registryID, err)}
|
||||||
}
|
|
||||||
|
|
||||||
_, err = hasData.ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return ConfigErr{ErrStage, err}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hasData {
|
|
||||||
_, err = pk.NBT(&data).ReadFrom(r)
|
|
||||||
if err != nil {
|
|
||||||
return ConfigErr{ErrStage, err}
|
|
||||||
}
|
|
||||||
err = registry.InsertWithNBT(string(entryId), data)
|
|
||||||
if err != nil {
|
|
||||||
return ConfigErr{ErrStage, err}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case packetid.ClientboundConfigResourcePackPop:
|
case packetid.ClientboundConfigResourcePackPop:
|
||||||
|
@ -88,7 +88,7 @@ func (m *Manager) handlePlayerChat(packet pk.Packet) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return InvalidChatPacket{ErrUnknownPlayer}
|
return InvalidChatPacket{ErrUnknownPlayer}
|
||||||
}
|
}
|
||||||
ct := m.c.Registries.ChatType.FindByID(chatType.ID)
|
ct := m.c.Registries.ChatType.GetByID(chatType.ID)
|
||||||
if ct == nil {
|
if ct == nil {
|
||||||
return InvalidChatPacket{ErrUnknwonChatType}
|
return InvalidChatPacket{ErrUnknwonChatType}
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ func (m *Manager) handleDisguisedChat(packet pk.Packet) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ct := m.c.Registries.ChatType.FindByID(chatType.ID)
|
ct := m.c.Registries.ChatType.GetByID(chatType.ID)
|
||||||
if ct == nil {
|
if ct == nil {
|
||||||
return InvalidChatPacket{ErrUnknwonChatType}
|
return InvalidChatPacket{ErrUnknwonChatType}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ func (w *World) onPlayerSpawn(pk.Packet) error {
|
|||||||
|
|
||||||
func (w *World) handleLevelChunkWithLightPacket(packet pk.Packet) error {
|
func (w *World) handleLevelChunkWithLightPacket(packet pk.Packet) error {
|
||||||
var pos level.ChunkPos
|
var pos level.ChunkPos
|
||||||
currentDimType := w.c.Registries.DimensionType.FindByID(w.p.DimensionType)
|
currentDimType := w.c.Registries.DimensionType.GetByID(w.p.DimensionType)
|
||||||
if currentDimType == nil {
|
if currentDimType == nil {
|
||||||
return fmt.Errorf("dimension type %d not found", w.p.DimensionType)
|
return fmt.Errorf("dimension type %d not found", w.p.DimensionType)
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,22 @@ type NetworkCodec struct {
|
|||||||
JukeboxSong Registry[nbt.RawMessage] `registry:"minecraft:jukebox_song"`
|
JukeboxSong Registry[nbt.RawMessage] `registry:"minecraft:jukebox_song"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewNetworkCodec() NetworkCodec {
|
||||||
|
return NetworkCodec{
|
||||||
|
ChatType: NewRegistry[ChatType](),
|
||||||
|
DamageType: NewRegistry[DamageType](),
|
||||||
|
DimensionType: NewRegistry[Dimension](),
|
||||||
|
TrimMaterial: NewRegistry[nbt.RawMessage](),
|
||||||
|
TrimPattern: NewRegistry[nbt.RawMessage](),
|
||||||
|
WorldGenBiome: NewRegistry[nbt.RawMessage](),
|
||||||
|
Wolfvariant: NewRegistry[nbt.RawMessage](),
|
||||||
|
PaintingVariant: NewRegistry[nbt.RawMessage](),
|
||||||
|
BannerPattern: NewRegistry[nbt.RawMessage](),
|
||||||
|
Enchantment: NewRegistry[nbt.RawMessage](),
|
||||||
|
JukeboxSong: NewRegistry[nbt.RawMessage](),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type ChatType struct {
|
type ChatType struct {
|
||||||
Chat chat.Decoration `nbt:"chat"`
|
Chat chat.Decoration `nbt:"chat"`
|
||||||
Narration chat.Decoration `nbt:"narration"`
|
Narration chat.Decoration `nbt:"narration"`
|
||||||
@ -56,7 +72,7 @@ type Dimension struct {
|
|||||||
MonsterSpawnBlockLightLimit int32 `nbt:"monster_spawn_block_light_limit"`
|
MonsterSpawnBlockLightLimit int32 `nbt:"monster_spawn_block_light_limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *NetworkCodec) Registry(id string) RegistryHandler {
|
func (c *NetworkCodec) Registry(id string) any {
|
||||||
codecVal := reflect.ValueOf(c).Elem()
|
codecVal := reflect.ValueOf(c).Elem()
|
||||||
codecTyp := codecVal.Type()
|
codecTyp := codecVal.Type()
|
||||||
numField := codecVal.NumField()
|
numField := codecVal.NumField()
|
||||||
@ -66,12 +82,8 @@ func (c *NetworkCodec) Registry(id string) RegistryHandler {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if registryID == id {
|
if registryID == id {
|
||||||
return codecVal.Field(i).Addr().Interface().(RegistryHandler)
|
return codecVal.Field(i).Addr().Interface()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegistryHandler interface {
|
|
||||||
InsertWithNBT(name string, data nbt.RawMessage) error
|
|
||||||
}
|
|
||||||
|
46
registry/network.go
Normal file
46
registry/network.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package registry
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (reg *Registry[E]) ReadFrom(r io.Reader) (int64, error) {
|
||||||
|
var length pk.VarInt
|
||||||
|
|
||||||
|
n, err := length.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reg.Clear()
|
||||||
|
|
||||||
|
var key pk.Identifier
|
||||||
|
var hasData pk.Boolean
|
||||||
|
for i := 0; i < int(length); i++ {
|
||||||
|
var data E
|
||||||
|
var n1, n2, n3 int64
|
||||||
|
|
||||||
|
n1, err = key.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n + n1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
n2, err = hasData.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n + n1 + n2, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasData {
|
||||||
|
n3, err = pk.NBTField{V:&data, AllowUnknownFields: true}.ReadFrom(r)
|
||||||
|
if err != nil {
|
||||||
|
return n + n1 + n2 + n3, err
|
||||||
|
}
|
||||||
|
reg.Put(string(key), data)
|
||||||
|
}
|
||||||
|
|
||||||
|
n += n1 + n2 + n3
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
@ -1,55 +1,45 @@
|
|||||||
package registry
|
package registry
|
||||||
|
|
||||||
import "github.com/Tnze/go-mc/nbt"
|
|
||||||
|
|
||||||
type Registry[E any] struct {
|
type Registry[E any] struct {
|
||||||
Type string `nbt:"type"`
|
keys map[string]int32
|
||||||
Value []Entry[E] `nbt:"value"`
|
values []E
|
||||||
|
indices map[*E]int32
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entry[E any] struct {
|
func NewRegistry[E any]() Registry[E] {
|
||||||
Name string `nbt:"name"`
|
return Registry[E]{
|
||||||
ID int32 `nbt:"id"`
|
keys: make(map[string]int32),
|
||||||
Element E `nbt:"element"`
|
values: make([]E, 0, 256),
|
||||||
|
indices: make(map[*E]int32),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Registry[E]) Find(name string) (int32, *E) {
|
func (r *Registry[E]) Get(key string) (int32, *E) {
|
||||||
for i := range r.Value {
|
id, ok := r.keys[key]
|
||||||
if r.Value[i].Name == name {
|
if !ok {
|
||||||
return int32(i), &r.Value[i].Element
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1, nil
|
return -1, nil
|
||||||
|
}
|
||||||
|
return id, &r.values[id]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Registry[E]) FindByID(id int32) *E {
|
func (r *Registry[E]) GetByID(id int32) *E {
|
||||||
if id >= 0 && id < int32(len(r.Value)) && r.Value[id].ID == id {
|
if id >= 0 && id < int32(len(r.values)) {
|
||||||
return &r.Value[id].Element
|
return &r.values[id]
|
||||||
}
|
|
||||||
for i := range r.Value {
|
|
||||||
if r.Value[i].ID == id {
|
|
||||||
return &r.Value[i].Element
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Registry[E]) Insert(name string, data E) {
|
func (r *Registry[E]) Put(name string, data E) (id int32, val *E) {
|
||||||
entry := Entry[E]{
|
id = int32(len(r.values))
|
||||||
Name: name,
|
r.keys[name] = id
|
||||||
ID: int32(len(r.Value)),
|
r.values = append(r.values, data)
|
||||||
Element: data,
|
val = &r.values[id]
|
||||||
}
|
r.indices[val] = id
|
||||||
r.Value = append(r.Value, entry)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Registry[E]) InsertWithNBT(name string, data nbt.RawMessage) error {
|
func (r *Registry[E]) Clear() {
|
||||||
var elem E
|
r.keys = make(map[string]int32)
|
||||||
if data.Type != 0 {
|
r.values = r.values[:0]
|
||||||
if err := data.UnmarshalDisallowUnknownField(&elem); err != nil {
|
r.indices = make(map[*E]int32)
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.Insert(name, elem)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user