prismarine-item 1.11.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/dependabot.yml +14 -0
- package/.github/workflows/ci.yml +25 -0
- package/.github/workflows/npm-publish.yml +25 -0
- package/README.md +174 -0
- package/example.js +21 -0
- package/index.d.ts +46 -0
- package/index.js +197 -0
- package/lib/anvil.js +173 -0
- package/package.json +41 -0
- package/test/anvil.test.js +345 -0
- package/test/basic.test.js +294 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: npm
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: daily
|
|
7
|
+
open-pull-requests-limit: 10
|
|
8
|
+
ignore:
|
|
9
|
+
- dependency-name: "@types/node"
|
|
10
|
+
versions:
|
|
11
|
+
- 15.0.0
|
|
12
|
+
- dependency-name: minecraft-data
|
|
13
|
+
versions:
|
|
14
|
+
- 2.80.0
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ master ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
node-version: [14.x]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v2
|
|
20
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
21
|
+
uses: actions/setup-node@v1
|
|
22
|
+
with:
|
|
23
|
+
node-version: ${{ matrix.node-version }}
|
|
24
|
+
- run: npm install
|
|
25
|
+
- run: npm test
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: npm-publish
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- master # Change this to your default branch
|
|
6
|
+
jobs:
|
|
7
|
+
npm-publish:
|
|
8
|
+
name: npm-publish
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- name: Checkout repository
|
|
12
|
+
uses: actions/checkout@master
|
|
13
|
+
- name: Set up Node.js
|
|
14
|
+
uses: actions/setup-node@master
|
|
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
|
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# prismarine-item
|
|
2
|
+
[](http://npmjs.com/package/prismarine-item)
|
|
3
|
+
[](https://github.com/PrismarineJS/prismarine-item/actions?query=workflow%3A%22CI%22)
|
|
4
|
+
|
|
5
|
+
Represent a minecraft item with its associated data
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
const Item = require('prismarine-item')('1.8')
|
|
11
|
+
|
|
12
|
+
const ironShovelItem = new Item(256, 1)
|
|
13
|
+
console.log(ironShovelItem)
|
|
14
|
+
|
|
15
|
+
const notchItem = Item.toNotch(ironShovelItem)
|
|
16
|
+
console.log(notchItem)
|
|
17
|
+
console.log(Item.fromNotch(notchItem))
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## API
|
|
21
|
+
|
|
22
|
+
### Item(type, count[, metadata], nbt)
|
|
23
|
+
|
|
24
|
+
#### Item.toNotch(item)
|
|
25
|
+
|
|
26
|
+
Take an `item` in the format of the minecraft packets and return an `Item` instance.
|
|
27
|
+
|
|
28
|
+
#### Item.fromNotch(item)
|
|
29
|
+
|
|
30
|
+
Take an `Item` instance and return it in the format of the minecraft packets.
|
|
31
|
+
|
|
32
|
+
### Item.anvil(itemOne, itemTwo, creative[, newName])
|
|
33
|
+
|
|
34
|
+
Take two seperate `item` instances, and makes one item using the same combining done by the vanilla anvil
|
|
35
|
+
|
|
36
|
+
### Item.equal(itemOne, itemTwo[, matchStackSize])
|
|
37
|
+
|
|
38
|
+
`itemOne` - first item
|
|
39
|
+
|
|
40
|
+
`itemTwo` - second item
|
|
41
|
+
|
|
42
|
+
`matchStackSize` - whether to check for count equality
|
|
43
|
+
|
|
44
|
+
Checks equality between two items based on itemType, count, metadata, and stringified nbt
|
|
45
|
+
|
|
46
|
+
#### item.type
|
|
47
|
+
|
|
48
|
+
Numerical id.
|
|
49
|
+
|
|
50
|
+
#### item.count
|
|
51
|
+
|
|
52
|
+
#### item.metadata
|
|
53
|
+
|
|
54
|
+
Number which represents different things depending on the item.
|
|
55
|
+
See http://www.minecraftwiki.net/wiki/Data_values#Data
|
|
56
|
+
|
|
57
|
+
#### item.nbt
|
|
58
|
+
|
|
59
|
+
Buffer.
|
|
60
|
+
|
|
61
|
+
#### item.name
|
|
62
|
+
|
|
63
|
+
#### item.displayName
|
|
64
|
+
|
|
65
|
+
#### item.stackSize
|
|
66
|
+
|
|
67
|
+
#### item.equal(otherItem)
|
|
68
|
+
|
|
69
|
+
Return true if items are equal.
|
|
70
|
+
|
|
71
|
+
#### item.durabilityUsed
|
|
72
|
+
|
|
73
|
+
A getter/setter for abstracting the underlying nbt
|
|
74
|
+
|
|
75
|
+
#### item.customName
|
|
76
|
+
|
|
77
|
+
the item's custom name (ie. anvil name)
|
|
78
|
+
|
|
79
|
+
#### item.customLore
|
|
80
|
+
|
|
81
|
+
the item's custom lore (ie. set in give command)
|
|
82
|
+
|
|
83
|
+
#### item.enchants
|
|
84
|
+
|
|
85
|
+
A getter/setter for abstracting the underlying nbt (does calculations)
|
|
86
|
+
|
|
87
|
+
#### item.repairCost
|
|
88
|
+
|
|
89
|
+
A getter/setter for abstracting the underlying nbt.
|
|
90
|
+
See https://minecraft.gamepedia.com/Anvil_mechanics#Anvil_Uses
|
|
91
|
+
|
|
92
|
+
#### item.spawnEggMobName
|
|
93
|
+
|
|
94
|
+
A getter for abstracting the underlying nbt, get's the mob name from a spawn egg Item. e.g. a zombie spawn egg on 1.8 will return `Zombie`
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
## History
|
|
98
|
+
|
|
99
|
+
## 1.11.0
|
|
100
|
+
|
|
101
|
+
* fix typings
|
|
102
|
+
* add .customLore
|
|
103
|
+
* .customName now returns null when there is no custom name
|
|
104
|
+
|
|
105
|
+
## 1.10.1
|
|
106
|
+
|
|
107
|
+
* update typings (thanks @stzups)
|
|
108
|
+
|
|
109
|
+
## 1.10.0
|
|
110
|
+
|
|
111
|
+
* add item.spawnEggMobName (thanks @U9G)
|
|
112
|
+
|
|
113
|
+
## 1.9.1
|
|
114
|
+
|
|
115
|
+
* fix item present detection (thanks @U9G)
|
|
116
|
+
|
|
117
|
+
## 1.9.0
|
|
118
|
+
|
|
119
|
+
* Revise typings (thanks @extremeheat)
|
|
120
|
+
* Revise deps (thanks @rom1504)
|
|
121
|
+
* Correctly identify null items in MC 1.13 (thanks @u9g)
|
|
122
|
+
|
|
123
|
+
## 1.8.0
|
|
124
|
+
|
|
125
|
+
* add matchStackSize option on Item.equal (thanks @u9g)
|
|
126
|
+
|
|
127
|
+
## 1.7.0
|
|
128
|
+
|
|
129
|
+
* Item.equal checks nbt equality (thanks @u9g)
|
|
130
|
+
|
|
131
|
+
## 1.6.0
|
|
132
|
+
|
|
133
|
+
* Item.anvil added, along with a ton of getters & setters for Item (thanks @u9g)
|
|
134
|
+
|
|
135
|
+
### 1.5.0
|
|
136
|
+
|
|
137
|
+
* 1.16 support (thanks @DrakoTrogdor)
|
|
138
|
+
|
|
139
|
+
### 1.4.0
|
|
140
|
+
|
|
141
|
+
* typescripts definitions (thanks @IdanHo)
|
|
142
|
+
|
|
143
|
+
### 1.3.0
|
|
144
|
+
|
|
145
|
+
* 1.15 support
|
|
146
|
+
|
|
147
|
+
### 1.2.0
|
|
148
|
+
|
|
149
|
+
* 1.14 support
|
|
150
|
+
|
|
151
|
+
### 1.1.1
|
|
152
|
+
|
|
153
|
+
* allow unknown items
|
|
154
|
+
|
|
155
|
+
### 1.1.0
|
|
156
|
+
|
|
157
|
+
* 1.13 support
|
|
158
|
+
|
|
159
|
+
### 1.0.2
|
|
160
|
+
|
|
161
|
+
* make nbt default to null
|
|
162
|
+
* display the item id if it is not found in minecraft data
|
|
163
|
+
|
|
164
|
+
### 1.0.1
|
|
165
|
+
|
|
166
|
+
* bump mcdata
|
|
167
|
+
|
|
168
|
+
### 1.0.0
|
|
169
|
+
|
|
170
|
+
* bump dependencies
|
|
171
|
+
|
|
172
|
+
### 0.0.0
|
|
173
|
+
|
|
174
|
+
* Import from mineflayer
|
package/example.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const Item = require('./')('1.8')
|
|
2
|
+
|
|
3
|
+
const ironShovelItem = new Item(256, 1)
|
|
4
|
+
|
|
5
|
+
console.log(ironShovelItem)
|
|
6
|
+
|
|
7
|
+
const notchItem = Item.toNotch(ironShovelItem)
|
|
8
|
+
console.log(notchItem)
|
|
9
|
+
|
|
10
|
+
console.log(Item.fromNotch(notchItem))
|
|
11
|
+
|
|
12
|
+
const Item113 = require('./')('1.13.2')
|
|
13
|
+
|
|
14
|
+
const ironShovelItem2 = new Item113(472, 1)
|
|
15
|
+
|
|
16
|
+
console.log(ironShovelItem2)
|
|
17
|
+
|
|
18
|
+
const notchItem2 = Item113.toNotch(ironShovelItem2)
|
|
19
|
+
console.log(notchItem2)
|
|
20
|
+
|
|
21
|
+
console.log(Item113.fromNotch(notchItem2))
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
|
|
3
|
+
import { Tags, TagType } from 'prismarine-nbt'
|
|
4
|
+
|
|
5
|
+
type ItemLike = Item | null
|
|
6
|
+
|
|
7
|
+
declare class Item {
|
|
8
|
+
constructor(type: number, count: number, metadata?: number, nbt?: object);
|
|
9
|
+
type: number;
|
|
10
|
+
slot: number;
|
|
11
|
+
count: number;
|
|
12
|
+
metadata: number;
|
|
13
|
+
nbt: Tags[TagType] | null;
|
|
14
|
+
name: string;
|
|
15
|
+
displayName: string;
|
|
16
|
+
stackSize: number;
|
|
17
|
+
durabilityUsed: number;
|
|
18
|
+
enchants: NormalizedEnchant[];
|
|
19
|
+
repairCost: number;
|
|
20
|
+
customName: string | null;
|
|
21
|
+
customLore: string | null;
|
|
22
|
+
readonly spawnEggMobName: string;
|
|
23
|
+
static equal(item1: Item, item2: Item, matchStackSize: boolean): boolean;
|
|
24
|
+
static toNotch(item: ItemLike): NotchItem;
|
|
25
|
+
static fromNotch(item: NotchItem): ItemLike;
|
|
26
|
+
static anvil (itemOne: ItemLike, itemTwo: ItemLike, creative: boolean, rename: string | undefined): { xpCost: number, item: ItemLike }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare interface NotchItem {
|
|
30
|
+
// 1.8 - 1.12
|
|
31
|
+
blockId?: number;
|
|
32
|
+
itemDamage?: number;
|
|
33
|
+
// 1.13 - 1.15
|
|
34
|
+
present?: boolean;
|
|
35
|
+
itemId?: number;
|
|
36
|
+
|
|
37
|
+
itemCount?: number;
|
|
38
|
+
nbtData?: Buffer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare interface NormalizedEnchant {
|
|
42
|
+
name: string;
|
|
43
|
+
lvl: number
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default function loader(mcVersion: string): typeof Item;
|
package/index.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
const nbt = require('prismarine-nbt')
|
|
2
|
+
function loader (version) {
|
|
3
|
+
const mcData = require('minecraft-data')(version)
|
|
4
|
+
class Item {
|
|
5
|
+
constructor (type, count, metadata, nbt) {
|
|
6
|
+
if (type == null) return
|
|
7
|
+
|
|
8
|
+
if (metadata instanceof Object && metadata !== null) {
|
|
9
|
+
nbt = metadata
|
|
10
|
+
metadata = 0
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this.type = type
|
|
14
|
+
this.count = count
|
|
15
|
+
this.metadata = metadata == null ? 0 : metadata
|
|
16
|
+
this.nbt = nbt || null
|
|
17
|
+
|
|
18
|
+
const itemEnum = mcData.findItemOrBlockById(type)
|
|
19
|
+
if (itemEnum) {
|
|
20
|
+
this.name = itemEnum.name
|
|
21
|
+
this.displayName = itemEnum.displayName
|
|
22
|
+
if ('variations' in itemEnum) {
|
|
23
|
+
for (const i in itemEnum.variations) {
|
|
24
|
+
if (itemEnum.variations[i].metadata === metadata) { this.displayName = itemEnum.variations[i].displayName }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
this.stackSize = itemEnum.stackSize
|
|
28
|
+
} else {
|
|
29
|
+
this.name = 'unknown'
|
|
30
|
+
this.displayName = 'unknown'
|
|
31
|
+
this.stackSize = 1
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static equal (item1, item2, matchStackSize = true) {
|
|
36
|
+
if (item1 == null && item2 == null) {
|
|
37
|
+
return true
|
|
38
|
+
} else if (item1 == null) {
|
|
39
|
+
return false
|
|
40
|
+
} else if (item2 == null) {
|
|
41
|
+
return false
|
|
42
|
+
} else {
|
|
43
|
+
return (item1.type === item2.type &&
|
|
44
|
+
(matchStackSize ? item1.count === item2.count : true) &&
|
|
45
|
+
item1.metadata === item2.metadata &&
|
|
46
|
+
JSON.stringify(item1.nbt) === JSON.stringify(item2.nbt))
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static toNotch (item) {
|
|
51
|
+
if (mcData.isNewerOrEqualTo('1.13')) {
|
|
52
|
+
if (item == null) return { present: false }
|
|
53
|
+
const notchItem = {
|
|
54
|
+
present: true,
|
|
55
|
+
itemId: item.type,
|
|
56
|
+
itemCount: item.count
|
|
57
|
+
}
|
|
58
|
+
if (item.nbt && item.nbt.length !== 0) { notchItem.nbtData = item.nbt }
|
|
59
|
+
return notchItem
|
|
60
|
+
} else {
|
|
61
|
+
if (item == null) return { blockId: -1 }
|
|
62
|
+
const notchItem = {
|
|
63
|
+
blockId: item.type,
|
|
64
|
+
itemCount: item.count,
|
|
65
|
+
itemDamage: item.metadata
|
|
66
|
+
}
|
|
67
|
+
if (item.nbt && item.nbt.length !== 0) { notchItem.nbtData = item.nbt }
|
|
68
|
+
return notchItem
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static fromNotch (item) {
|
|
73
|
+
if (mcData.isNewerOrEqualTo('1.14')) {
|
|
74
|
+
if (item.present === false) return null
|
|
75
|
+
return new Item(item.itemId, item.itemCount, item.nbtData)
|
|
76
|
+
} else if (mcData.isNewerOrEqualTo('1.13')) {
|
|
77
|
+
if (item.itemId === -1 || item.present === false) return null
|
|
78
|
+
return new Item(item.itemId, item.itemCount, item.nbtData)
|
|
79
|
+
} else {
|
|
80
|
+
if (item.blockId === -1) return null
|
|
81
|
+
return new Item(item.blockId, item.itemCount, item.itemDamage, item.nbtData)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get customName () {
|
|
86
|
+
if (Object.keys(this).length === 0) return null
|
|
87
|
+
return this?.nbt?.value?.display?.value?.Name?.value ?? null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
set customName (newName) {
|
|
91
|
+
if (!this.nbt) this.nbt = { name: '', type: 'compound', value: {} }
|
|
92
|
+
if (!this.nbt.value.display) this.nbt.value.display = { type: 'compound', value: {} }
|
|
93
|
+
this.nbt.value.display.value.Name = { type: 'string', value: newName }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get customLore () {
|
|
97
|
+
if (Object.keys(this).length === 0) return null
|
|
98
|
+
return this?.nbt?.value?.display?.value?.Name?.value ?? null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
set customLore (newLore) {
|
|
102
|
+
if (!this.nbt) this.nbt = { name: '', type: 'compound', value: {} }
|
|
103
|
+
if (!this.nbt.value.display) this.nbt.value.display = { type: 'compound', value: {} }
|
|
104
|
+
this.nbt.value.display.value.Lore = { type: 'string', value: newLore }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// gets the cost based on previous anvil uses
|
|
108
|
+
get repairCost () {
|
|
109
|
+
if (Object.keys(this).length === 0) return 0
|
|
110
|
+
return this?.nbt?.value?.RepairCost?.value ?? 0
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
set repairCost (value) {
|
|
114
|
+
if (!this?.nbt) this.nbt = { name: '', type: 'compound', value: {} }
|
|
115
|
+
this.nbt.value.RepairCost = { type: 'int', value }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get enchants () {
|
|
119
|
+
if (Object.keys(this).length === 0) return []
|
|
120
|
+
if (mcData.isOlderThan('1.13')) {
|
|
121
|
+
let itemEnch
|
|
122
|
+
if (this.name === 'enchanted_book' && this?.nbt?.value?.StoredEnchantments) {
|
|
123
|
+
itemEnch = nbt.simplify(this.nbt).StoredEnchantments
|
|
124
|
+
} else if (this?.nbt?.value?.ench) {
|
|
125
|
+
itemEnch = nbt.simplify(this.nbt).ench
|
|
126
|
+
} else {
|
|
127
|
+
itemEnch = []
|
|
128
|
+
}
|
|
129
|
+
return itemEnch.map(ench => ({ lvl: ench.lvl, name: mcData.enchantments[ench.id].name }))
|
|
130
|
+
} else {
|
|
131
|
+
let itemEnch = []
|
|
132
|
+
if (this?.nbt?.value?.Enchantments) {
|
|
133
|
+
itemEnch = nbt.simplify(this.nbt).Enchantments
|
|
134
|
+
} else if (this?.nbt?.value?.StoredEnchantments) {
|
|
135
|
+
itemEnch = nbt.simplify(this.nbt).StoredEnchantments
|
|
136
|
+
} else {
|
|
137
|
+
itemEnch = []
|
|
138
|
+
}
|
|
139
|
+
return itemEnch.map(ench => ({ lvl: ench.lvl, name: ench.id.replace(/minecraft:/, '') }))
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
set enchants (normalizedEnchArray) {
|
|
144
|
+
const isBook = this.name === 'enchanted_book'
|
|
145
|
+
const postEnchantChange = mcData.isOlderThan('1.13')
|
|
146
|
+
const enchListName = postEnchantChange ? 'ench' : 'Enchantments'
|
|
147
|
+
const type = postEnchantChange ? 'short' : 'string'
|
|
148
|
+
if (!this.nbt) this.nbt = { name: '', type: 'compound', value: {} }
|
|
149
|
+
|
|
150
|
+
const enchs = normalizedEnchArray.map(({ name, lvl }) => {
|
|
151
|
+
const value = postEnchantChange ? mcData.enchantmentsByName[name].id : `minecraft:${mcData.enchantmentsByName[name].name}`
|
|
152
|
+
return { id: { type, value }, lvl: { type: 'short', value: lvl } }
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
if (enchs.length !== 0) {
|
|
156
|
+
this.nbt.value[isBook ? 'StoredEnchantments' : enchListName] = { type: 'list', value: { type: 'compound', value: enchs } }
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (mcData.isNewerOrEqualTo('1.13') && mcData.itemsByName[this.name].maxDurability) this.nbt.value.Damage = { type: 'int', value: 0 }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
get durabilityUsed () {
|
|
163
|
+
if (Object.keys(this).length === 0) return null
|
|
164
|
+
if (mcData.isNewerOrEqualTo('1.13')) {
|
|
165
|
+
return this?.nbt?.value?.Damage?.value ?? 0
|
|
166
|
+
} else {
|
|
167
|
+
return this.metadata ?? 0
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
set durabilityUsed (value) {
|
|
172
|
+
if (mcData.isNewerOrEqualTo('1.13')) {
|
|
173
|
+
if (!this?.nbt) this.nbt = { name: '', type: 'compound', value: {} }
|
|
174
|
+
this.nbt.value.Damage = { type: 'int', value }
|
|
175
|
+
} else {
|
|
176
|
+
this.metadata = value
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
get spawnEggMobName () {
|
|
181
|
+
if (mcData.isOlderThan('1.9')) {
|
|
182
|
+
return mcData.entitiesArray.find(o => o.internalId === this.metadata).name
|
|
183
|
+
}
|
|
184
|
+
if (mcData.isOlderThan('1.13')) {
|
|
185
|
+
const data = nbt.simplify(this.nbt)
|
|
186
|
+
const entityName = data.EntityTag.id
|
|
187
|
+
return entityName.replace('minecraft:', '')
|
|
188
|
+
}
|
|
189
|
+
return this.name.replace('_spawn_egg', '')
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
Item.anvil = require('./lib/anvil.js')(mcData, Item)
|
|
194
|
+
return Item
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = loader
|
package/lib/anvil.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
function loader (mcData, Item) {
|
|
2
|
+
function combine (itemOne, itemTwo, creative, renamedName) {
|
|
3
|
+
const rename = typeof renamedName === 'string'
|
|
4
|
+
const data = {
|
|
5
|
+
finalEnchs: [],
|
|
6
|
+
fixedDurability: 0
|
|
7
|
+
}
|
|
8
|
+
let onlyRename = false // to tell if its just a rename
|
|
9
|
+
if (!combinePossible(itemOne, itemTwo) && itemTwo !== null) return { xpCost: 0, item: null }
|
|
10
|
+
let cost = 0
|
|
11
|
+
if (rename) {
|
|
12
|
+
onlyRename = true
|
|
13
|
+
const renameCost = getRenameCost(itemOne)
|
|
14
|
+
if (renameCost === -1) return { xpCost: 0, item: null }
|
|
15
|
+
cost += renameCost
|
|
16
|
+
}
|
|
17
|
+
if (itemOne.durabilityUsed !== 0) {
|
|
18
|
+
onlyRename = false
|
|
19
|
+
const { xpLevelCost: repairCost, fixedDurability, usedMats } = getRepairCost(itemOne, itemTwo)
|
|
20
|
+
data.fixedDurability = fixedDurability
|
|
21
|
+
data.usedMats = usedMats
|
|
22
|
+
cost += repairCost
|
|
23
|
+
}
|
|
24
|
+
if (itemTwo && (itemTwo.name === itemOne.name || itemTwo.name === 'enchanted_book')) {
|
|
25
|
+
onlyRename = false
|
|
26
|
+
const { xpLevelCost: enchantCost, finalEnchs } = combineEnchants(itemOne, itemTwo, creative)
|
|
27
|
+
data.finalEnchs = finalEnchs
|
|
28
|
+
if (enchantCost === 0 && !rename && itemOne.metadata === 0) return { xpCost: 0, item: null } // no change
|
|
29
|
+
cost += enchantCost
|
|
30
|
+
}
|
|
31
|
+
if (itemTwo === null && itemOne.customName === renamedName) return { xpCost: 0, item: null } // no change
|
|
32
|
+
cost += itemOne.repairCost + (itemTwo?.repairCost ?? 0)
|
|
33
|
+
|
|
34
|
+
if (cost > 39 && onlyRename) cost = 39
|
|
35
|
+
else if (cost >= 40) return { xpCost: 0, item: null } // show too expensive message
|
|
36
|
+
|
|
37
|
+
let finalItem = null
|
|
38
|
+
if (itemOne) {
|
|
39
|
+
finalItem = new Item(itemOne.type, itemOne.count, 0, JSON.parse(JSON.stringify(itemOne.nbt)))
|
|
40
|
+
const repairCost = Math.max(itemOne.repairCost, (itemTwo?.repairCost ?? 0)) * 2 + 1
|
|
41
|
+
if (data?.finalEnchs.length > 0) finalItem.enchants = data.finalEnchs
|
|
42
|
+
if (rename) finalItem.customName = renamedName
|
|
43
|
+
finalItem.repairCost = repairCost
|
|
44
|
+
if (itemOne.name !== 'enchanted_book') finalItem.durabilityUsed = itemOne.durabilityUsed - data.fixedDurability
|
|
45
|
+
}
|
|
46
|
+
return { xpCost: cost, item: finalItem, usedMats: data.usedMats }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @param {Item} itemOne left hand item
|
|
52
|
+
* @param {Item} itemTwo right hand item
|
|
53
|
+
* @returns {xpLevelCost, finalEnchs}
|
|
54
|
+
* xpLevelCost is enchant data that is strictly from combining enchants
|
|
55
|
+
* finalEnchs is the array of enchants on the final object
|
|
56
|
+
*/
|
|
57
|
+
function combineEnchants (itemOne, itemTwo, creative) {
|
|
58
|
+
const rightIsBook = itemTwo.name === 'enchanted_book'
|
|
59
|
+
const finalEnchs = itemOne.enchants
|
|
60
|
+
const finalEnchsByName = finalEnchs.map(x => x.name)
|
|
61
|
+
const itemTwoEnch = itemTwo.enchants
|
|
62
|
+
let xpLevelCost = 0
|
|
63
|
+
for (const ench of itemTwoEnch) {
|
|
64
|
+
const enchOnItemOne = finalEnchs.find(x => x.name === ench.name)
|
|
65
|
+
let { exclude, maxLevel, category, weight } = mcData.enchantmentsByName[ench.name]
|
|
66
|
+
const multiplier = getMultipliers(weight, rightIsBook)
|
|
67
|
+
if (!(itemOne.name === 'enchanted_book' && rightIsBook) && !mcData.itemsByName[itemOne.name].enchantCategories.includes(category) && !creative) continue
|
|
68
|
+
else if (enchOnItemOne === undefined) { // first item doesn't have this ench
|
|
69
|
+
exclude = exclude.map(name => mcData.enchantmentsByName[name].name)
|
|
70
|
+
if (exclude.some(excludedEnch => finalEnchsByName.includes(excludedEnch))) { // has an excluded enchant
|
|
71
|
+
xpLevelCost++
|
|
72
|
+
} else {
|
|
73
|
+
const finalLevel = ench.lvl
|
|
74
|
+
xpLevelCost += finalLevel * multiplier
|
|
75
|
+
finalEnchs.push({ name: ench.name, lvl: ench.lvl })
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
let finalLevel = 0
|
|
79
|
+
const itemOneLevel = enchOnItemOne.lvl
|
|
80
|
+
const itemTwoLevel = ench.lvl
|
|
81
|
+
if (itemOneLevel === itemTwoLevel) {
|
|
82
|
+
finalLevel = Math.min(itemOneLevel + 1, maxLevel)
|
|
83
|
+
enchOnItemOne.lvl = finalLevel
|
|
84
|
+
} else if (itemTwoLevel > itemOneLevel) {
|
|
85
|
+
finalLevel = itemTwoLevel
|
|
86
|
+
enchOnItemOne.lvl = finalLevel
|
|
87
|
+
} else if (itemOneLevel > itemTwoLevel) {
|
|
88
|
+
finalLevel = itemOneLevel
|
|
89
|
+
}
|
|
90
|
+
xpLevelCost += finalLevel * multiplier
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { xpLevelCost, finalEnchs }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// converts enchant weight to enchant cost multiplier
|
|
97
|
+
function getMultipliers (weight, isBook) {
|
|
98
|
+
const itemMultiplier = {
|
|
99
|
+
10: 1,
|
|
100
|
+
5: 2,
|
|
101
|
+
2: 4,
|
|
102
|
+
1: 8
|
|
103
|
+
}[weight]
|
|
104
|
+
return isBook ? Math.max(1, itemMultiplier / 2) : itemMultiplier
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
*
|
|
109
|
+
* @param {Item} itemOne left hand item
|
|
110
|
+
* @param {Item} itemTwo right hand item
|
|
111
|
+
* @returns {xpLevelCost, fixedDurability, usedMats}
|
|
112
|
+
* xpLevelCost is the number of xp levels used for repair (if any)
|
|
113
|
+
* fixedDurability is duribility after using the anvil
|
|
114
|
+
* usedMats is the number of materials used to fix the broken item (if many mats is used)
|
|
115
|
+
*/
|
|
116
|
+
function getRepairCost (itemOne, itemTwo) {
|
|
117
|
+
if (itemTwo === null) return { xpLevelCost: 0, fixedDurability: 0, usedMats: 0 } // air
|
|
118
|
+
else if (itemTwo.name === 'enchanted_book') return { xpLevelCost: 0, fixedDurability: 0, usedMats: 0 }
|
|
119
|
+
|
|
120
|
+
const maxDurability = mcData.itemsByName[itemOne.name].maxDurability
|
|
121
|
+
const durabilityLost = itemOne.durabilityUsed
|
|
122
|
+
const fixMaterials = mcData.itemsByName[itemOne.name].repairWith.concat([itemOne.name])
|
|
123
|
+
if (!fixMaterials.includes(itemTwo.name) && itemOne.name !== itemTwo.name) {
|
|
124
|
+
return 0 // Enchanted book can't fix
|
|
125
|
+
}
|
|
126
|
+
let results = {
|
|
127
|
+
fixedDurability: 0,
|
|
128
|
+
xpLevelCost: 0,
|
|
129
|
+
usedMats: 0
|
|
130
|
+
}
|
|
131
|
+
if (itemTwo.name === itemOne.name) {
|
|
132
|
+
const possibleFixedDura = Math.floor(0.12 * maxDurability) + itemTwo.metadata
|
|
133
|
+
results = {
|
|
134
|
+
fixedDurability: itemOne.metadata < possibleFixedDura ? itemOne.durabilityUsed : possibleFixedDura,
|
|
135
|
+
xpLevelCost: 2,
|
|
136
|
+
usedMats: 1
|
|
137
|
+
}
|
|
138
|
+
} else if (durabilityLost !== 0) {
|
|
139
|
+
const durabilityFixedPerMat = Math.floor(maxDurability * 0.25)
|
|
140
|
+
const matsToFullyRepair = Math.ceil(durabilityLost / durabilityFixedPerMat)
|
|
141
|
+
if (itemTwo.count > matsToFullyRepair) { // takeall of itemTwo
|
|
142
|
+
results = {
|
|
143
|
+
fixedDurability: maxDurability - itemOne.durabilityUsed,
|
|
144
|
+
xpLevelCost: matsToFullyRepair, // 1 exp lvl per mat used
|
|
145
|
+
usedMats: matsToFullyRepair
|
|
146
|
+
}
|
|
147
|
+
} else if (itemOne && itemTwo) {
|
|
148
|
+
results = {
|
|
149
|
+
fixedDurability: Math.min(itemOne.durabilityUsed, durabilityFixedPerMat * itemTwo.count),
|
|
150
|
+
xpLevelCost: itemTwo.count, // 1 exp lvl per mat used
|
|
151
|
+
usedMats: itemTwo.count
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return results
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function getRenameCost (item) {
|
|
159
|
+
if (item?.nbt?.value?.RepairCost?.value === 0x7fffffff) return -1
|
|
160
|
+
return 1
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function combinePossible (itemOne, itemTwo) {
|
|
164
|
+
if (!itemOne?.name || !itemTwo?.name || (!itemOne?.name && !itemTwo?.name)) return false
|
|
165
|
+
let fixMaterials = (mcData.itemsByName[itemOne.name].repairWith ?? []).concat([itemOne.name])
|
|
166
|
+
if (itemOne.name !== 'enchanted_book') fixMaterials = fixMaterials.concat(['enchanted_book'])
|
|
167
|
+
return fixMaterials.includes(itemTwo.name)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return combine
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
module.exports = loader
|