diff --git a/binary/jce/gen/structs_parser.go b/binary/jce/gen/structs_parser.go deleted file mode 100644 index 9d941bd6..00000000 --- a/binary/jce/gen/structs_parser.go +++ /dev/null @@ -1,92 +0,0 @@ -package main - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "os" - "os/exec" - "strings" - - _ "embed" -) - -//go:embed structs_parser_tmp.go -var tmpmain string - -func main() { - f := flag.String("f", "structs_tobytes.go", "output file.") - i := flag.String("i", "structs.go", "input file.") - flag.Parse() - fmt.Println("gen runs on arg", *f, *i) - fmt.Println("len of tmp main is", len(tmpmain)) - tmp, err := os.Create("tmp.go") - if err != nil { - panic(err) - } - inp, err := os.Open(*i) - if err != nil { - panic(err) - } - var structs []string - var isinhead = true - var isinfill = false - var isnexttemplate = false - s := bufio.NewScanner(bytes.NewReader([]byte(tmpmain))) - for s.Scan() { - line := s.Text() - if isinhead { - if strings.Contains(line, "Main_") { - line = "func main() {" - isnexttemplate = true - isinhead = false - scanner := bufio.NewScanner(inp) - start := false - for scanner.Scan() { - t := scanner.Text() - if t == "type (" { - start = true - } - if start { - tmp.WriteString(t + "\n") - if t == ")" { - break - } - if strings.Contains(t, " struct {") { - structs = append(structs, strings.Trim(t[:len(t)-9], "\t")) - } - } - } - inp.Close() - } - tmp.WriteString(line + "\n") - } else if isinfill { - for _, s := range structs { - fmt.Fprintf(tmp, "\tWriteJceStruct(w, &%s{})\n", s) - } - isinfill = false - tmp.WriteString("// structs_parser: fill area\n") - tmp.WriteString(line + "\n") - } else { - if strings.Contains(line, "// structs_parser: fill area") { - isinfill = true - tmp.WriteString("// structs_parser: fill area\n") - } else { - if isnexttemplate { - fmt.Fprintf(tmp, line+"\n", *f) - isnexttemplate = false - } else { - tmp.WriteString(line + "\n") - } - } - } - } - tmp.Close() - c := exec.Command("go", "run", "tmp.go") - err = c.Run() - if err != nil { - panic(err) - } - os.Remove("tmp.go") -} diff --git a/binary/jce/gen/structs_parser_tmp.go b/binary/jce/gen/structs_parser_tmp.go deleted file mode 100644 index f20901fa..00000000 --- a/binary/jce/gen/structs_parser_tmp.go +++ /dev/null @@ -1,149 +0,0 @@ -package main - -import ( - "fmt" - "io" - "os" - "reflect" - "strconv" - "strings" - "sync" -) - -type IJceStruct interface{} - -const head = "// Code generated by structs_parser; DO NOT EDIT.\npackage jce\n" - -func Main_() { - w, err := os.Create("%s") - if err != nil { - panic(err) - } - w.WriteString(head) - // structs_parser: fill area - err = w.Close() - if err != nil { - panic(err) - } -} - -func writeObject(w io.Writer, v reflect.Value, tag byte, name string) { - k := v.Kind() - if k == reflect.Map { - switch v.Interface().(type) { - case map[string]string: - w.Write([]byte(fmt.Sprintf("\tw.writeMapStrStr(pkt.%s, %d)\n", name, tag))) - case map[string][]byte: - w.Write([]byte(fmt.Sprintf("\tw.writeMapStrBytes(pkt.%s, %d)\n", name, tag))) - case map[string]map[string][]byte: - w.Write([]byte(fmt.Sprintf("\tw.writeMapStrMapStrBytes(pkt.%s, %d)\n", name, tag))) - default: - w.Write([]byte(fmt.Sprintf("\tw.writeMap(pkt.%s, %d)\n", name, tag))) - } - return - } - if k == reflect.Slice { - switch v.Interface().(type) { - case []byte: - w.Write([]byte(fmt.Sprintf("\tw.WriteBytes(pkt.%s, %d)\n", name, tag))) - case []int64: - w.Write([]byte(fmt.Sprintf("\tw.WriteInt64Slice(pkt.%s, %d)\n", name, tag))) - case [][]byte: - w.Write([]byte(fmt.Sprintf("\tw.WriteBytesSlice(pkt.%s, %d)\n", name, tag))) - default: - writeJceStructSlice(w, tag, name) - } - return - } - switch k { - case reflect.Uint8, reflect.Int8: - w.Write([]byte(fmt.Sprintf("\tw.WriteByte(pkt.%s, %d)\n", name, tag))) - case reflect.Uint16, reflect.Int16: - w.Write([]byte(fmt.Sprintf("\tw.WriteInt16(pkt.%s, %d)\n", name, tag))) - case reflect.Uint32, reflect.Int32: - w.Write([]byte(fmt.Sprintf("\tw.WriteInt32(pkt.%s, %d)\n", name, tag))) - case reflect.Uint64, reflect.Int64: - w.Write([]byte(fmt.Sprintf("\tw.WriteInt64(pkt.%s, %d)\n", name, tag))) - case reflect.Int, reflect.Uint: - w.Write([]byte(fmt.Sprintf("\tw.WriteInt64(int64(pkt.%s), %d)\n", name, tag))) - case reflect.String: - w.Write([]byte(fmt.Sprintf("\tw.WriteString(pkt.%s, %d)\n", name, tag))) - case reflect.Interface, reflect.Ptr: - w.Write([]byte(fmt.Sprintf("\tw.writeHead(10, %d)\n", tag))) - w.Write([]byte(fmt.Sprintf("\tw.buf.Write(pkt.%s.ToBytes())\n", name))) - w.Write([]byte("\tw.writeHead(11, 0)\n")) - default: - switch v.Interface().(type) { - case float32: - w.Write([]byte(fmt.Sprintf("\tw.WriteFloat32(pkt.%s, %d)\n", name, tag))) - case float64: - w.Write([]byte(fmt.Sprintf("\tw.WriteFloat64(pkt.%s, %d)\n", name, tag))) - } - } -} - -type decoder struct { - index int - id int - name string -} - -var decoderCache = sync.Map{} - -// writeJceStructRaw 写入 Jce 结构体 -func writeJceStructRaw(w io.Writer, s interface{}) { - t := reflect.TypeOf(s) - if t.Kind() != reflect.Ptr { - return - } - t = t.Elem() - v := reflect.ValueOf(s).Elem() - var jceDec []decoder - dec, ok := decoderCache.Load(t) - if ok { // 从缓存中加载 - jceDec = dec.([]decoder) - } else { // 初次反射 - jceDec = make([]decoder, 0, t.NumField()) - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - strId := field.Tag.Get("jceId") - if strId == "" { - continue - } - id, err := strconv.Atoi(strId) - if err != nil { - continue - } - jceDec = append(jceDec, decoder{ - index: i, - id: id, - name: field.Name, - }) - } - decoderCache.Store(t, jceDec) // 存入缓存 - } - for _, dec := range jceDec { - obj := v.Field(dec.index) - writeObject(w, obj, byte(dec.id), dec.name) - } -} - -func writeJceStructSlice(w io.Writer, tag byte, name string) { - w.Write([]byte(fmt.Sprintf("\tw.writeHead(9, %d)\n", tag))) - w.Write([]byte(fmt.Sprintf("\tif len(pkt.%s) == 0 {\n", name))) - w.Write([]byte("\t\tw.writeHead(12, 0) // w.WriteInt32(0, 0)\n")) - w.Write([]byte("\t} else {\n")) - w.Write([]byte(fmt.Sprintf("\t\tw.WriteInt32(int32(len(pkt.%s)), 0)\n", name))) - w.Write([]byte(fmt.Sprintf("\t\tfor _, i := range pkt.%s {\n", name))) - w.Write([]byte("\t\t\tw.buf.Write(i.ToBytes())\n")) - w.Write([]byte("\t\t}\n")) - w.Write([]byte("\t}\n")) -} - -func WriteJceStruct(w io.Writer, s IJceStruct) { - w.Write([]byte(fmt.Sprintf("\nfunc (pkt %s) ToBytes() []byte {\n", strings.ReplaceAll(reflect.TypeOf(s).String(), "main.", "")))) - w.Write([]byte("\tw := NewJceWriter()\n")) - writeJceStructRaw(w, s) - w.Write([]byte("\treturn w.Bytes()\n")) - w.Write([]byte("}\n")) -} diff --git a/binary/jce/structs.go b/binary/jce/structs.go index f30e9a63..60296879 100644 --- a/binary/jce/structs.go +++ b/binary/jce/structs.go @@ -5,7 +5,7 @@ type IJceStruct interface { ReadFrom(*JceReader) } -//go:generate go run gen/structs_parser.go -f structs_tobytes.go -i structs.go +//go:generate go run github.com/Mrs4s/MiraiGo/internal/generator/jce_gen -file=structs.go -o structs_tobytes.go type ( RequestPacket struct { IVersion int16 `jceId:"1"` @@ -75,7 +75,6 @@ type ( } SvcReqRegister struct { - IJceStruct Uin int64 `jceId:"0"` Bid int64 `jceId:"1"` ConnType byte `jceId:"2"` @@ -140,7 +139,6 @@ type ( } SvcReqRegisterNew struct { - IJceStruct RequestOptional int64 `jceId:"0"` C2CMsg IJceStruct `jceId:"1"` // SvcReqGetMsgV2 GroupMsg IJceStruct `jceId:"2"` // SvcReqPullGroupMsgSeq @@ -174,7 +172,6 @@ type ( } PullGroupSeqParam struct { - IJceStruct GroupCode int64 `jceId:"0"` LastSeqId int64 `jceId:"1"` } @@ -252,7 +249,6 @@ type ( } SvcRespPushMsg struct { - IJceStruct Uin int64 `jceId:"0"` DelInfos []IJceStruct `jceId:"1"` Svrip int32 `jceId:"2"` @@ -300,7 +296,6 @@ type ( } FriendListRequest struct { - IJceStruct Reqtype int32 `jceId:"0"` IfReflush byte `jceId:"1"` Uin int64 `jceId:"2"` @@ -382,7 +377,6 @@ type ( } TroopListRequest struct { - IJceStruct Uin int64 `jceId:"0"` GetMSFMsgFlag byte `jceId:"1"` Cookies []byte `jceId:"2"` @@ -433,7 +427,6 @@ type ( } TroopMemberListRequest struct { - IJceStruct Uin int64 `jceId:"0"` GroupCode int64 `jceId:"1"` NextUin int64 `jceId:"2"` @@ -483,7 +476,6 @@ type ( } ModifyGroupCardRequest struct { - IJceStruct Zero int64 `jceId:"0"` GroupCode int64 `jceId:"1"` NewSeq int64 `jceId:"2"` @@ -502,7 +494,6 @@ type ( } SummaryCardReq struct { - IJceStruct Uin int64 `jceId:"0"` ComeFrom int32 `jceId:"1"` QzoneFeedTimestamp int64 `jceId:"2"` @@ -524,7 +515,6 @@ type ( } SummaryCardReqSearch struct { - IJceStruct Keyword string `jceId:"0"` CountryCode string `jceId:"1"` Version int32 `jceId:"2"` @@ -532,7 +522,6 @@ type ( } DelFriendReq struct { - IJceStruct Uin int64 `jceId:"0"` DelUin int64 `jceId:"1"` DelType byte `jceId:"2"` diff --git a/binary/jce/structs_tobytes.go b/binary/jce/structs_tobytes.go index e03ef5f7..19a3b2b2 100644 --- a/binary/jce/structs_tobytes.go +++ b/binary/jce/structs_tobytes.go @@ -1,4 +1,5 @@ -// Code generated by structs_parser; DO NOT EDIT. +// Code generated by internal/generator/jce_gen; DO NOT EDIT. + package jce func (pkt *RequestPacket) ToBytes() []byte { @@ -38,70 +39,100 @@ func (pkt *SsoServerInfo) ToBytes() []byte { func (pkt *FileStoragePushFSSvcList) ToBytes() []byte { w := NewJceWriter() - w.writeHead(9, 0) - if len(pkt.UploadList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.UploadList)), 0) - for _, i := range pkt.UploadList { - w.buf.Write(i.ToBytes()) + { // write pkt.UploadList tag=0 + w.writeHead(9, 0) + if len(pkt.UploadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UploadList)), 0) + for _, i := range pkt.UploadList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } - w.writeHead(9, 1) - if len(pkt.PicDownloadList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.PicDownloadList)), 0) - for _, i := range pkt.PicDownloadList { - w.buf.Write(i.ToBytes()) + { // write pkt.PicDownloadList tag=1 + w.writeHead(9, 1) + if len(pkt.PicDownloadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.PicDownloadList)), 0) + for _, i := range pkt.PicDownloadList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } - w.writeHead(9, 2) - if len(pkt.GPicDownloadList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.GPicDownloadList)), 0) - for _, i := range pkt.GPicDownloadList { - w.buf.Write(i.ToBytes()) + { // write pkt.GPicDownloadList tag=2 + w.writeHead(9, 2) + if len(pkt.GPicDownloadList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.GPicDownloadList)), 0) + for _, i := range pkt.GPicDownloadList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } - w.writeHead(9, 3) - if len(pkt.QZoneProxyServiceList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.QZoneProxyServiceList)), 0) - for _, i := range pkt.QZoneProxyServiceList { - w.buf.Write(i.ToBytes()) + { // write pkt.QZoneProxyServiceList tag=3 + w.writeHead(9, 3) + if len(pkt.QZoneProxyServiceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.QZoneProxyServiceList)), 0) + for _, i := range pkt.QZoneProxyServiceList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } - w.writeHead(9, 4) - if len(pkt.UrlEncodeServiceList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.UrlEncodeServiceList)), 0) - for _, i := range pkt.UrlEncodeServiceList { - w.buf.Write(i.ToBytes()) + { // write pkt.UrlEncodeServiceList tag=4 + w.writeHead(9, 4) + if len(pkt.UrlEncodeServiceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UrlEncodeServiceList)), 0) + for _, i := range pkt.UrlEncodeServiceList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } - w.writeHead(10, 5) - w.buf.Write(pkt.BigDataChannel.ToBytes()) - w.writeHead(11, 0) - w.writeHead(9, 6) - if len(pkt.VipEmotionList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.VipEmotionList)), 0) - for _, i := range pkt.VipEmotionList { - w.buf.Write(i.ToBytes()) + { // write BigDataChannel tag=5 + w.writeHead(10, 5) + w.buf.Write(pkt.BigDataChannel.ToBytes()) + w.writeHead(11, 0) + } + { // write pkt.VipEmotionList tag=6 + w.writeHead(9, 6) + if len(pkt.VipEmotionList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.VipEmotionList)), 0) + for _, i := range pkt.VipEmotionList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } - w.writeHead(9, 7) - if len(pkt.C2CPicDownList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.C2CPicDownList)), 0) - for _, i := range pkt.C2CPicDownList { - w.buf.Write(i.ToBytes()) + { // write pkt.C2CPicDownList tag=7 + w.writeHead(9, 7) + if len(pkt.C2CPicDownList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.C2CPicDownList)), 0) + for _, i := range pkt.C2CPicDownList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } w.WriteBytes(pkt.PttList, 10) @@ -117,13 +148,17 @@ func (pkt *FileStorageServerInfo) ToBytes() []byte { func (pkt *BigDataChannel) ToBytes() []byte { w := NewJceWriter() - w.writeHead(9, 0) - if len(pkt.IPLists) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.IPLists)), 0) - for _, i := range pkt.IPLists { - w.buf.Write(i.ToBytes()) + { // write pkt.IPLists tag=0 + w.writeHead(9, 0) + if len(pkt.IPLists) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.IPLists)), 0) + for _, i := range pkt.IPLists { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } w.WriteBytes(pkt.SigSession, 1) @@ -137,13 +172,17 @@ func (pkt *BigDataChannel) ToBytes() []byte { func (pkt *BigDataIPList) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.ServiceType, 0) - w.writeHead(9, 1) - if len(pkt.IPList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.IPList)), 0) - for _, i := range pkt.IPList { - w.buf.Write(i.ToBytes()) + { // write pkt.IPList tag=1 + w.writeHead(9, 1) + if len(pkt.IPList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.IPList)), 0) + for _, i := range pkt.IPList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } w.WriteInt64(pkt.FragmentSize, 3) @@ -229,12 +268,16 @@ func (pkt *SvcRespRegister) ToBytes() []byte { func (pkt *SvcReqRegisterNew) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.RequestOptional, 0) - w.writeHead(10, 1) - w.buf.Write(pkt.C2CMsg.ToBytes()) - w.writeHead(11, 0) - w.writeHead(10, 2) - w.buf.Write(pkt.GroupMsg.ToBytes()) - w.writeHead(11, 0) + { // write C2CMsg tag=1 + w.writeHead(10, 1) + w.buf.Write(pkt.C2CMsg.ToBytes()) + w.writeHead(11, 0) + } + { // write GroupMsg tag=2 + w.writeHead(10, 2) + w.buf.Write(pkt.GroupMsg.ToBytes()) + w.writeHead(11, 0) + } w.WriteByte(pkt.DisGroupMsgFilter, 14) w.WriteByte(pkt.GroupMask, 15) w.WriteInt64(pkt.EndSeq, 16) @@ -261,13 +304,17 @@ func (pkt *SvcReqGetMsgV2) ToBytes() []byte { func (pkt *SvcReqPullGroupMsgSeq) ToBytes() []byte { w := NewJceWriter() - w.writeHead(9, 0) - if len(pkt.GroupInfo) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.GroupInfo)), 0) - for _, i := range pkt.GroupInfo { - w.buf.Write(i.ToBytes()) + { // write pkt.GroupInfo tag=0 + w.writeHead(9, 0) + if len(pkt.GroupInfo) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.GroupInfo)), 0) + for _, i := range pkt.GroupInfo { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } w.WriteByte(pkt.VerifyType, 1) @@ -291,13 +338,17 @@ func (pkt *SvcRespParam) ToBytes() []byte { w.WriteInt32(pkt.IsSupportViewPCFile, 4) w.WriteInt32(pkt.PcVersion, 5) w.WriteInt64(pkt.RoamFlag, 6) - w.writeHead(9, 7) - if len(pkt.OnlineInfos) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.OnlineInfos)), 0) - for _, i := range pkt.OnlineInfos { - w.buf.Write(i.ToBytes()) + { // write pkt.OnlineInfos tag=7 + w.writeHead(9, 7) + if len(pkt.OnlineInfos) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.OnlineInfos)), 0) + for _, i := range pkt.OnlineInfos { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } w.WriteInt32(pkt.PCClientType, 8) @@ -339,13 +390,17 @@ func (pkt *SvcReqMSFLoginNotify) ToBytes() []byte { w.WriteString(pkt.Info, 5) w.WriteInt64(pkt.ProductType, 6) w.WriteInt64(pkt.ClientType, 7) - w.writeHead(9, 8) - if len(pkt.InstanceList) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.InstanceList)), 0) - for _, i := range pkt.InstanceList { - w.buf.Write(i.ToBytes()) + { // write pkt.InstanceList tag=8 + w.writeHead(9, 8) + if len(pkt.InstanceList) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.InstanceList)), 0) + for _, i := range pkt.InstanceList { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } return w.Bytes() @@ -385,13 +440,17 @@ func (pkt *PushMessageInfo) ToBytes() []byte { func (pkt *SvcRespPushMsg) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.Uin, 0) - w.writeHead(9, 1) - if len(pkt.DelInfos) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.DelInfos)), 0) - for _, i := range pkt.DelInfos { - w.buf.Write(i.ToBytes()) + { // write pkt.DelInfos tag=1 + w.writeHead(9, 1) + if len(pkt.DelInfos) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.DelInfos)), 0) + for _, i := range pkt.DelInfos { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } w.WriteInt32(pkt.Svrip, 2) @@ -412,11 +471,6 @@ func (pkt *SvcReqGetDevLoginInfo) ToBytes() []byte { return w.Bytes() } -func (pkt *SvcDevLoginInfo) ToBytes() []byte { - w := NewJceWriter() - return w.Bytes() -} - func (pkt *DelMsgInfo) ToBytes() []byte { w := NewJceWriter() w.WriteInt64(pkt.FromUin, 0) @@ -630,13 +684,17 @@ func (pkt *ModifyGroupCardRequest) ToBytes() []byte { w.WriteInt64(pkt.Zero, 0) w.WriteInt64(pkt.GroupCode, 1) w.WriteInt64(pkt.NewSeq, 2) - w.writeHead(9, 3) - if len(pkt.UinInfo) == 0 { - w.writeHead(12, 0) // w.WriteInt32(0, 0) - } else { - w.WriteInt32(int32(len(pkt.UinInfo)), 0) - for _, i := range pkt.UinInfo { - w.buf.Write(i.ToBytes()) + { // write pkt.UinInfo tag=3 + w.writeHead(9, 3) + if len(pkt.UinInfo) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.UinInfo)), 0) + for _, i := range pkt.UinInfo { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } } } return w.Bytes() diff --git a/client/c2c_processor.go b/client/c2c_processor.go index 2e936bbc..5a19ba5e 100644 --- a/client/c2c_processor.go +++ b/client/c2c_processor.go @@ -1,6 +1,6 @@ package client -//go:generate go run cmd/c2c_switcher.go +//go:generate go run github.com/Mrs4s/MiraiGo/internal/generator/c2c_switcher import ( "fmt" diff --git a/client/c2c_switch.go b/client/c2c_switch.go index 5e792c97..de8f735f 100644 --- a/client/c2c_switch.go +++ b/client/c2c_switch.go @@ -1,4 +1,4 @@ -// Code generated by client/c2c_switcher.go DO NOT EDIT. +// Code generated by internal/generator/c2c_switcher DO NOT EDIT. package client @@ -9,10 +9,10 @@ import ( const ( UnknownDecoder = iota nonSvcNotifyTroopSystemMsgDecoders - troopSystemMsgDecoders - sysMsgDecoders otherDecoders privateMsgDecoders + sysMsgDecoders + troopSystemMsgDecoders ) func peekC2CDecoder(msgType int32) (decoder func(*QQClient, *msg.Message, *incomingPacketInfo), decoderType uint8) { diff --git a/client/cmd/c2c_switcher.go b/internal/generator/c2c_switcher/c2c_switcher.go similarity index 93% rename from client/cmd/c2c_switcher.go rename to internal/generator/c2c_switcher/c2c_switcher.go index 10f49712..649b2ea4 100644 --- a/client/cmd/c2c_switcher.go +++ b/internal/generator/c2c_switcher/c2c_switcher.go @@ -12,7 +12,7 @@ import ( "text/template" ) -const codeTemplate = `// Code generated by client/c2c_switcher.go DO NOT EDIT. +const codeTemplate = `// Code generated by internal/generator/c2c_switcher DO NOT EDIT. package client @@ -93,6 +93,9 @@ func main() { } } } + sort.Slice(sf.Consts, func(i, j int) bool { + return sf.Consts[i] < sf.Consts[j] + }) sort.Sort(sf.Decoders) f, _ := os.OpenFile("c2c_switch.go", os.O_WRONLY|os.O_CREATE|os.O_SYNC|os.O_TRUNC, 0o644) diff --git a/internal/generator/jce_gen/main.go b/internal/generator/jce_gen/main.go new file mode 100644 index 00000000..734dc558 --- /dev/null +++ b/internal/generator/jce_gen/main.go @@ -0,0 +1,197 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "io" + "os" + "reflect" + "strconv" +) + +type JceField struct { + Name string + Type ast.Expr + Id int +} + +type JceStruct struct { + Name string + Fields []JceField +} + +type Generator struct { + JceStructs []JceStruct +} + +func main() { + file := flag.String("file", "structs.txt", "file to parse") + output := flag.String("o", "", "output file") + flag.Parse() + f, err := parser.ParseFile(token.NewFileSet(), *file, nil, parser.ParseComments) + assert(err == nil, err) + g := Generator{} + ast.Inspect(f, func(n ast.Node) bool { + switch n := n.(type) { + case *ast.FuncDecl: + return false + case *ast.TypeSpec: + x, ok := n.Type.(*ast.StructType) + if !ok { + return false + } + if x.Fields != nil { + var jce JceStruct + for _, f := range x.Fields.List { + if f.Tag == nil { + continue + } + unquoted, _ := strconv.Unquote(f.Tag.Value) + tag, ok := reflect.StructTag(unquoted).Lookup("jceId") + if !ok { + continue + } + id, _ := strconv.Atoi(tag) + if len(f.Names) != 1 { + panic("unexpected name count") + } + jce.Fields = append(jce.Fields, JceField{ + Name: f.Names[0].Name, + Type: f.Type, + Id: id, + }) + } + jce.Name = n.Name.Name + g.JceStructs = append(g.JceStructs, jce) + } + } + return true + }) + buf := new(bytes.Buffer) + assert(err == nil, err) + g.Generate(buf) + formated, err := format.Source(buf.Bytes()) + if err != nil { + fmt.Printf("%s\n", buf.Bytes()) + panic(err) + } + _ = os.WriteFile(*output, formated, 0644) +} + +func (g Generator) Generate(w io.Writer) { + io.WriteString(w, "// Code generated by internal/generator/jce_gen; DO NOT EDIT.\n\npackage jce\n\n") + for _, jce := range g.JceStructs { + if jce.Name == "" || len(jce.Fields) == 0 { + continue + } + + var generate func(typ ast.Expr, i int) + generate = func(typ ast.Expr, i int) { + field := jce.Fields[i] + switch typ := typ.(type) { + case *ast.Ident: + switch typ.Name { + case "uint8", "uint16", "uint32", "uint64": + typename := []byte(typ.Name)[1:] + casted := fmt.Sprintf("%s(pkt.%s)", typename, field.Name) + typename[0] ^= ' ' + fmt.Fprintf(w, "w.Write%s(%s, %d)\n", typename, casted, field.Id) + + case "int8", "int16", "int32", "int64", + "byte", "string": + typename := []byte(typ.Name) + typename[0] ^= ' ' + fmt.Fprintf(w, "w.Write%s(pkt.%s, %d)\n", typename, field.Name, field.Id) + + case "int": + fmt.Fprintf(w, "w.WriteInt64(int64(pkt.%s), %d)\n", field.Name, field.Id) + + default: + fmt.Fprintf(w, `{ // write %s tag=%d + w.writeHead(10, %d) + w.buf.Write(pkt.%s.ToBytes()) + w.writeHead(11, 0)}`+"\n", field.Name, field.Id, field.Id, field.Name) + } + case *ast.StarExpr: + _ = typ.X.(*ast.Ident) // assert + generate(typ.X, i) + case *ast.ArrayType: + assert(typ.Len == nil, "unexpected array len") + var method string + switch typeName(typ) { + case "[]byte": + method = "WriteBytes" + case "[]int64": + method = "WriteInt64Slice" + case "[][]byte": + method = "WriteBytesSlice" + + default: + fmt.Fprintf(w, + "\t"+`{ // write pkt.%s tag=%d + w.writeHead(9, %d) + if len(pkt.%s) == 0 { + w.writeHead(12, 0) // w.WriteInt32(0, 0) + } else { + w.WriteInt32(int32(len(pkt.%s)), 0) + for _, i := range pkt.%s { + w.writeHead(10, 0) + w.buf.Write(i.ToBytes()) + w.writeHead(11, 0) + } + }}`+"\n", field.Name, field.Id, field.Id, field.Name, field.Name, field.Name) + return + } + assert(method != "", typeName(typ)) + fmt.Fprintf(w, "w.%s(pkt.%s, %d)\n", method, field.Name, field.Id) + case *ast.MapType: + var method string + typName := typeName(typ) + switch typName { + case "map[string]string": + method = "writeMapStrStr" + case "map[string][]byte": + method = "writeMapStrBytes" + case "map[string]map[string][]byte": + method = "writeMapStrMapStrBytes" + } + assert(method != "", typName) + fmt.Fprintf(w, "w.%s(pkt.%s, %d)\n", method, field.Name, field.Id) + } + } + + fmt.Fprintf(w, "func (pkt *%s) ToBytes() []byte {\nw := NewJceWriter()\n", jce.Name) + for i := range jce.Fields { + generate(jce.Fields[i].Type, i) + } + fmt.Fprintf(w, "return w.Bytes()\n}\n\n") + } +} + +func assert(cond bool, val interface{}) { + if !cond { + panic("assertion failed: " + fmt.Sprint(val)) + } +} + +func typeName(typ ast.Expr) string { + switch typ := typ.(type) { + case *ast.Ident: + return typ.Name + case *ast.StarExpr: + return "*" + typeName(typ.X) + case *ast.ArrayType: + if typ.Len != nil { + panic("unexpected array type") + } + return "[]" + typeName(typ.Elt) + case *ast.MapType: + return "map[" + typeName(typ.Key) + "]" + typeName(typ.Value) + } + panic("unexpected type") +}