26ed99fda6
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
package session
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/df-mc/dragonfly/server/item"
|
|
"github.com/df-mc/dragonfly/server/world"
|
|
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
|
|
)
|
|
|
|
// BookEditHandler handles the BookEdit packet.
|
|
type BookEditHandler struct{}
|
|
|
|
// Handle ...
|
|
func (b BookEditHandler) Handle(p packet.Packet, s *Session, _ *world.Tx, _ Controllable) error {
|
|
pk := p.(*packet.BookEdit)
|
|
|
|
it, err := s.inv.Item(int(pk.InventorySlot))
|
|
if err != nil {
|
|
return fmt.Errorf("invalid inventory slot index %v", pk.InventorySlot)
|
|
}
|
|
book, ok := it.Item().(item.BookAndQuill)
|
|
if !ok {
|
|
return fmt.Errorf("inventory slot %v does not contain a writable book", pk.InventorySlot)
|
|
}
|
|
|
|
page := int(pk.PageNumber)
|
|
if page >= 50 || page < 0 {
|
|
return fmt.Errorf("page number %v is out of bounds", pk.PageNumber)
|
|
}
|
|
if len(pk.Text) > 256 {
|
|
return fmt.Errorf("text can not be longer than 256 bytes")
|
|
}
|
|
|
|
slot := int(pk.InventorySlot)
|
|
switch pk.ActionType {
|
|
case packet.BookActionReplacePage:
|
|
book = book.SetPage(page, pk.Text)
|
|
case packet.BookActionAddPage:
|
|
if len(book.Pages) >= 50 {
|
|
return fmt.Errorf("unable to add page beyond 50")
|
|
}
|
|
if page >= len(book.Pages) && page <= len(book.Pages)+2 {
|
|
book = book.SetPage(page, "")
|
|
break
|
|
}
|
|
if _, ok := book.Page(page); !ok {
|
|
return fmt.Errorf("unable to insert page at %v", pk.PageNumber)
|
|
}
|
|
book = book.InsertPage(page, pk.Text)
|
|
case packet.BookActionDeletePage:
|
|
if _, ok := book.Page(page); !ok {
|
|
// We break here instead of returning an error because the client can be a page or two ahead in the UI then
|
|
// the actual pages representation server side. The client still sends the deletion indexes.
|
|
break
|
|
}
|
|
book = book.DeletePage(page)
|
|
case packet.BookActionSwapPages:
|
|
if pk.SecondaryPageNumber >= 50 {
|
|
return fmt.Errorf("page number out of bounds")
|
|
}
|
|
_, ok := book.Page(page)
|
|
_, ok2 := book.Page(int(pk.SecondaryPageNumber))
|
|
if !ok || !ok2 {
|
|
// We break here instead of returning an error because the client can try to swap pages that don't exist.
|
|
// This happens as a result of the client being a page or two ahead in the UI then the actual pages
|
|
// representation server side. The client still sends the swap indexes.
|
|
break
|
|
}
|
|
book = book.SwapPages(page, int(pk.SecondaryPageNumber))
|
|
case packet.BookActionSign:
|
|
_ = s.inv.SetItem(slot, it.WithItem(item.WrittenBook{Title: pk.Title, Author: pk.Author, Pages: book.Pages, Generation: item.OriginalGeneration()}))
|
|
return nil
|
|
}
|
|
_ = s.inv.SetItem(slot, it.WithItem(book))
|
|
return nil
|
|
}
|