const nbt = require('prismarine-nbt') module.exports = registry => { if (registry.version.type === 'pc') { const ChatMessage = require('prismarine-chat')(registry.version.majorVersion) function signValueToJSONArray (text) { const texts = [] if (typeof text === 'string') { // Sign line should look like JSON string of `{"text: "actualText"}`. Since we have plaintext, need to add in this JSON wrapper. texts.push(...text.split('\n').map((t) => (JSON.stringify({ text: t })))) } else if (Array.isArray(text)) { for (const t of text) { if (t.toJSON) { // prismarine-chat texts.push(JSON.stringify(t.toJSON())) } else if (typeof t === 'object') { // normal JS object texts.push(JSON.stringify(t)) } else { // plaintext texts.push(JSON.stringify({ text: t })) } } } return texts } function mergeNbt (obj1, obj2) { for (const [key, value] of Object.entries(obj2)) { if (!(key in obj1)) { obj1[key] = value continue } if (typeof value === 'object' && !Array.isArray(value)) mergeNbt(obj1[key], obj2[key]) } } function setSignTextForMultiSideSign (block, side, text) { const texts = signValueToJSONArray(text) if (!block.entity) { block.entity = nbt.comp({ id: nbt.string(registry.version['>=']('1.11') ? 'minecraft:sign' : 'Sign') }) } mergeNbt(block.entity, nbt.comp({ isWaxed: nbt.byte(0), back_text: nbt.comp({ has_glowing_text: nbt.byte(0), color: nbt.string('black'), messages: nbt.list(nbt.string(['{"text":""}'])) }), front_text: nbt.comp({ has_glowing_text: nbt.byte(0), color: nbt.string('black'), messages: nbt.list(nbt.string(['{"text":""}'])) }) })) block.entity.value[side].value.messages.value.value = texts } function getSignTextForMultiSideSign (block, side) { if (!block.entity) return '' return block.entity?.value?.[side]?.value?.messages?.value?.value?.map(text => typeof JSON.parse(text) === 'string' ? JSON.parse(text) : new ChatMessage(JSON.parse(text)).toString()).join('\n') ?? '' } function setSignTextForLegacySign (block, text) { const texts = signValueToJSONArray(text) if (!block.entity) { block.entity = nbt.comp({ id: nbt.string(registry.version['>=']('1.11') ? 'minecraft:sign' : 'Sign') }) } Object.assign(block.entity.value, { Text1: nbt.string(texts[0] || '""'), Text2: nbt.string(texts[1] || '""'), Text3: nbt.string(texts[2] || '""'), Text4: nbt.string(texts[3] || '""') }) } function getSignTextForLegacySign (block) { if (!block.entity) return '' const texts = [block.entity.value.Text1.value, block.entity.value.Text2.value, block.entity.value.Text3.value, block.entity.value.Text4.value].map(val => val || '"') return texts.map(text => typeof JSON.parse(text) === 'string' ? JSON.parse(text) : new ChatMessage(JSON.parse(text)).toString()).join('\n').trimEnd() } return { sign: { setSignText (front, back) { if (registry.supportFeature('multiSidedSigns')) { if (front !== undefined) setSignTextForMultiSideSign(this, 'front_text', front) if (back !== undefined) setSignTextForMultiSideSign(this, 'back_text', back) } else { if (front !== undefined) setSignTextForLegacySign(this, front) if (back !== undefined) throw new Error(`Cannot set the back text of a sign on a version before 1.20 : ${registry.version.minecraftVersion}`) } }, getSignText () { if (registry.supportFeature('multiSidedSigns')) { return [getSignTextForMultiSideSign(this, 'front_text'), getSignTextForMultiSideSign(this, 'back_text')] } else { return [getSignTextForLegacySign(this)] } }, // Deprecated APIs kept for backwards compatibility get signText () { return this.getSignText()[0] }, set signText (text) { this.setSignText(text) } } } } if (registry.version.type === 'bedrock') { return { sign: { getSignText () { if (!this.entity) return [''] return [this.entity.Text.value] }, setSignText (text) { if (!this.entity) { this.entity = nbt.comp({ id: nbt.string('Sign') }) } Object.assign(this.entity.value, { Text: nbt.string(Array.isArray(text) ? text.join('\n') : text) }) }, // Deprecated APIs kept for backwards compatibility get signText () { return this.getSignText()[0] }, set signText (text) { this.setSignText(text) } } } } }