Update Text Component defination

This commit is contained in:
Tnze
2024-04-27 22:09:56 +08:00
parent fee324e25a
commit 79c8b35389
6 changed files with 149 additions and 90 deletions

View File

@ -82,11 +82,11 @@ func attachDisconnect(c *bot.Client, handler func(reason chat.Message) error) {
c.Events.AddListener(bot.PacketHandler{ c.Events.AddListener(bot.PacketHandler{
Priority: 64, ID: packetid.ClientboundDisconnect, Priority: 64, ID: packetid.ClientboundDisconnect,
F: func(p pk.Packet) error { F: func(p pk.Packet) error {
var reason chat.Message var reason chat.JsonMessage
if err := p.Scan(&reason); err != nil { if err := p.Scan(&reason); err != nil {
return Error{err} return Error{err}
} }
return handler(reason) return handler(chat.Message(reason))
}, },
}) })
} }

View File

@ -4,8 +4,8 @@ import "strconv"
// ClickEvent defines an event that occurs when this component is clicked. // ClickEvent defines an event that occurs when this component is clicked.
type ClickEvent struct { type ClickEvent struct {
Action string `json:"action"` Action string `json:"action" nbt:"action"`
Value string `json:"value"` Value string `json:"value" nbt:"value"`
} }
// OpenURL create a ClickEvent opens the given URL in the default web browser. // OpenURL create a ClickEvent opens the given URL in the default web browser.

View File

@ -1,12 +1,10 @@
package chat package chat
import "encoding/json"
// HoverEvent defines an event that occurs when this component hovered over. // HoverEvent defines an event that occurs when this component hovered over.
type HoverEvent struct { type HoverEvent struct {
Action string `json:"action"` Action string `json:"action" nbt:"action"`
Contents json.RawMessage `json:"contents"` // Didn't handled yet Contents any `json:"contents" nbt:"contents"` // Didn't handled yet
Value Message `json:"value"` // Legacy Value Message `json:"value" nbt:"value"` // Legacy
} }
type HoverSub struct { type HoverSub struct {

60
chat/jsonmessage.go Normal file
View File

@ -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]) + "'")
}
}

View File

@ -11,16 +11,11 @@
package chat package chat
import ( import (
"bytes"
"encoding/json"
"errors"
"fmt" "fmt"
"io"
"regexp" "regexp"
"strings" "strings"
en_us "github.com/Tnze/go-mc/data/lang/en-us" en_us "github.com/Tnze/go-mc/data/lang/en-us"
pk "github.com/Tnze/go-mc/net/packet"
) )
const ( const (
@ -56,102 +51,54 @@ const (
// Message is a message sent by other // Message is a message sent by other
type Message struct { type Message struct {
Text string `json:"text"` Text string `json:"text" nbt:"text"`
Bold bool `json:"bold,omitempty"` // 粗体 Bold bool `json:"bold,omitempty" nbt:"bold,omitempty"` // 粗体
Italic bool `json:"italic,omitempty"` // 斜体 Italic bool `json:"italic,omitempty" nbt:"italic,omitempty"` // 斜体
UnderLined bool `json:"underlined,omitempty"` // 下划线 UnderLined bool `json:"underlined,omitempty" nbt:"underlined,omitempty"` // 下划线
StrikeThrough bool `json:"strikethrough,omitempty"` // 删除线 StrikeThrough bool `json:"strikethrough,omitempty" nbt:"strikethrough,omitempty"` // 删除线
Obfuscated bool `json:"obfuscated,omitempty"` // 随机 Obfuscated bool `json:"obfuscated,omitempty" nbt:"obfuscated,omitempty"` // 随机
// Font of the message, could be one of minecraft:uniform, minecraft:alt or minecraft:default // 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. // This option is only valid on 1.16+, otherwise the property is ignored.
Font string `json:"font,omitempty"` // 字体 Font string `json:"font,omitempty" nbt:"font,omitempty"` // 字体
Color string `json:"color,omitempty"` // 颜色 Color string `json:"color,omitempty" nbt:"color,omitempty"` // 颜色
// Insertion contains text to insert. Only used for messages in chat. // Insertion contains text to insert. Only used for messages in chat.
// When shift is held, clicking the component inserts the given text // When shift is held, clicking the component inserts the given text
// into the chat box at the cursor (potentially replacing selected text). // into the chat box at the cursor (potentially replacing selected text).
Insertion string `json:"insertion,omitempty"` Insertion string `json:"insertion,omitempty" nbt:"insertion,omitempty"`
ClickEvent *ClickEvent `json:"clickEvent,omitempty"` ClickEvent *ClickEvent `json:"clickEvent,omitempty" nbt:"clickEvent,omitempty"`
HoverEvent *HoverEvent `json:"hoverEvent,omitempty"` HoverEvent *HoverEvent `json:"hoverEvent,omitempty" nbt:"hoverEvent,omitempty"`
Translate string `json:"translate,omitempty"` Translate string `json:"translate,omitempty" nbt:"translate,omitempty"`
With []Message `json:"with,omitempty"` With []Message `json:"with,omitempty" nbt:"with,omitempty"`
Extra []Message `json:"extra,omitempty"` Extra []Message `json:"extra,omitempty" nbt:"extra,omitempty"`
} }
// Same as Message, but "Text" is omitempty // Same as Message, but "Text" is omitempty
type translateMsg struct { type translateMsg struct {
Text string `json:"text,omitempty"` Text string `json:"text,omitempty" nbt:"text,omitempty"`
Bold bool `json:"bold,omitempty"` Bold bool `json:"bold,omitempty" nbt:"bold,omitempty"`
Italic bool `json:"italic,omitempty"` Italic bool `json:"italic,omitempty" nbt:"italic,omitempty"`
UnderLined bool `json:"underlined,omitempty"` UnderLined bool `json:"underlined,omitempty" nbt:"underlined,omitempty"`
StrikeThrough bool `json:"strikethrough,omitempty"` StrikeThrough bool `json:"strikethrough,omitempty" nbt:"strikethrough,omitempty"`
Obfuscated bool `json:"obfuscated,omitempty"` Obfuscated bool `json:"obfuscated,omitempty" nbt:"obfuscated,omitempty"`
Font string `json:"font,omitempty"` Font string `json:"font,omitempty" nbt:"font,omitempty"`
Color string `json:"color,omitempty"` Color string `json:"color,omitempty" nbt:"color,omitempty"`
Insertion string `json:"insertion,omitempty"` Insertion string `json:"insertion,omitempty" nbt:"insertion,omitempty"`
ClickEvent *ClickEvent `json:"clickEvent,omitempty"` ClickEvent *ClickEvent `json:"clickEvent,omitempty" nbt:"clickEvent,omitempty"`
HoverEvent *HoverEvent `json:"hoverEvent,omitempty"` HoverEvent *HoverEvent `json:"hoverEvent,omitempty" nbt:"hoverEvent,omitempty"`
Translate string `json:"translate"` Translate string `json:"translate,omitempty" nbt:"translate,omitempty"`
With []Message `json:"with,omitempty"` With []Message `json:"with,omitempty" nbt:"with,omitempty"`
Extra []Message `json:"extra,omitempty"` Extra []Message `json:"extra,omitempty" nbt:"extra,omitempty"`
} }
type rawMsgStruct Message 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. // Append extra message to the end of the message and return the new one.
// The source message remains unchanged. // The source message remains unchanged.
func (m Message) Append(extraMsg ...Message) Message { func (m Message) Append(extraMsg ...Message) Message {

54
chat/nbtmessage.go Normal file
View File

@ -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) + "'")
}
}