diff --git a/blockdata.go b/blockdata.go index 16939ab..9679109 100644 --- a/blockdata.go +++ b/blockdata.go @@ -14,22 +14,9 @@ const NodeCount = 16 * 16 * 16 func processBlockdata(p *Peer, pkt *rudp.Pkt) bool { srv := p.ServerName() - var zc uint32 - si := len(pkt.Data) - 1 - for ; si > 0; si-- { - // Check for zlib header - if pkt.Data[si] == 120 && (pkt.Data[1+si] == 0x01 || pkt.Data[1+si] == 0x9C || pkt.Data[1+si] == 0xDA) { - zc++ - } - } - - if zc == 2 { - si = 14 - // Check for zlib header - for ; !(pkt.Data[si] == 120 && (pkt.Data[1+si] == 0x01 || pkt.Data[1+si] == 0x9C || pkt.Data[1+si] == 0xDA)); si++ { - } - } else { - si = len(pkt.Data) + si := 14 + // Check for zlib header + for ; !(pkt.Data[si] == 120 && (pkt.Data[1+si] == 0x01 || pkt.Data[1+si] == 0x9C || pkt.Data[1+si] == 0xDA)); si++ { } compressedNodes := pkt.Data[13:si] @@ -64,20 +51,22 @@ func processBlockdata(p *Peer, pkt *rudp.Pkt) bool { recompNodes := recompBuf.Bytes() - if zc == 2 { - data := make([]byte, 13+len(recompNodes)+len(pkt.Data[si:])) - copy(data[:13], pkt.Data[:13]) - copy(data[13:13+len(recompNodes)], recompNodes) - copy(data[13+len(recompNodes):], pkt.Data[si:]) + data := make([]byte, 13+len(recompNodes)+len(pkt.Data[si:])) + copy(data[:13], pkt.Data[:13]) + copy(data[13:13+len(recompNodes)], recompNodes) + copy(data[13+len(recompNodes):], pkt.Data[si:]) - pkt.Data = data - } else { - data := make([]byte, 13+len(recompNodes)) - copy(data[:13], pkt.Data[:13]) - copy(data[13:], recompNodes) - - pkt.Data = data - } + pkt.Data = data + + return false +} + +func processAddnode(p *Peer, pkt *rudp.Pkt) bool { + srv := p.ServerName() + + contentID := binary.BigEndian.Uint16(pkt.Data[8:10]) + newID := nodeDefs[srv][contentID].ID() + binary.BigEndian.PutUint16(pkt.Data[8:10], newID) return false } diff --git a/command.go b/command.go index 7d8fcbe..5ed741e 100644 --- a/command.go +++ b/command.go @@ -149,6 +149,8 @@ func processPktCommand(src, dst *Peer, pkt *rudp.Pkt) bool { return processRpc(src, *pkt) case ToClientBlockdata: return processBlockdata(dst, pkt) + case ToClientAddNode: + return processAddnode(dst, pkt) default: return false } diff --git a/itemdef.go b/itemdef.go new file mode 100644 index 0000000..30841a6 --- /dev/null +++ b/itemdef.go @@ -0,0 +1,125 @@ +package main + +import ( + "bytes" + "compress/zlib" + "encoding/binary" + "io" +) + +var itemdef []byte + +type ItemDef struct { + name string + data []byte +} + +// Name returns the name of an ItemDef +func (i *ItemDef) Name() string { return i.name } + +// Data returns the actual definition +func (i *ItemDef) Data() []byte { return i.data } + +func mergeItemdefs(mgrs [][]byte) error { + var itemDefs []*ItemDef + aliases := make(map[string]string) + + // Extract definitions from CItemDefManager + for _, compressedMgr := range mgrs { + zr, err := zlib.NewReader(bytes.NewReader(compressedMgr)) + if err != nil { + return err + } + + buf := &bytes.Buffer{} + _, err = io.Copy(buf, zr) + if err != nil { + return err + } + zr.Close() + + mgr := buf.Bytes() + + count := binary.BigEndian.Uint16(mgr[1:3]) + + si := uint32(3) + ItemLoop: + for i := uint16(0); i < count; i++ { + deflen := binary.BigEndian.Uint16(mgr[si : 2+si]) + def := mgr[2+si : 2+si+uint32(deflen)] + + itemNameLen := binary.BigEndian.Uint16(def[2:4]) + itemName := string(def[4 : 4+itemNameLen]) + + for _, idef := range itemDefs { + if idef.Name() == itemName { + si += 2 + uint32(deflen) + continue ItemLoop + } + } + + itemDefs = append(itemDefs, &ItemDef{name: itemName, data: def}) + + si += 2 + uint32(deflen) + } + + aliasCount := binary.BigEndian.Uint16(mgr[si : 2+si]) + + si += 2 + for i := uint16(0); i < aliasCount; i++ { + namelen := binary.BigEndian.Uint16(mgr[si : 2+si]) + name := string(mgr[2+si : 2+si+uint32(namelen)]) + + convertlen := binary.BigEndian.Uint16(mgr[2+si+uint32(namelen) : 4+si+uint32(namelen)]) + convert := string(mgr[4+si+uint32(namelen) : 4+si+uint32(namelen)+uint32(convertlen)]) + + if aliases[name] == "" { + aliases[name] = convert + } + + si += 4 + uint32(namelen) + uint32(convertlen) + } + } + + // Merge definitions into new CItemDefManager + mgr := make([]byte, 3) + mgr[0] = uint8(0x00) + binary.BigEndian.PutUint16(mgr[1:3], uint16(len(itemDefs))) + + var allDefs []byte + for _, def := range itemDefs { + defData := make([]byte, 2+len(def.Data())) + binary.BigEndian.PutUint16(defData[0:2], uint16(len(def.Data()))) + copy(defData[2:], def.Data()) + allDefs = append(allDefs, defData...) + } + + mgr = append(mgr, allDefs...) + + aliasCount := make([]byte, 2) + binary.BigEndian.PutUint16(aliasCount, uint16(len(aliases))) + mgr = append(mgr, aliasCount...) + + for name, convert := range aliases { + namelen := make([]byte, 2) + binary.BigEndian.PutUint16(namelen, uint16(len(name))) + + convertlen := make([]byte, 2) + binary.BigEndian.PutUint16(convertlen, uint16(len(convert))) + + mgr = append(mgr, namelen...) + mgr = append(mgr, []byte(name)...) + + mgr = append(mgr, convertlen...) + mgr = append(mgr, []byte(convert)...) + } + + var compressedMgr bytes.Buffer + zw := zlib.NewWriter(&compressedMgr) + zw.Write(mgr) + zw.Close() + + itemdef = compressedMgr.Bytes() + + return nil +} diff --git a/media.go b/media.go index 5abc900..8c6d856 100644 --- a/media.go +++ b/media.go @@ -14,7 +14,7 @@ import ( ) // MediaRefetchInterval is the amount of time between media downloads -const MediaRefetchInterval = 30 * time.Second +const MediaRefetchInterval = 10 * time.Minute var media map[string]*mediaFile var tooldefs [][]byte @@ -61,7 +61,7 @@ func (p *Peer) fetchMedia() { case ToClientCraftitemdef: craftitemdefs = append(craftitemdefs, pkt.Data[2:]) case ToClientItemdef: - itemdefs = append(itemdefs, pkt.Data[2:]) + itemdefs = append(itemdefs, pkt.Data[6:]) case ToClientMovement: movement = pkt.Data[2:] case ToClientDetachedInventory: @@ -205,19 +205,17 @@ func (p *Peer) announceMedia() { <-ack } - for _, def := range itemdefs { - data := make([]byte, 2+len(def)) - data[0] = uint8(0x00) - data[1] = uint8(ToClientItemdef) - copy(data[2:], def) + data = make([]byte, 6+len(itemdef)) + data[0] = uint8(0x00) + data[1] = uint8(ToClientItemdef) + binary.BigEndian.PutUint32(data[2:6], uint32(len(itemdef))) + copy(data[6:], itemdef) - ack, err := p.Send(rudp.Pkt{Data: data}) - if err != nil { - log.Print(err) - continue - } - <-ack + ack, err = p.Send(rudp.Pkt{Data: data}) + if err != nil { + log.Print(err) } + <-ack p.updateDetachedInvs(srvname) @@ -438,6 +436,10 @@ func loadMedia() { } } + if err := mergeItemdefs(itemdefs); err != nil { + log.Fatal(err) + } + updateMediaCache() } diff --git a/nodedef.go b/nodedef.go index 864f087..99edf74 100644 --- a/nodedef.go +++ b/nodedef.go @@ -38,7 +38,7 @@ func mergeNodedefs(mgrs map[string][]byte) error { var nextID uint16 - // Extract definitions from NodeDefMgrs + // Extract definitions from NodeDefManagers for srv, compressedMgr := range mgrs { if nodeDefs[srv] == nil { nodeDefs[srv] = make(map[uint16]*NodeDef) @@ -96,7 +96,7 @@ func mergeNodedefs(mgrs map[string][]byte) error { } } - // Merge definitions into new NodeDefMgr + // Merge definitions into new NodeDefManager mgr := make([]byte, 7) mgr[0] = uint8(1) binary.BigEndian.PutUint16(mgr[1:3], total)