diff --git a/chat/decoration.go b/chat/decoration.go index 15b7aeed..e22ee330 100644 --- a/chat/decoration.go +++ b/chat/decoration.go @@ -29,7 +29,7 @@ type Type struct { } func (t *Type) Decorate(content Message, d *Decoration) (msg Message) { - with := make([]Message, len(d.Parameters)) + with := make([]any, len(d.Parameters)) for i, para := range d.Parameters { switch para { case "sender": diff --git a/chat/jsonmessage.go b/chat/jsonmessage.go index be036b67..723096f8 100644 --- a/chat/jsonmessage.go +++ b/chat/jsonmessage.go @@ -58,3 +58,16 @@ func (m *Message) UnmarshalJSON(raw []byte) (err error) { return errors.New("unknown chat message type: '" + string(raw[0]) + "'") } } + +func (t *TranslateArgs) UnmarshalJSON(raw []byte) error { + var v []Message + err := json.Unmarshal(raw, &v) + if err != nil { + return err + } + + for _, v := range v { + *t = append(*t, v) + } + return nil +} diff --git a/chat/message.go b/chat/message.go index 85f0253f..f6368b2b 100644 --- a/chat/message.go +++ b/chat/message.go @@ -70,11 +70,13 @@ type Message struct { ClickEvent *ClickEvent `json:"clickEvent,omitempty" nbt:"clickEvent,omitempty"` HoverEvent *HoverEvent `json:"hoverEvent,omitempty" nbt:"hoverEvent,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"` + Translate string `json:"translate,omitempty" nbt:"translate,omitempty"` + With TranslateArgs `json:"with,omitempty" nbt:"with,omitempty"` + Extra []Message `json:"extra,omitempty" nbt:"extra,omitempty"` } +type TranslateArgs []any + // Same as Message, but "Text" is omitempty type translateMsg struct { Text string `json:"text,omitempty" nbt:"text,omitempty"` @@ -92,9 +94,9 @@ type translateMsg struct { ClickEvent *ClickEvent `json:"clickEvent,omitempty" nbt:"clickEvent,omitempty"` HoverEvent *HoverEvent `json:"hoverEvent,omitempty" nbt:"hoverEvent,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"` + Translate string `json:"translate,omitempty" nbt:"translate,omitempty"` + With TranslateArgs `json:"with,omitempty" nbt:"with,omitempty"` + Extra []Message `json:"extra,omitempty" nbt:"extra,omitempty"` } type rawMsgStruct Message @@ -127,7 +129,9 @@ func Text(str string) Message { func TranslateMsg(key string, with ...Message) (m Message) { m.Translate = key - m.With = with + for _, v := range with { + m.With = append(m.With, v) + } return } @@ -195,7 +199,12 @@ func (m Message) ClearString() string { if m.Translate != "" { args := make([]any, len(m.With)) for i, v := range m.With { - args[i] = v.ClearString() + switch v := v.(type) { + case Message: + args[i] = v.ClearString() + default: + args[i] = v + } } _, _ = fmt.Fprintf(&msg, translateMap[m.Translate], args...) @@ -238,12 +247,7 @@ func (m Message) String() string { // handle translate if m.Translate != "" { - args := make([]any, len(m.With)) - for i, v := range m.With { - args[i] = v - } - - _, _ = fmt.Fprintf(&msg, translateMap[m.Translate], args...) + _, _ = fmt.Fprintf(&msg, translateMap[m.Translate], m.With...) } if m.Extra != nil { diff --git a/chat/nbtmessage.go b/chat/nbtmessage.go index 8d63967c..cb31a6cd 100644 --- a/chat/nbtmessage.go +++ b/chat/nbtmessage.go @@ -52,3 +52,50 @@ func (m *Message) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error { return errors.New("unknown chat message type: '" + strconv.FormatUint(uint64(tagType), 16) + "'") } } + +func (t *TranslateArgs) UnmarshalNBT(tagType byte, r nbt.DecoderReader) error { + tagReader := bytes.NewReader([]byte{tagType}) + decoder := nbt.NewDecoder(io.MultiReader(tagReader, r)) + decoder.NetworkFormat(true) // TagType directlly followed the body + + switch tagType { + case nbt.TagList: + var value []Message + if _, err := decoder.Decode(&value); err != nil { + return err + } + for _, v := range value { + *t = append(*t, v) + } + return nil + case nbt.TagByteArray: + var value []int8 + if _, err := decoder.Decode(&value); err != nil { + return err + } + for _, v := range value { + *t = append(*t, strconv.FormatInt(int64(v), 10)) + } + return nil + case nbt.TagIntArray: + var value []int32 + if _, err := decoder.Decode(&value); err != nil { + return err + } + for _, v := range value { + *t = append(*t, strconv.FormatInt(int64(v), 10)) + } + return nil + case nbt.TagLongArray: + var value []int64 + if _, err := decoder.Decode(&value); err != nil { + return err + } + for _, v := range value { + *t = append(*t, strconv.FormatInt(int64(v), 10)) + } + return nil + default: + return errors.New("unknown translation args type: '" + strconv.FormatUint(uint64(tagType), 16) + "'") + } +} diff --git a/chat/nbtmessage_test.go b/chat/nbtmessage_test.go new file mode 100644 index 00000000..54059f23 --- /dev/null +++ b/chat/nbtmessage_test.go @@ -0,0 +1,36 @@ +package chat_test + +import ( + "testing" + + "github.com/Tnze/go-mc/chat" + en_us "github.com/Tnze/go-mc/data/lang/en-us" + "github.com/Tnze/go-mc/nbt" +) + +func TestMessage_UnmarshalJSON_string(t *testing.T) { + snbts := []string{ + "{translate: sleep.players_sleeping, with: [I; 1, 37]}", + } + + texts := []string{ + "1/37 players sleeping", + } + + chat.SetLanguage(en_us.Map) + for i, v := range snbts { + bytes, err := nbt.Marshal(nbt.StringifiedMessage(v)) + if err != nil { + t.Errorf("Invalid SNBT: %v", err) + continue + } + + var cm chat.Message + if err := nbt.Unmarshal(bytes, &cm); err != nil { + t.Error(err) + } + if str := cm.String(); str != texts[i] { + t.Errorf("gets %q, wants %q", str, texts[i]) + } + } +}