prismarine-chat 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +17 -10
- package/HISTORY.md +9 -0
- package/MessageBuilder.js +1 -1
- package/README.md +8 -2
- package/index.d.ts +11 -7
- package/index.js +38 -11
- package/package.json +5 -5
- package/test/basic.test.js +97 -31
- package/test/messagebuilder.test.js +1 -1
|
@@ -13,13 +13,20 @@ jobs:
|
|
|
13
13
|
- name: Set up Node.js
|
|
14
14
|
uses: actions/setup-node@master
|
|
15
15
|
with:
|
|
16
|
-
node-version:
|
|
17
|
-
-
|
|
18
|
-
uses:
|
|
19
|
-
with:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
node-version: 14.0.0
|
|
17
|
+
- id: publish
|
|
18
|
+
uses: JS-DevTools/npm-publish@v1
|
|
19
|
+
with:
|
|
20
|
+
token: ${{ secrets.NPM_AUTH_TOKEN }}
|
|
21
|
+
- name: Create Release
|
|
22
|
+
if: steps.publish.outputs.type != 'none'
|
|
23
|
+
id: create_release
|
|
24
|
+
uses: actions/create-release@v1
|
|
25
|
+
env:
|
|
26
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
with:
|
|
28
|
+
tag_name: ${{ steps.publish.outputs.version }}
|
|
29
|
+
release_name: Release ${{ steps.publish.outputs.version }}
|
|
30
|
+
body: ${{ steps.publish.outputs.version }}
|
|
31
|
+
draft: false
|
|
32
|
+
prerelease: false
|
package/HISTORY.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
## History
|
|
2
2
|
|
|
3
|
+
### 1.7.0
|
|
4
|
+
|
|
5
|
+
* Support 1.19 client side message formatting (@extremeheat)
|
|
6
|
+
* Fix motd color codes bleeding through their with block (@U9g)
|
|
7
|
+
|
|
8
|
+
### 1.6.1
|
|
9
|
+
|
|
10
|
+
* Update mcdata
|
|
11
|
+
|
|
3
12
|
### 1.6.0
|
|
4
13
|
|
|
5
14
|
* Added number type to getText()'s idx argument
|
package/MessageBuilder.js
CHANGED
package/README.md
CHANGED
|
@@ -12,7 +12,8 @@ A parser for a minecraft chat message
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
14
|
```js
|
|
15
|
-
const
|
|
15
|
+
const registry = require('prismarine-registry')('1.16')
|
|
16
|
+
const ChatMessage = require('prismarine-chat')(registry)
|
|
16
17
|
|
|
17
18
|
const msg = new ChatMessage({"text":"Example chat mesasge"})
|
|
18
19
|
console.log(msg.toString()) // Example chat message
|
|
@@ -60,7 +61,8 @@ Appends another ChatMessage or a string
|
|
|
60
61
|
Returns a clone of the ChatMessage
|
|
61
62
|
|
|
62
63
|
```js
|
|
63
|
-
const
|
|
64
|
+
const registry = require('prismarine-registry')('1.16')
|
|
65
|
+
const { MessageBuilder } = require('prismarine-chat')(registry)
|
|
64
66
|
|
|
65
67
|
const msg = new MessageBuilder().setText('Example chat mesasge')
|
|
66
68
|
console.log(JSON.stringify(msg)) // The string as a message component
|
|
@@ -71,6 +73,10 @@ console.log(JSON.stringify(msg)) // The string as a message component
|
|
|
71
73
|
|
|
72
74
|
Returns a prismarine-chat representation of the message recieved from the 'chat' packet, example shown [here](examples/minecraftprotocol_fromnotch/fromnotch.js)
|
|
73
75
|
|
|
76
|
+
#### static ChatMessage.fromNetwork(messageType, messageParameters)
|
|
77
|
+
|
|
78
|
+
(1.19+) Loads a chat message sent by server that needs to be formatted on client side.
|
|
79
|
+
|
|
74
80
|
### MessageBuilder()
|
|
75
81
|
|
|
76
82
|
#### setBold (val: boolean) : this
|
package/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
declare const loader: (
|
|
1
|
+
declare const loader: (registryOrVersion) => typeof ChatMessage
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare class ChatMessage {
|
|
3
|
+
declare class ChatMessage {
|
|
6
4
|
// for export
|
|
7
5
|
static MessageBuilder: typeof MessageBuilder
|
|
8
6
|
|
|
@@ -70,9 +68,7 @@ export declare class ChatMessage {
|
|
|
70
68
|
static fromNotch(str: string): ChatMessage
|
|
71
69
|
}
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
export declare class MessageBuilder {
|
|
71
|
+
declare class MessageBuilder {
|
|
76
72
|
with: string[]
|
|
77
73
|
extra: string[]
|
|
78
74
|
bold?: boolean
|
|
@@ -192,8 +188,16 @@ export declare class MessageBuilder {
|
|
|
192
188
|
str: string,
|
|
193
189
|
args?: { colorSeparator?: string }
|
|
194
190
|
): MessageBuilder
|
|
191
|
+
|
|
192
|
+
// 1.19+
|
|
193
|
+
static fromNetwork (messageType: number, parameters: Record<String, Object>): MessageBuilder
|
|
195
194
|
}
|
|
196
195
|
|
|
196
|
+
loader.ChatMessage = typeof ChatMessage
|
|
197
|
+
export = loader
|
|
198
|
+
|
|
199
|
+
type Language = { [key: string]: string }
|
|
200
|
+
|
|
197
201
|
type Color =
|
|
198
202
|
| "black"
|
|
199
203
|
| "dark_blue"
|
package/index.js
CHANGED
|
@@ -3,10 +3,10 @@ const vsprintf = require('sprintf-js').vsprintf
|
|
|
3
3
|
|
|
4
4
|
module.exports = loader
|
|
5
5
|
|
|
6
|
-
function loader (
|
|
7
|
-
const
|
|
8
|
-
const defaultLang =
|
|
9
|
-
const { MessageBuilder } = require('./MessageBuilder')(
|
|
6
|
+
function loader (registryOrVersion) {
|
|
7
|
+
const registry = typeof registryOrVersion === 'string' ? require('prismarine-registry')(registryOrVersion) : registryOrVersion
|
|
8
|
+
const defaultLang = registry.language
|
|
9
|
+
const { MessageBuilder } = require('./MessageBuilder')(registry)
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* ChatMessage Constructor
|
|
@@ -287,7 +287,8 @@ function loader (mcVersion) {
|
|
|
287
287
|
red: '§c',
|
|
288
288
|
light_purple: '§d',
|
|
289
289
|
yellow: '§e',
|
|
290
|
-
white: '§f'
|
|
290
|
+
white: '§f',
|
|
291
|
+
reset: '§r'
|
|
291
292
|
},
|
|
292
293
|
bold: '§l',
|
|
293
294
|
italic: '§o',
|
|
@@ -298,8 +299,7 @@ function loader (mcVersion) {
|
|
|
298
299
|
|
|
299
300
|
let message = Object.keys(codes).map((code) => {
|
|
300
301
|
this[code] = this[code] || parent[code]
|
|
301
|
-
|
|
302
|
-
if (!this[code] || this[code] === 'false' || this.text === '') return null
|
|
302
|
+
if (!this[code] || this[code] === 'false'/* || this.text === '' */) return null
|
|
303
303
|
if (code === 'color') {
|
|
304
304
|
// return hex codes in this format
|
|
305
305
|
if (this.color.startsWith('#')) return `§${this.color}`
|
|
@@ -308,10 +308,12 @@ function loader (mcVersion) {
|
|
|
308
308
|
return codes[code]
|
|
309
309
|
}).join('')
|
|
310
310
|
|
|
311
|
-
|
|
312
|
-
if ((typeof this.text === 'string' || typeof this.text === 'number') && this.text !== '') message += `${this.text}§r`
|
|
311
|
+
if ((typeof this.text === 'string' || typeof this.text === 'number')/* && this.text !== '' */) message += this.text
|
|
313
312
|
else if (this.with) {
|
|
314
|
-
const args = this.with.map(entry =>
|
|
313
|
+
const args = this.with.map(entry => {
|
|
314
|
+
const entryAsMotd = entry.toMotd(lang, this)
|
|
315
|
+
return entryAsMotd + (entryAsMotd.includes('§') ? '§r' + message : '')
|
|
316
|
+
})
|
|
315
317
|
const format = lang[this.translate]
|
|
316
318
|
if (!format) message += args.join('')
|
|
317
319
|
else message += vsprintf(format, args)
|
|
@@ -365,7 +367,7 @@ function loader (mcVersion) {
|
|
|
365
367
|
// ANSI from https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#rgb-colors
|
|
366
368
|
message = message.replace(hexRegex, `\u001b[38;2;${red};${green};${blue}m`)
|
|
367
369
|
}
|
|
368
|
-
return message +
|
|
370
|
+
return codes['§r'] + message + codes['§r']
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
static fromNotch (msg) {
|
|
@@ -377,6 +379,31 @@ function loader (mcVersion) {
|
|
|
377
379
|
}
|
|
378
380
|
return toRet
|
|
379
381
|
}
|
|
382
|
+
|
|
383
|
+
// 1.19 applies chat formatting on the client side. A format string is provided like in C printf
|
|
384
|
+
// syntax, including positional arguments which we poll from the supplied parameters map.
|
|
385
|
+
// For example,
|
|
386
|
+
// printf("<%s> %s" /* fmt string */, [sender], [content])
|
|
387
|
+
static fromNetwork (type, params) {
|
|
388
|
+
const msg = new ChatMessage('')
|
|
389
|
+
const format = registry.chatFormattingById[type]
|
|
390
|
+
const fstr = format.formatString
|
|
391
|
+
const slices = []
|
|
392
|
+
for (let i = 0, j = 0, k = 0; i < fstr.length; i++) {
|
|
393
|
+
const c = fstr[i]
|
|
394
|
+
const cNext = fstr[i + 1]
|
|
395
|
+
if (c === '%' && cNext === 's') {
|
|
396
|
+
slices.push(fstr.slice(j, i), new ChatMessage(params[format.parameters[k++]]))
|
|
397
|
+
i++
|
|
398
|
+
j = i + 1
|
|
399
|
+
continue
|
|
400
|
+
} else if (cNext == null) {
|
|
401
|
+
slices.push(fstr.slice(j))
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
for (const slice of slices) msg.append(slice)
|
|
405
|
+
return msg
|
|
406
|
+
}
|
|
380
407
|
}
|
|
381
408
|
|
|
382
409
|
ChatMessage.MessageBuilder = MessageBuilder
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prismarine-chat",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Wrapper for a minecraft chat message",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -24,16 +24,16 @@
|
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://github.com/PrismarineJS/prismarine-chat#readme",
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"expect": "^
|
|
28
|
-
"mocha": "^
|
|
27
|
+
"expect": "^29.1.0",
|
|
28
|
+
"mocha": "^10.0.0",
|
|
29
29
|
"prismarine-chat": "file:.",
|
|
30
|
-
"standard": "^
|
|
30
|
+
"standard": "^17.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"minecraft-data": "^2.62.1",
|
|
34
33
|
"mojangson": "^2.0.1",
|
|
35
34
|
"prismarine-item": "^1.10.0",
|
|
36
35
|
"prismarine-nbt": "^2.0.0",
|
|
36
|
+
"prismarine-registry": "^1.4.0",
|
|
37
37
|
"sprintf-js": "^1.1.2"
|
|
38
38
|
}
|
|
39
39
|
}
|
package/test/basic.test.js
CHANGED
|
@@ -1,36 +1,102 @@
|
|
|
1
1
|
/* eslint-env mocha */
|
|
2
|
+
const expect = require('expect').default
|
|
3
|
+
const assert = require('assert')
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
+
describe('Parsing chat on 1.16', function () {
|
|
6
|
+
const ChatMessage = require('prismarine-chat')('1.16')
|
|
7
|
+
it('Parsing a chat message', () => {
|
|
8
|
+
const msg = new ChatMessage({ text: 'Example chat message' })
|
|
9
|
+
expect(msg.toString()).toBe('Example chat message')
|
|
10
|
+
})
|
|
11
|
+
it('Parsing message that uses language file & numbers', () => {
|
|
12
|
+
const msg = new ChatMessage({
|
|
13
|
+
italic: true,
|
|
14
|
+
color: 'gray',
|
|
15
|
+
translate: 'chat.type.admin',
|
|
16
|
+
with: [{
|
|
17
|
+
insertion: 'ripwhitescrolls',
|
|
18
|
+
clickEvent: {
|
|
19
|
+
action: 'suggest_command',
|
|
20
|
+
value: '/tell ripwhitescrolls '
|
|
21
|
+
},
|
|
22
|
+
hoverEvent: {
|
|
23
|
+
action: 'show_entity',
|
|
24
|
+
contents: {
|
|
25
|
+
type: 'minecraft:player',
|
|
26
|
+
id: '9d9e9257-b812-4332-8426-5e9a0d707392',
|
|
27
|
+
name: {
|
|
28
|
+
text: 'ripwhitescrolls'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
text: 'ripwhitescrolls'
|
|
33
|
+
}, {
|
|
34
|
+
translate: 'commands.clear.success.multiple',
|
|
35
|
+
with: [256, 2]
|
|
36
|
+
}]
|
|
37
|
+
})
|
|
38
|
+
// test as a string
|
|
39
|
+
expect(msg.toString()).toBe('[ripwhitescrolls: Removed 256 items from 2 players]')
|
|
40
|
+
// test as motd
|
|
41
|
+
expect(msg.toMotd()).toBe('§7§o[§7§oripwhitescrolls§r§7§o: §7§oRemoved §7§o256§r§7§o items from §7§o2§r§7§o players§r§7§o]')
|
|
42
|
+
// test as ansi
|
|
43
|
+
expect(msg.toAnsi()).toBe('\u001b[0m\u001b[37m\u001b[3m[\u001b[37m\u001b[3mripwhitescrolls\u001b[0m\u001b[37m\u001b[3m: \u001b[37m\u001b[3mRemoved \u001b[37m\u001b[3m256\u001b[0m\u001b[37m\u001b[3m items from \u001b[37m\u001b[3m2\u001b[0m\u001b[37m\u001b[3m players\u001b[0m\u001b[37m\u001b[3m]\u001b[0m')
|
|
44
|
+
// test clickEvent
|
|
45
|
+
expect(msg.with[0].clickEvent.action).toBe('suggest_command')
|
|
46
|
+
expect(msg.with[0].clickEvent.value).toBe('/tell ripwhitescrolls ')
|
|
47
|
+
// test numbers
|
|
48
|
+
expect(msg.with[1].with[0].text).toBe(256)
|
|
49
|
+
expect(msg.with[1].with[1].text).toBe(2)
|
|
50
|
+
})
|
|
51
|
+
it('Parsing a chat message which is an array', () => {
|
|
52
|
+
const msg = new ChatMessage([{ text: 'Example chat ' }, { text: 'message' }])
|
|
53
|
+
expect(msg.toString()).toBe('Example chat message')
|
|
54
|
+
})
|
|
55
|
+
it('Chat Message with a single hex color', () => {
|
|
56
|
+
const msg = new ChatMessage({ text: 'uwu', color: '#FF0000' })
|
|
57
|
+
expect(msg.toMotd()).toBe('§#FF0000uwu')
|
|
58
|
+
expect(msg.toAnsi()).toBe('\u001b[0m\u001b[38;2;255;0;0muwu\u001b[0m')
|
|
59
|
+
})
|
|
60
|
+
it('Chat Message with multiple hex colors', () => {
|
|
61
|
+
const msg = new ChatMessage(['', { text: 'uwu ', color: '#FF0000' }, { text: 'owo ', color: '#0000FF' }, { text: 'uwu', color: '#FF0000' }])
|
|
62
|
+
expect(msg.toMotd()).toBe('§#FF0000uwu §#0000FFowo §#FF0000uwu')
|
|
63
|
+
expect(msg.toAnsi()).toBe('\u001b[0m\u001b[38;2;255;0;0muwu \u001b[38;2;0;0;255mowo \u001b[38;2;255;0;0muwu\u001b[0m')
|
|
64
|
+
})
|
|
65
|
+
it('parse1', () => {
|
|
66
|
+
const msg = new ChatMessage({ translate: 'chat.type.text', with: [{ text: 'IM_U9G', color: 'aqua' }, { text: 'yo sup', color: 'green' }] })
|
|
67
|
+
expect(msg.toMotd()).toBe('<§bIM_U9G§r> §ayo sup§r')
|
|
68
|
+
console.log(msg.toAnsi())
|
|
69
|
+
expect(msg.toAnsi()).toBe('\u001b[0m<\u001b[96mIM_U9G\u001b[0m> \u001b[92myo sup\u001b[0m\u001b[0m')
|
|
70
|
+
})
|
|
5
71
|
|
|
6
|
-
it('
|
|
7
|
-
|
|
8
|
-
|
|
72
|
+
it('parse2', () => {
|
|
73
|
+
const msg = new ChatMessage({ color: 'blue', translate: 'chat.type.text', with: [{ text: 'IM_U9G', color: 'aqua' }, { text: 'yo sup', color: 'green' }] })
|
|
74
|
+
expect(msg.toMotd()).toBe('§9<§bIM_U9G§r§9> §ayo sup§r§9')
|
|
75
|
+
console.log(msg.toAnsi())
|
|
76
|
+
expect(msg.toAnsi()).toBe('\u001b[0m\u001b[94m<\u001b[96mIM_U9G\u001b[0m\u001b[94m> \u001b[92myo sup\u001b[0m\u001b[94m\u001b[0m')
|
|
77
|
+
})
|
|
9
78
|
})
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const msg = new ChatMessage(['', { text: 'uwu ', color: '#FF0000' }, { text: 'owo ', color: '#0000FF' }, { text: 'uwu', color: '#FF0000' }])
|
|
34
|
-
expect(msg.toMotd()).toBe('§#FF0000uwu §r§#0000FFowo §r§#FF0000uwu§r')
|
|
35
|
-
expect(msg.toAnsi()).toBe('\u001B[38;2;255;0;0muwu \u001B[0m\u001B[38;2;0;0;255mowo \u001B[0m\u001B[38;2;255;0;0muwu\u001B[0m\u001B[0m')
|
|
79
|
+
|
|
80
|
+
describe('Client-side chat formatting', function () {
|
|
81
|
+
const sender = { insertion: 'Player', clickEvent: { action: 'suggest_command', value: '/tell Player ' }, hoverEvent: { action: 'show_entity', contents: { type: 'minecraft:player', id: '00000000-00000000-00000000-00000000', name: { text: 'Player' } } }, text: 'Player' }
|
|
82
|
+
it('loads on 1.19', function () {
|
|
83
|
+
const registry = require('prismarine-registry')('1.19')
|
|
84
|
+
const ChatMessage = require('prismarine-chat')(registry)
|
|
85
|
+
registry.loadDimensionCodec(registry.loginPacket.dimensionCodec)
|
|
86
|
+
const msg = ChatMessage.fromNetwork(registry.chatFormattingByName['minecraft:emote_command'].id, {
|
|
87
|
+
sender,
|
|
88
|
+
content: { text: 'says hi' }
|
|
89
|
+
})
|
|
90
|
+
assert.strictEqual(msg.toString(), '* Player says hi')
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('loads exotic formatting', function () {
|
|
94
|
+
const registry = require('prismarine-registry')('1.19')
|
|
95
|
+
const ChatMessage = require('prismarine-chat')(registry)
|
|
96
|
+
registry.chatFormattingById = {
|
|
97
|
+
0: { formatString: '💬 [%s] %s » %s ⏎', parameters: ['rank', 'sender', 'content'] }
|
|
98
|
+
}
|
|
99
|
+
const msg = ChatMessage.fromNetwork(0, { sender, content: { text: 'hello world !' }, rank: 'Admin' })
|
|
100
|
+
assert.strictEqual(msg.toString(), '💬 [Admin] Player » hello world ! ⏎')
|
|
101
|
+
})
|
|
36
102
|
})
|