Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Books and Quills + Written Book #608

Merged
merged 35 commits into from
Aug 20, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6ea616f
Implemented Books and Quills + Written Book
abimek Jul 28, 2022
4bc9bb0
fixing checks
abimek Jul 28, 2022
94a7650
Reordered register.go
abimek Jul 28, 2022
3678996
Documentation Fixes + Code Fixes
abimek Jul 28, 2022
ab0028c
Removal of Unnecessary Glinted Field
abimek Jul 28, 2022
81f3efe
Doc update
abimek Jul 28, 2022
3e9c4d2
removed excessive encoding field
abimek Jul 28, 2022
c71e835
Doc Changes + WrittenBookGeneration
abimek Jul 28, 2022
f4eca7b
Updates
abimek Aug 2, 2022
b36f5f8
Merge branch 'master' into feature/books
abimek Aug 2, 2022
4ea8a7a
Missing Docs
abimek Aug 2, 2022
742a00e
booo wiki
abimek Aug 2, 2022
0f8a787
Update server/item/written_book.go
JustTalDevelops Aug 2, 2022
89d78db
Merge branch 'master' into feature/books
JustTalDevelops Aug 3, 2022
f1e9f3f
server/item: Various improvements to Book and Quills.
JustTalDevelops Aug 3, 2022
32d624a
Merge branch 'master' into feature/books
JustTalDevelops Aug 7, 2022
a4ca352
item/written_book.go: Fix DecodeNBT on pages.
JustTalDevelops Aug 8, 2022
40acb60
Books and Quills are Done Now :D
abimek Aug 8, 2022
0681078
Validate Page Number within SetPage
abimek Aug 8, 2022
a671801
Merge branch 'master' into feature/books
DaPigGuy Aug 10, 2022
db551de
Update server/item/book_and_quill.go
abimek Aug 11, 2022
bef1e46
Update server/item/written_book.go
abimek Aug 11, 2022
8da9b01
Update server/session/handler_book_edit.go
abimek Aug 11, 2022
7a37c88
fix formatting
DaPigGuy Aug 11, 2022
ac21d40
Punctuation fixes.
abimek Aug 12, 2022
2cc3f04
Removes of ValidPage method for Boolean flag within Page() and use of…
abimek Aug 12, 2022
01b656a
Improved the Page method as well as the documentation.
abimek Aug 12, 2022
9afbd64
Moving Documentation for Consistency
abimek Aug 12, 2022
ea5c2bd
used duplicateStack() in order to save lore information and other ite…
abimek Aug 12, 2022
09c5122
Creation of InsertPage and DeletePage methods.
abimek Aug 12, 2022
738b9c4
Updated struct receiver variable name w -> b.
abimek Aug 12, 2022
d448ffa
Merge branch 'master' into feature/books
JustTalDevelops Aug 19, 2022
55bf763
item/book_and_quill.go: cleanup decode
DaPigGuy Aug 20, 2022
49eace2
item/written_book.go: cleanup decode
DaPigGuy Aug 20, 2022
2d6e3f3
session/handler_book_edit.go: duplicate item stack
DaPigGuy Aug 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions server/item/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func init() {
world.RegisterItem(BlazeRod{})
world.RegisterItem(Bone{})
world.RegisterItem(Book{})
world.RegisterItem(WritableBook{})
world.RegisterItem(WrittenBook{})
abimek marked this conversation as resolved.
Show resolved Hide resolved
world.RegisterItem(Bowl{})
world.RegisterItem(Charcoal{})
world.RegisterItem(DragonBreath{})
Expand Down
97 changes: 97 additions & 0 deletions server/item/writable_book.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package item

type WritableBook struct {
Pages []string
}
abimek marked this conversation as resolved.
Show resolved Hide resolved

// Page returns a specific page from the book. If the page exists, it will return the content and true, otherwise
// it will return an empty string and false.
func (w WritableBook) Page(page uint) (string, bool) {
abimek marked this conversation as resolved.
Show resolved Hide resolved
p := int(page)
if len(w.Pages) <= p {
return "", false
}
return w.Pages[p], true
}

// MaxCount always returns 1.
func (w WritableBook) MaxCount() int {
return 1
}

// Exists checks to see weather a page exists or not
func (w WritableBook) Exists(page uint) bool {
abimek marked this conversation as resolved.
Show resolved Hide resolved
return len(w.Pages) > int(page)
}

// Set writes a page to the book, if the page doesn't exist it will be created. It will panic if the
// text is longer then 256 characters. It will return the newly updated pages.
abimek marked this conversation as resolved.
Show resolved Hide resolved
func (w WritableBook) Set(page uint, text string) []string {
abimek marked this conversation as resolved.
Show resolved Hide resolved
abimek marked this conversation as resolved.
Show resolved Hide resolved
if len(text) > 256 {
panic("text longer then 256 bytes")
}
abimek marked this conversation as resolved.
Show resolved Hide resolved
pages := w.Pages
if !w.Exists(page) {
newPages := make([]string, page+1)
copy(newPages, pages)
pages = newPages
}
pages[page] = text
return pages
}

// Swap swaps two different pages, it will panic if the largest of the two numbers doesn't exist. it will
// return the newly updated pages.
func (w WritableBook) Swap(page1, page2 uint) []string {
abimek marked this conversation as resolved.
Show resolved Hide resolved
abimek marked this conversation as resolved.
Show resolved Hide resolved
pages := w.Pages
if w.Exists(max(page1, page2)) {
panic("invalid page number")
}
TwistedAsylumMC marked this conversation as resolved.
Show resolved Hide resolved
content1 := pages[page1]
content2 := pages[page2]
pages[page1] = content2
pages[page2] = content1
return pages
}

// DecodeNBT ...
func (w WritableBook) DecodeNBT(data map[string]any) any {
if pages, ok := data["pages"].([]any); ok {
for _, page := range pages {
if pageData, ok := page.(map[string]any); ok {
if text, ok := pageData["text"].(string); ok {
w.Pages = append(w.Pages, text)
}
}
}
}
return w
}

// EncodeNBT ...
func (w WritableBook) EncodeNBT() map[string]any {
if len(w.Pages) == 0 {
abimek marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
data := map[string]any{}
var pages []any
abimek marked this conversation as resolved.
Show resolved Hide resolved
for _, page := range w.Pages {
pages = append(pages, map[string]any{
abimek marked this conversation as resolved.
Show resolved Hide resolved
"text": page,
})
}
data["pages"] = pages
abimek marked this conversation as resolved.
Show resolved Hide resolved
return data
}

// max ...
func max(a, b uint) uint {
if a > b {
return a
}
return b
}

func (w WritableBook) EncodeItem() (name string, meta int16) {
abimek marked this conversation as resolved.
Show resolved Hide resolved
return "minecraft:writable_book", 0
}
62 changes: 62 additions & 0 deletions server/item/written_book.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package item

type WrittenBook struct {
Title string
Author string
Generation uint
abimek marked this conversation as resolved.
Show resolved Hide resolved
Glinted
abimek marked this conversation as resolved.
Show resolved Hide resolved
Pages []string
}
abimek marked this conversation as resolved.
Show resolved Hide resolved

// MaxCount always returns 1.
func (w WrittenBook) MaxCount() int {
return 1
}

// Page returns a specific page from the book. If the page exists, it will return the content and true, otherwise
// it will return an empty string and false.
func (w WrittenBook) Page(page uint) (string, bool) {
abimek marked this conversation as resolved.
Show resolved Hide resolved
p := int(page)
if len(w.Pages) <= p {
return "", false
}
return w.Pages[p], true
}

// DecodeNBT ...
func (w WrittenBook) DecodeNBT(data map[string]any) any {
if pages, ok := data["pages"].([]map[string]string); ok {
for i, page := range pages {
w.Pages[i] = page["text"]
}
}
if v, ok := data["title"].(string); ok {
w.Title = v
}
DaPigGuy marked this conversation as resolved.
Show resolved Hide resolved
if v, ok := data["author"].(string); ok {
w.Author = v
}
return w
}

// EncodeNBT ...
func (w WrittenBook) EncodeNBT() map[string]any {
data := map[string]any{}
var pages []map[string]string
JustTalDevelops marked this conversation as resolved.
Show resolved Hide resolved
for _, page := range w.Pages {
pages = append(pages, map[string]string{
JustTalDevelops marked this conversation as resolved.
Show resolved Hide resolved
"text": page,
"photoname": "",
abimek marked this conversation as resolved.
Show resolved Hide resolved
})
}
data["pages"] = pages
data["author"] = w.Author
data["title"] = w.Title
data["generation"] = byte(w.Generation)
return data
}

// EncodeItem ...
func (w WrittenBook) EncodeItem() (name string, meta int16) {
return "minecraft:written_book", 0
}
66 changes: 66 additions & 0 deletions server/session/handler_book_edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package session

import (
"fmt"
"github.com/df-mc/dragonfly/server/item"
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"golang.org/x/exp/slices"
)

type BookEditHandler struct{}
abimek marked this conversation as resolved.
Show resolved Hide resolved

// Handle ...
func (b BookEditHandler) Handle(p packet.Packet, s *Session) error {
JustTalDevelops marked this conversation as resolved.
Show resolved Hide resolved
abimek marked this conversation as resolved.
Show resolved Hide resolved
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.WritableBook)
if !ok {
return fmt.Errorf("inventory slot %v does not contain a writable book", pk.InventorySlot)
}
// check page number and text beforehand to reduce repetition, shouldn't matter as the default values
// match these constraints
abimek marked this conversation as resolved.
Show resolved Hide resolved
page := uint(pk.PageNumber)
if page >= 50 {
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")
}
TwistedAsylumMC marked this conversation as resolved.
Show resolved Hide resolved
var pages []string
slot := int(pk.InventorySlot)
switch pk.ActionType {
case packet.BookActionReplacePage:
pages = book.Set(page, pk.Text)
case packet.BookActionAddPage:
if !book.Exists(page) {
return fmt.Errorf("may only come before a page which already exists")
}
if len(book.Pages) >= 50 {
return fmt.Errorf("unable to add page beyond 50")
}
pages = slices.Insert(book.Pages, int(page), pk.Text)
case packet.BookActionDeletePage:
if !book.Exists(page) {
return fmt.Errorf("page number %v does not exist", pk.PageNumber)
}
pages = slices.Delete(book.Pages, int(page), int(page+1))
case packet.BookActionSwapPages:
if pk.SecondaryPageNumber >= 50 {
return fmt.Errorf("page number out of bounds")
}
if !book.Exists(page) || !book.Exists(uint(pk.SecondaryPageNumber)) {
return fmt.Errorf("page numbers do not exist")
}
pages = book.Swap(page, uint(pk.SecondaryPageNumber))
case packet.BookActionSign:
// Error does not need to be handled as it's confirmed at the begging that this slot contains a writable book.
s.inv.SetItem(slot, item.NewStack(item.WrittenBook{Title: pk.Title, Author: pk.Author, Pages: book.Pages, Generation: 0}, 1))
return nil
}
// Error does not need to be handled as it's confirmed at the begging that this slot contains a writable book.
s.inv.SetItem(slot, item.NewStack(item.WritableBook{Pages: pages}, 1))
abimek marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
1 change: 1 addition & 0 deletions server/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ func (s *Session) registerHandlers() {
packet.IDAnvilDamage: nil,
packet.IDBlockActorData: &BlockActorDataHandler{},
packet.IDBlockPickRequest: &BlockPickRequestHandler{},
packet.IDBookEdit: &BookEditHandler{},
packet.IDBossEvent: nil,
packet.IDClientCacheBlobStatus: &ClientCacheBlobStatusHandler{},
packet.IDCommandRequest: &CommandRequestHandler{},
Expand Down