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.
@@ -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: 10.0.0
17
- - name: Publish if version has been updated
18
- uses: pascalgn/npm-publish-action@4f4bf159e299f65d21cd1cbd96fc5d53228036df
19
- with: # All of theses inputs are optional
20
- tag_name: "%s"
21
- tag_message: "%s"
22
- commit_pattern: "^Release (\\S+)"
23
- env: # More info about the environment variables in the README
24
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated
25
- NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # You need to set this in your repo settings
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
@@ -26,7 +26,7 @@ const supportedColors = {
26
26
  r: 'reset'
27
27
  }
28
28
 
29
- function loader (version) {
29
+ function loader (registry) {
30
30
  class MessageBuilder {
31
31
  constructor () {
32
32
  this.with = []
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 ChatMessage = require('prismarine-chat')('1.16')
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 { MessageBuilder } = require('prismarine-chat')('1.16')
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: (mcVersion: string) => typeof ChatMessage
1
+ declare const loader: (registryOrVersion) => typeof ChatMessage
2
2
 
3
- export default loader
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
- type Language = { [key: string]: string }
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 (mcVersion) {
7
- const mcData = require('minecraft-data')(mcVersion)
8
- const defaultLang = mcData.language
9
- const { MessageBuilder } = require('./MessageBuilder')(mcVersion)
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
- // don't color code empty strings
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
- // don't add empty strings
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 => entry.toMotd(lang))
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 + '\u001b[0m'
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.6.0",
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": "^27.3.1",
28
- "mocha": "^9.1.3",
27
+ "expect": "^29.1.0",
28
+ "mocha": "^10.0.0",
29
29
  "prismarine-chat": "file:.",
30
- "standard": "^16.0.1"
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
  }
@@ -1,36 +1,102 @@
1
1
  /* eslint-env mocha */
2
+ const expect = require('expect').default
3
+ const assert = require('assert')
2
4
 
3
- const ChatMessage = require('prismarine-chat')('1.16')
4
- const expect = require('expect')
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('Parsing a chat message', () => {
7
- const msg = new ChatMessage({ text: 'Example chat message' })
8
- expect(msg.toString()).toBe('Example chat message')
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
- it('Parsing message that uses language file & numbers', () => {
11
- const msg = new ChatMessage({ italic: true, color: 'gray', translate: 'chat.type.admin', with: [{ insertion: 'ripwhitescrolls', clickEvent: { action: 'suggest_command', value: '/tell ripwhitescrolls ' }, hoverEvent: { action: 'show_entity', contents: { type: 'minecraft:player', id: '9d9e9257-b812-4332-8426-5e9a0d707392', name: { text: 'ripwhitescrolls' } } }, text: 'ripwhitescrolls' }, { translate: 'commands.clear.success.multiple', with: [256, 2] }] })
12
- // test as a string
13
- expect(msg.toString()).toBe('[ripwhitescrolls: Removed 256 items from 2 players]')
14
- // test as ansi
15
- expect(msg.toAnsi()).toBe('\u001b[37m\u001b[3m[ripwhitescrolls\u001b[0m: Removed 256\u001b[0m items from 2\u001b[0m players]\u001b[0m')
16
- // test clickEvent
17
- expect(msg.with[0].clickEvent.action).toBe('suggest_command')
18
- expect(msg.with[0].clickEvent.value).toBe('/tell ripwhitescrolls ')
19
- // test numbers
20
- expect(msg.with[1].with[0].text).toBe(256)
21
- expect(msg.with[1].with[1].text).toBe(2)
22
- })
23
- it('Parsing a chat message which is an array', () => {
24
- const msg = new ChatMessage([{ text: 'Example chat ' }, { text: 'message' }])
25
- expect(msg.toString()).toBe('Example chat message')
26
- })
27
- it('Chat Message with a single hex color', () => {
28
- const msg = new ChatMessage({ text: 'uwu', color: '#FF0000' })
29
- expect(msg.toMotd()).toBe('§#FF0000uwu§r')
30
- expect(msg.toAnsi()).toBe('\u001B[38;2;255;0;0muwu\u001B[0m\u001B[0m')
31
- })
32
- it('Chat Message with multiple hex colors', () => {
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
  })
@@ -1,6 +1,6 @@
1
1
  /* eslint-env mocha */
2
2
 
3
- const expect = require('expect')
3
+ const expect = require('expect').default
4
4
 
5
5
  describe('MessageBuilder', () => {
6
6
  describe('1.16.5', () => {