From 79c8b35389b1587aea6a79173b768f9e07a077dc Mon Sep 17 00:00:00 2001 From: Tnze Date: Sat, 27 Apr 2024 22:09:56 +0800 Subject: [PATCH] Update Text Component defination --- bot/basic/events.go | 4 +- chat/clickevent.go | 4 +- chat/hoverevent.go | 8 ++-- chat/jsonmessage.go | 60 ++++++++++++++++++++++++ chat/message.go | 109 ++++++++++++-------------------------------- chat/nbtmessage.go | 54 ++++++++++++++++++++++ 6 files changed, 149 insertions(+), 90 deletions(-) create mode 100644 chat/jsonmessage.go create mode 100644 chat/nbtmessage.go diff --git a/bot/basic/events.go b/bot/basic/events.go index 51eef6c..0b02365 100644 --- a/bot/basic/events.go +++ b/bot/basic/events.go @@ -82,11 +82,11 @@ func attachDisconnect(c *bot.Client, handler func(reason chat.Message) error) { c.Events.AddListener(bot.PacketHandler{ Priority: 64, ID: packetid.ClientboundDisconnect, F: func(p pk.Packet) error { - var reason chat.Message + var reason chat.JsonMessage if err := p.Scan(&reason); err != nil { return Error{err} } - return handler(reason) + return handler(chat.Message(reason)) }, }) } diff --git a/chat/clickevent.go b/chat/clickevent.go index b0246c5..94cca08 100644 --- a/chat/clickevent.go +++ b/chat/clickevent.go @@ -4,8 +4,8 @@ import "strconv" // ClickEvent defines an event that occurs when this component is clicked. type ClickEvent struct { - Action string `json:"action"` - Value string `json:"value"` + Action string `json:"action" nbt:"action"` + Value string `json:"value" nbt:"value"` } // OpenURL create a ClickEvent opens the given URL in the default web browser. diff --git a/chat/hoverevent.go b/chat/hoverevent.go index df7371d..5b61acc 100644 --- a/chat/hoverevent.go +++ b/chat/hoverevent.go @@ -1,12 +1,10 @@ package chat -import "encoding/json" - // HoverEvent defines an event that occurs when this component hovered over. type HoverEvent struct { - Action string `json:"action"` - Contents json.RawMessage `json:"contents"` // Didn't handled yet - Value Message `json:"value"` // Legacy + Action string `json:"action" nbt:"action"` + Contents any `json:"contents" nbt:"contents"` // Didn't handled yet + Value Message `json:"value" nbt:"value"` // Legacy } type HoverSub struct { diff --git a/chat/jsonmessage.go b/chat/jsonmessage.go new file mode 100644 index 0000000..be036b6 --- /dev/null +++ b/chat/jsonmessage.go @@ -0,0 +1,60 @@ +package chat + +import ( + "bytes" + "encoding/json" + "errors" + "io" + + pk "github.com/Tnze/go-mc/net/packet" +) + +// JsonMessage is Message, unless when it is going to be Json instead of NBT +type JsonMessage Message + +// ReadFrom decode Message in a JSON Text component +func (m *JsonMessage) ReadFrom(r io.Reader) (int64, error) { + var code pk.String + n, err := code.ReadFrom(r) + if err != nil { + return n, err + } + err = json.Unmarshal([]byte(code), (*Message)(m)) + return n, err +} + +// WriteTo encode Message into a JSON Text component +func (m JsonMessage) WriteTo(w io.Writer) (int64, error) { + code, err := json.Marshal(Message(m)) + if err != nil { + panic(err) + } + return pk.String(code).WriteTo(w) +} + +func (m Message) MarshalJSON() ([]byte, error) { + if m.Translate != "" { + return json.Marshal(translateMsg(m)) + } else { + return json.Marshal(rawMsgStruct(m)) + } +} + +func (m *Message) UnmarshalJSON(raw []byte) (err error) { + raw = bytes.TrimSpace(raw) + if len(raw) == 0 { + return io.EOF + } + // The right way to distinguish JSON String and Object + // is to look up the first character. + switch raw[0] { + case '"': + return json.Unmarshal(raw, &m.Text) // Unmarshal as jsonString + case '{': + return json.Unmarshal(raw, (*rawMsgStruct)(m)) // Unmarshal as jsonMsg + case '[': + return json.Unmarshal(raw, &m.Extra) // Unmarshal as []Message + default: + return errors.New("unknown chat message type: '" + string(raw[0]) + "'") + } +} diff --git a/chat/message.go b/chat/message.go index 49e47df..85f0253 100644 --- a/chat/message.go +++ b/chat/message.go @@ -11,16 +11,11 @@ package chat import ( - "bytes" - "encoding/json" - "errors" "fmt" - "io" "regexp" "strings" en_us "github.com/Tnze/go-mc/data/lang/en-us" - pk "github.com/Tnze/go-mc/net/packet" ) const ( @@ -56,102 +51,54 @@ const ( // Message is a message sent by other type Message struct { - Text string `json:"text"` + Text string `json:"text" nbt:"text"` - Bold bool `json:"bold,omitempty"` // 粗体 - Italic bool `json:"italic,omitempty"` // 斜体 - UnderLined bool `json:"underlined,omitempty"` // 下划线 - StrikeThrough bool `json:"strikethrough,omitempty"` // 删除线 - Obfuscated bool `json:"obfuscated,omitempty"` // 随机 + Bold bool `json:"bold,omitempty" nbt:"bold,omitempty"` // 粗体 + Italic bool `json:"italic,omitempty" nbt:"italic,omitempty"` // 斜体 + UnderLined bool `json:"underlined,omitempty" nbt:"underlined,omitempty"` // 下划线 + StrikeThrough bool `json:"strikethrough,omitempty" nbt:"strikethrough,omitempty"` // 删除线 + Obfuscated bool `json:"obfuscated,omitempty" nbt:"obfuscated,omitempty"` // 随机 // Font of the message, could be one of minecraft:uniform, minecraft:alt or minecraft:default // This option is only valid on 1.16+, otherwise the property is ignored. - Font string `json:"font,omitempty"` // 字体 - Color string `json:"color,omitempty"` // 颜色 + Font string `json:"font,omitempty" nbt:"font,omitempty"` // 字体 + Color string `json:"color,omitempty" nbt:"color,omitempty"` // 颜色 // Insertion contains text to insert. Only used for messages in chat. // When shift is held, clicking the component inserts the given text // into the chat box at the cursor (potentially replacing selected text). - Insertion string `json:"insertion,omitempty"` - ClickEvent *ClickEvent `json:"clickEvent,omitempty"` - HoverEvent *HoverEvent `json:"hoverEvent,omitempty"` + Insertion string `json:"insertion,omitempty" nbt:"insertion,omitempty"` + ClickEvent *ClickEvent `json:"clickEvent,omitempty" nbt:"clickEvent,omitempty"` + HoverEvent *HoverEvent `json:"hoverEvent,omitempty" nbt:"hoverEvent,omitempty"` - Translate string `json:"translate,omitempty"` - With []Message `json:"with,omitempty"` - Extra []Message `json:"extra,omitempty"` + Translate string `json:"translate,omitempty" nbt:"translate,omitempty"` + With []Message `json:"with,omitempty" nbt:"with,omitempty"` + Extra []Message `json:"extra,omitempty" nbt:"extra,omitempty"` } // Same as Message, but "Text" is omitempty type translateMsg struct { - Text string `json:"text,omitempty"` + Text string `json:"text,omitempty" nbt:"text,omitempty"` - Bold bool `json:"bold,omitempty"` - Italic bool `json:"italic,omitempty"` - UnderLined bool `json:"underlined,omitempty"` - StrikeThrough bool `json:"strikethrough,omitempty"` - Obfuscated bool `json:"obfuscated,omitempty"` + Bold bool `json:"bold,omitempty" nbt:"bold,omitempty"` + Italic bool `json:"italic,omitempty" nbt:"italic,omitempty"` + UnderLined bool `json:"underlined,omitempty" nbt:"underlined,omitempty"` + StrikeThrough bool `json:"strikethrough,omitempty" nbt:"strikethrough,omitempty"` + Obfuscated bool `json:"obfuscated,omitempty" nbt:"obfuscated,omitempty"` - Font string `json:"font,omitempty"` - Color string `json:"color,omitempty"` + Font string `json:"font,omitempty" nbt:"font,omitempty"` + Color string `json:"color,omitempty" nbt:"color,omitempty"` - Insertion string `json:"insertion,omitempty"` - ClickEvent *ClickEvent `json:"clickEvent,omitempty"` - HoverEvent *HoverEvent `json:"hoverEvent,omitempty"` + Insertion string `json:"insertion,omitempty" nbt:"insertion,omitempty"` + ClickEvent *ClickEvent `json:"clickEvent,omitempty" nbt:"clickEvent,omitempty"` + HoverEvent *HoverEvent `json:"hoverEvent,omitempty" nbt:"hoverEvent,omitempty"` - Translate string `json:"translate"` - With []Message `json:"with,omitempty"` - Extra []Message `json:"extra,omitempty"` + Translate string `json:"translate,omitempty" nbt:"translate,omitempty"` + With []Message `json:"with,omitempty" nbt:"with,omitempty"` + Extra []Message `json:"extra,omitempty" nbt:"extra,omitempty"` } type rawMsgStruct Message -func (m Message) MarshalJSON() ([]byte, error) { - if m.Translate != "" { - return json.Marshal(translateMsg(m)) - } else { - return json.Marshal(rawMsgStruct(m)) - } -} - -// UnmarshalJSON decode json to Message -func (m *Message) UnmarshalJSON(raw []byte) (err error) { - raw = bytes.TrimSpace(raw) - if len(raw) == 0 { - return io.EOF - } - // The right way to distinguish JSON String and Object - // is to look up the first character. - switch raw[0] { - case '"': - return json.Unmarshal(raw, &m.Text) // Unmarshal as jsonString - case '{': - return json.Unmarshal(raw, (*rawMsgStruct)(m)) // Unmarshal as jsonMsg - case '[': - return json.Unmarshal(raw, &m.Extra) // Unmarshal as []Message - default: - return errors.New("unknown chat message type: '" + string(raw[0]) + "'") - } -} - -// ReadFrom decode Message in a ChatMsg packet -func (m *Message) ReadFrom(r io.Reader) (int64, error) { - var code pk.String - n, err := code.ReadFrom(r) - if err != nil { - return n, err - } - err = json.Unmarshal([]byte(code), m) - return n, err -} - -// WriteTo encode Message into a ChatMsg packet -func (m Message) WriteTo(w io.Writer) (int64, error) { - code, err := json.Marshal(m) - if err != nil { - panic(err) - } - return pk.String(code).WriteTo(w) -} - // Append extra message to the end of the message and return the new one. // The source message remains unchanged. func (m Message) Append(extraMsg ...Message) Message { diff --git a/chat/nbtmessage.go b/chat/nbtmessage.go new file mode 100644 index 0000000..ac6a926 --- /dev/null +++ b/chat/nbtmessage.go @@ -0,0 +1,54 @@ +package chat + +import ( + "errors" + "io" + "strconv" + + "github.com/Tnze/go-mc/nbt" + pk "github.com/Tnze/go-mc/net/packet" +) + +// ReadFrom decode Message in a Text component +func (m *Message) ReadFrom(r io.Reader) (int64, error) { + var code pk.String + n, err := code.ReadFrom(r) + if err != nil { + return n, err + } + err = nbt.Unmarshal([]byte(code), (*Message)(m)) + return n, err +} + +// WriteTo encode Message into a Text component +func (m Message) WriteTo(w io.Writer) (int64, error) { + code, err := nbt.Marshal(Message(m)) + if err != nil { + panic(err) + } + return pk.String(code).WriteTo(w) +} + +func (m Message) MarshalNBT() ([]byte, error) { + if m.Translate != "" { + return nbt.Marshal(translateMsg(m)) + } else { + return nbt.Marshal(rawMsgStruct(m)) + } +} + +func (m *Message) UnmarshalNBT(raw []byte) (err error) { + if len(raw) == 0 { + return io.EOF + } + switch raw[0] { + case nbt.TagString: + return nbt.Unmarshal(raw, &m.Text) // Unmarshal as jsonString + case nbt.TagCompound: + return nbt.Unmarshal(raw, (*rawMsgStruct)(m)) // Unmarshal as jsonMsg + case nbt.TagList: + return nbt.Unmarshal(raw, &m.Extra) // Unmarshal as []Message + default: + return errors.New("unknown chat message type: '" + strconv.FormatUint(uint64(raw[0]), 16) + "'") + } +}