It's been reported to me by dozens of users that use my plugin on dozens of different machines.
git-Spigot-ff439d1-24c79a1
EliteMobs
Yes
Very recently TextComponent started outputting garbage into books. I heavily rely on a wide array of features of TextComponent to write books, and I was told an update recently did some major changes to these systems. It would seem that even after the most recent patch there are still some lingering issues.
To save you some time: line 137 for the TextComponent, line 89 and on for it getting inserted into the book, line 109 for how I'm setting hover text, line 201 for generating the book itself.
Visual output:
What it is supposed to look like (still working for all users that haven't updated spigot in the last few days) :
I can reproduce the issue for components containing legacy color codes. My current guess is that the item's data is converted to Bukkit item meta and back to the Minecraft item (for example as part of Spigot's stricter item validation when the book item is sent to the client; but this also occurs in other situations). Due to some older issue, the item might contain page data in either JSON text or as legacy text. The previous approach has been to check if the data can be parsed as JSON, and otherwise assume that it is plain text. The recent change also takes into account whether the text contains color codes (https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java#111).
Since these components seem to contain color codes inside their text contents, their JSON text is currently interpreted as legacy text when the item meta is created for a given Minecraft ItemStack. A possible fix could therefore be to revert this and only check if the text can be parsed as JSON.
However, if we drop the assumption that components do not contain legacy color codes, the check for legacy color codes would then also need to be removed when we deserialize items from config files.
I will do some testing to see if I find any immediate issues with this approach and prepare a PR later.
blablubbabc
added a comment - I can reproduce the issue for components containing legacy color codes. My current guess is that the item's data is converted to Bukkit item meta and back to the Minecraft item (for example as part of Spigot's stricter item validation when the book item is sent to the client; but this also occurs in other situations). Due to some older issue, the item might contain page data in either JSON text or as legacy text. The previous approach has been to check if the data can be parsed as JSON, and otherwise assume that it is plain text. The recent change also takes into account whether the text contains color codes ( https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java#111).
Since these components seem to contain color codes inside their text contents, their JSON text is currently interpreted as legacy text when the item meta is created for a given Minecraft ItemStack. A possible fix could therefore be to revert this and only check if the text can be parsed as JSON.
However, if we drop the assumption that components do not contain legacy color codes, the check for legacy color codes would then also need to be removed when we deserialize items from config files.
I will do some testing to see if I find any immediate issues with this approach and prepare a PR later.
I've seem some old (pre 1.13) books that contain legacy color codes in components. Those books will be converted if taken in the inventory of a player and all pages will look like in the first picture.
Black Hole
added a comment - I've seem some old (pre 1.13) books that contain legacy color codes in components. Those books will be converted if taken in the inventory of a player and all pages will look like in the first picture.
{"searchers":{"groups":[{"searchers":[{"name":"Project","id":"project","key":"issue.field.project","isShown":true,"lastViewed":1743661179228,"shown":true},{"name":"Summary","id":"summary","key":"issue.field.summary","isShown":true,"shown":true},{"name":"Type","id":"issuetype","key":"issue.field.issuetype","isShown":true,"lastViewed":1743661179228,"shown":true},{"name":"Status","id":"status","key":"issue.field.status","isShown":true,"lastViewed":1743661179230,"shown":true},{"name":"Priority","id":"priority","key":"issue.field.priority","isShown":true,"shown":true},{"name":"Resolution","id":"resolution","key":"issue.field.resolution","isShown":true,"shown":true},{"name":"Creator","id":"creator","key":"issue.field.creator","isShown":true,"shown":true},{"name":"Affects Version","id":"version","key":"issue.field.affectsversions","isShown":true,"shown":true},{"name":"Fix Version","id":"fixfor","key":"issue.field.fixversions","isShown":true,"shown":true},{"name":"Component","id":"component","key":"issue.field.components","isShown":false,"shown":false},{"name":"% Limits","id":"workratio","key":"issue.field.workratio","isShown":true,"shown":true},{"name":"Link types","id":"issue_link_type","key":"issue.field.issuelinks","isShown":true,"shown":true},{"name":"Environment","id":"environment","key":"issue.field.environment","isShown":true,"shown":true},{"name":"Description","id":"description","key":"issue.field.description","isShown":true,"shown":true},{"name":"Comment","id":"comment","key":"issue.field.comment","isShown":true,"shown":true},{"name":"Label","id":"labels","key":"issue.field.labels","isShown":true,"lastViewed":1743661179230,"shown":true},{"name":"Query","id":"text","key":"text","isShown":true,"shown":true},{"name":"Business Value","id":"customfield_10003","key":"com.atlassian.jira.plugin.system.customfieldtypes:float","isShown":false,"shown":false},{"name":"Development","id":"customfield_10500","key":"com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary","isShown":true,"shown":true},{"name":"Epic Color","id":"customfield_10009","key":"com.pyxis.greenhopper.jira:gh-epic-color","isShown":false,"shown":false},{"name":"Epic Link","id":"customfield_10006","key":"com.pyxis.greenhopper.jira:gh-epic-link","isShown":true,"shown":true},{"name":"Epic Name","id":"customfield_10007","key":"com.pyxis.greenhopper.jira:gh-epic-label","isShown":true,"shown":true},{"name":"Epic Status","id":"customfield_10008","key":"com.pyxis.greenhopper.jira:gh-epic-status","isShown":false,"shown":false},{"name":"Epic/Theme","id":"customfield_10001","key":"com.atlassian.jira.plugin.system.customfieldtypes:labels","isShown":true,"shown":true},{"name":"Flagged","id":"customfield_10000","key":"com.atlassian.jira.plugin.system.customfieldtypes:multicheckboxes","isShown":true,"shown":true},{"name":"Forums Username","id":"customfield_10600","key":"com.atlassian.jira.plugin.system.customfieldtypes:textfield","isShown":false,"shown":false},{"name":"Guidelines Read","id":"customfield_10700","key":"com.atlassian.jira.plugin.system.customfieldtypes:radiobuttons","isShown":true,"shown":true},{"name":"Original story points","id":"customfield_10904","key":"com.atlassian.jpo:jpo-custom-field-original-story-points","isShown":true,"shown":true},{"name":"Parent Link","id":"customfield_10901","key":"com.atlassian.jpo:jpo-custom-field-parent","isShown":false,"shown":false},{"name":"Plugin","id":"customfield_10100","key":"com.atlassian.jira.plugin.system.customfieldtypes:textfield","isShown":true,"shown":true},{"name":"Rank","id":"customfield_10102","key":"com.pyxis.greenhopper.jira:gh-lexo-rank","isShown":true,"shown":true},{"name":"Release Version History","id":"customfield_10107","key":"com.pyxis.greenhopper.jira:greenhopper-releasedmultiversionhistory","isShown":true,"shown":true},{"name":"Sprint","id":"customfield_10005","key":"com.pyxis.greenhopper.jira:gh-sprint","isShown":true,"shown":true},{"name":"Story Points","id":"customfield_10002","key":"com.atlassian.jira.plugin.system.customfieldtypes:float","isShown":false,"shown":false},{"name":"Team","id":"customfield_10900","key":"com.atlassian.teams:rm-teams-custom-field-team","isShown":true,"shown":true},{"name":"Version","id":"customfield_10601","key":"com.atlassian.jira.plugin.system.customfieldtypes:textfield","isShown":true,"shown":true}],"type":"DETAILS","title":"Details"},{"searchers":[{"name":"Created Date","id":"created","key":"issue.field.created","isShown":true,"shown":true},{"name":"Updated Date","id":"updated","key":"issue.field.updated","isShown":true,"shown":true},{"name":"Resolution Date","id":"resolutiondate","key":"issue.field.resolution.date","isShown":true,"shown":true},{"name":"Target end","id":"customfield_10903","key":"com.atlassian.jpo:jpo-custom-field-baseline-end","isShown":true,"shown":true},{"name":"Target start","id":"customfield_10902","key":"com.atlassian.jpo:jpo-custom-field-baseline-start","isShown":true,"shown":true}],"type":"DATES","title":"Dates"},{"searchers":[{"name":"Assignee","id":"assignee","key":"issue.field.assignee","isShown":true,"lastViewed":1743661179230,"shown":true},{"name":"Reporter","id":"reporter","key":"issue.field.reporter","isShown":true,"shown":true}],"type":"PEOPLE","title":"People"}]},"values":{"issuetype":{"name":"Type","editHtml":"\n\n\n\n <div class=\"field-group aui-field-issuetype\" >\n <label for=\"searcher-type\">Type</label> <select class=\"select js-default-checkboxmultiselect\"\n id=\"searcher-type\"\n multiple=\"multiple\"\n name=\"type\"\n data-max-inline-results-displayed=\"100\"\n data-placeholder-text=\"Find Issue Types...\">\n <optgroup>\n \n <option class=\" \"\n id=\"type_-2\"\n title=\"All Standard Issue Types\"\n value=\"-2\">All Standard Issue Types</option>\n </optgroup>\n\n <optgroup label=\"Standard Issue Types\">\n \n <option class=\" imagebacked 10402 10101 10200 \"\n data-icon=\"/jira/secure/viewavatar?size=xsmall&avatarId=10303&avatarType=issuetype\"\n data-fallback-icon=\"/jira/images/icons/issuetypes/blank.png\"\n id=\"type_1\"\n title=\"Bug\"\n value=\"1\">Bug</option>\n \n <option class=\" imagebacked 10402 10200 \"\n data-icon=\"/jira/secure/viewavatar?size=xsmall&avatarId=10310&avatarType=issuetype\"\n data-fallback-icon=\"/jira/images/icons/issuetypes/blank.png\"\n id=\"type_4\"\n title=\"Improvement\"\n value=\"4\">Improvement</option>\n \n <option class=\" imagebacked 10402 10101 10200 \"\n data-icon=\"/jira/secure/viewavatar?size=xsmall&avatarId=10311&avatarType=issuetype\"\n data-fallback-icon=\"/jira/images/icons/issuetypes/blank.png\"\n id=\"type_2\"\n title=\"New Feature\"\n value=\"2\">New Feature</option>\n </optgroup>\n\n <optgroup label=\"Sub-Task Issue Types\">\n </optgroup>\n </select>\n </div>\n ","validSearcher":true,"isShown":true},"project":{"name":"Project","editHtml":" \n <div class=\"field-group aui-field-project\" >\n <label for=\"searcher-pid\">Project</label> <select class=\"js-project-checkboxmultiselect\"\n data-placeholder-text=\"Find Projects...\"\n id=\"searcher-pid\"\n multiple=\"multiple\"\n name=\"pid\">\n <optgroup label=\"Recent Projects\">\n </optgroup>\n <optgroup label=\"All Projects\" >\n \n <option data-icon=\"/jira/secure/projectavatar?pid=10100&size=small\"\n title=\"BuildTools\"\n value=\"10100\">\n BuildTools (BUILDTOOLS)\n </option>\n <option data-icon=\"/jira/secure/projectavatar?pid=10002&size=small\"\n title=\"Spigot\"\n value=\"10002\">\n Spigot (SPIGOT)\n </option>\n <option data-icon=\"/jira/secure/projectavatar?pid=10101&size=small\"\n title=\"SpigotPlugins\"\n value=\"10101\">\n SpigotPlugins (PLUG)\n </option>\n </optgroup>\n </select>\n </div>\n \n\n","validSearcher":true,"isShown":true},"assignee":{"name":"Assignee","editHtml":"\n \n <div class=\"field-group aui-field-userlist\" >\n <label for=\"searcher-assigneeSelect\">Assignee</label> <fieldset rel=\"assignee\" class=\"hidden user-group-searcher-params\">\n </fieldset>\n <select class=\"js-usergroup-checkboxmultiselect\" multiple=\"multiple\" id=\"assignee\" name=\"assignee\" data-placeholder-text=\"Enter username or group\">\n <optgroup>\n <option class=\"headerOption\" data-icon=\"https://hub.spigotmc.org/jira/secure/useravatar?size=xsmall&avatarId=10123\" value=\"empty\" title=\"Unassigned\">Unassigned</option>\n </optgroup>\n <optgroup>\n </optgroup>\n </select>\n <input type=\"hidden\" name=\"check_prev_assignee\" value=\"true\">\n </div>\n \n","validSearcher":true,"isShown":true},"status":{"name":"Status","editHtml":"\n <div class=\"field-group aui-field-constants\" >\n <label for=\"searcher-status\">Status</label> <select class=\"select js-default-checkboxmultiselectstatuslozenge\"\n data-placeholder-text=\"Find Statuses...\"\n id=\"searcher-status\"\n multiple=\"multiple\"\n name=\"status\"\n data-max-inline-results-displayed=\"100\"\n data-footer-text=\"-95 more options. Continue typing to refine further.\" data-status-lozenge=\"true\">\n <optgroup >\n <option class=\"imagebacked\" data-icon=\"/jira/images/icons/statuses/open.png\" value=\"1\" title=\"Open\" data-simple-status=\"{"id":"1","name":"Open","description":"The issue is open and ready for the assignee to start work on it.","iconUrl":"/jira/images/icons/statuses/open.png","statusCategory":{"id":2,"key":"new","colorName":"default"}}\">Open</option>\n <option class=\"imagebacked\" data-icon=\"/jira/images/icons/statuses/inprogress.png\" value=\"3\" title=\"In Progress\" data-simple-status=\"{"id":"3","name":"In Progress","description":"This issue is being actively worked on at the moment by the assignee.","iconUrl":"/jira/images/icons/statuses/inprogress.png","statusCategory":{"id":4,"key":"indeterminate","colorName":"inprogress"}}\">In Progress</option>\n <option class=\"imagebacked\" data-icon=\"/jira/images/icons/statuses/reopened.png\" value=\"4\" title=\"Reopened\" data-simple-status=\"{"id":"4","name":"Reopened","description":"This issue was once resolved, but the resolution was deemed incorrect. From here issues are either marked assigned or resolved.","iconUrl":"/jira/images/icons/statuses/reopened.png","statusCategory":{"id":2,"key":"new","colorName":"default"}}\">Reopened</option>\n <option class=\"imagebacked\" data-icon=\"/jira/images/icons/statuses/resolved.png\" value=\"5\" title=\"Resolved\" data-simple-status=\"{"id":"5","name":"Resolved","description":"A resolution has been taken, and it is awaiting verification by reporter. From here issues are either reopened, or are closed.","iconUrl":"/jira/images/icons/statuses/resolved.png","statusCategory":{"id":3,"key":"done","colorName":"success"}}\">Resolved</option>\n <option class=\"imagebacked\" data-icon=\"/jira/images/icons/statuses/closed.png\" value=\"6\" title=\"Closed\" data-simple-status=\"{"id":"6","name":"Closed","description":"The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.","iconUrl":"/jira/images/icons/statuses/closed.png","statusCategory":{"id":3,"key":"done","colorName":"success"}}\">Closed</option>\n </optgroup>\n</select>\n </div>\n \n","validSearcher":true,"isShown":true},"labels":{"name":"Label","viewHtml":" <div class=\"searcherValue\">\n \n <label class=\"fieldLabel\" for=\"fieldlabels\">Label:</label><span id=\"fieldlabels\" class=\"fieldValue\">\n \n TextComponent\n</span></div>\n","editHtml":"\n <div class=\"field-group aui-field-labels\" >\n <label for=\"searcher-labels\">Labels</label> <select class=\"js-label-checkboxmultiselect\" multiple=\"multiple\" id=\"searcher-labels\" name=\"labels\" data-placeholder-text=\"Find Labels...\">\n <option value=\"TextComponent\" title=\"TextComponent\" selected=\"selected\">TextComponent</option>\n </select>\n </div>\n \n","jql":"labels = TextComponent","validSearcher":true,"isShown":true}}}
[{"id":-1,"name":"My open issues","jql":"assignee = currentUser() AND resolution = Unresolved order by updated DESC","isSystem":true,"sharePermissions":[],"requiresLogin":true},{"id":-2,"name":"Reported by me","jql":"reporter = currentUser() order by created DESC","isSystem":true,"sharePermissions":[],"requiresLogin":true},{"id":-4,"name":"All issues","jql":"order by created DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false},{"id":-5,"name":"Open issues","jql":"resolution = Unresolved order by priority DESC,updated DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false},{"id":-9,"name":"Done issues","jql":"statusCategory = Done order by updated DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false},{"id":-3,"name":"Viewed recently","jql":"issuekey in issueHistory() order by lastViewed DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false},{"id":-6,"name":"Created recently","jql":"created >= -1w order by created DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false},{"id":-7,"name":"Resolved recently","jql":"resolutiondate >= -1w order by updated DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false},{"id":-8,"name":"Updated recently","jql":"updated >= -1w order by updated DESC","isSystem":true,"sharePermissions":[],"requiresLogin":false}]
I can reproduce the issue for components containing legacy color codes. My current guess is that the item's data is converted to Bukkit item meta and back to the Minecraft item (for example as part of Spigot's stricter item validation when the book item is sent to the client; but this also occurs in other situations). Due to some older issue, the item might contain page data in either JSON text or as legacy text. The previous approach has been to check if the data can be parsed as JSON, and otherwise assume that it is plain text. The recent change also takes into account whether the text contains color codes (https://hub.spigotmc.org/stash/projects/SPIGOT/repos/craftbukkit/browse/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java#111).
Since these components seem to contain color codes inside their text contents, their JSON text is currently interpreted as legacy text when the item meta is created for a given Minecraft ItemStack. A possible fix could therefore be to revert this and only check if the text can be parsed as JSON.
However, if we drop the assumption that components do not contain legacy color codes, the check for legacy color codes would then also need to be removed when we deserialize items from config files.
I will do some testing to see if I find any immediate issues with this approach and prepare a PR later.