github.com/df-mc/dragonfly@v0.9.13/server/session/handler_book_edit.go (about) 1 package session 2 3 import ( 4 "fmt" 5 "github.com/df-mc/dragonfly/server/item" 6 "github.com/sandertv/gophertunnel/minecraft/protocol/packet" 7 ) 8 9 // BookEditHandler handles the BookEdit packet. 10 type BookEditHandler struct{} 11 12 // Handle ... 13 func (b BookEditHandler) Handle(p packet.Packet, s *Session) error { 14 pk := p.(*packet.BookEdit) 15 16 it, err := s.inv.Item(int(pk.InventorySlot)) 17 if err != nil { 18 return fmt.Errorf("invalid inventory slot index %v", pk.InventorySlot) 19 } 20 book, ok := it.Item().(item.BookAndQuill) 21 if !ok { 22 return fmt.Errorf("inventory slot %v does not contain a writable book", pk.InventorySlot) 23 } 24 25 page := int(pk.PageNumber) 26 if page >= 50 || page < 0 { 27 return fmt.Errorf("page number %v is out of bounds", pk.PageNumber) 28 } 29 if len(pk.Text) > 256 { 30 return fmt.Errorf("text can not be longer than 256 bytes") 31 } 32 33 slot := int(pk.InventorySlot) 34 switch pk.ActionType { 35 case packet.BookActionReplacePage: 36 book = book.SetPage(page, pk.Text) 37 case packet.BookActionAddPage: 38 if len(book.Pages) >= 50 { 39 return fmt.Errorf("unable to add page beyond 50") 40 } 41 if page >= len(book.Pages) && page <= len(book.Pages)+2 { 42 book = book.SetPage(page, "") 43 break 44 } 45 if _, ok := book.Page(page); !ok { 46 return fmt.Errorf("unable to insert page at %v", pk.PageNumber) 47 } 48 book = book.InsertPage(page, pk.Text) 49 case packet.BookActionDeletePage: 50 if _, ok := book.Page(page); !ok { 51 // We break here instead of returning an error because the client can be a page or two ahead in the UI then 52 // the actual pages representation server side. The client still sends the deletion indexes. 53 break 54 } 55 book = book.DeletePage(page) 56 case packet.BookActionSwapPages: 57 if pk.SecondaryPageNumber >= 50 { 58 return fmt.Errorf("page number out of bounds") 59 } 60 _, ok := book.Page(page) 61 _, ok2 := book.Page(int(pk.SecondaryPageNumber)) 62 if !ok || !ok2 { 63 // We break here instead of returning an error because the client can try to swap pages that don't exist. 64 // This happens as a result of the client being a page or two ahead in the UI then the actual pages 65 // representation server side. The client still sends the swap indexes. 66 break 67 } 68 book = book.SwapPages(page, int(pk.SecondaryPageNumber)) 69 case packet.BookActionSign: 70 _ = s.inv.SetItem(slot, duplicateStack(it, item.WrittenBook{Title: pk.Title, Author: pk.Author, Pages: book.Pages, Generation: item.OriginalGeneration()})) 71 return nil 72 } 73 _ = s.inv.SetItem(slot, duplicateStack(it, book)) 74 return nil 75 }