@occultus/toolkit 0.23.4 → 0.24.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/LICENSE +9 -9
- package/README.md +30 -30
- package/package.json +2 -2
- package/src/entity/EntitiesUtils.ts +121 -121
- package/src/entity/entityUtils.ts +327 -327
- package/src/entity/health.ts +71 -71
- package/src/identifier/namespace.ts +23 -23
- package/src/index.ts +10 -9
- package/src/item/container.ts +227 -227
- package/src/item/cooldown.ts +26 -26
- package/src/item/item.ts +98 -98
- package/tsconfig.json +21 -21
package/src/entity/health.ts
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Entity,
|
|
3
|
-
EntityComponentTypes,
|
|
4
|
-
EntityHealthComponent
|
|
5
|
-
} from "@minecraft/server";
|
|
6
|
-
import { OccultusSDKError } from "@occultus/core";
|
|
7
|
-
|
|
8
|
-
export class EntityHealthUtils {
|
|
9
|
-
private readonly component: EntityHealthComponent;
|
|
10
|
-
public constructor(entity: Entity) {
|
|
11
|
-
this.component =
|
|
12
|
-
entity.getComponent(EntityComponentTypes.Health) ??
|
|
13
|
-
(() => {
|
|
14
|
-
throw new OccultusSDKError(
|
|
15
|
-
`Entity ${entity.typeId} (id ${entity.id}) 没有 EntityHealthComponent!`
|
|
16
|
-
);
|
|
17
|
-
})();
|
|
18
|
-
}
|
|
19
|
-
// 对于 component 方法的重载,便于直接代替原来的 component
|
|
20
|
-
public get current() {
|
|
21
|
-
return this.component.currentValue;
|
|
22
|
-
}
|
|
23
|
-
public set current(value: number) {
|
|
24
|
-
this.component.setCurrentValue(value);
|
|
25
|
-
}
|
|
26
|
-
public get default() {
|
|
27
|
-
return this.component.defaultValue;
|
|
28
|
-
}
|
|
29
|
-
public get max() {
|
|
30
|
-
return this.component.effectiveMax;
|
|
31
|
-
}
|
|
32
|
-
public get min() {
|
|
33
|
-
return this.component.effectiveMin;
|
|
34
|
-
}
|
|
35
|
-
public reset() {
|
|
36
|
-
this.component.resetToDefaultValue();
|
|
37
|
-
}
|
|
38
|
-
public setMax() {
|
|
39
|
-
this.component.resetToMaxValue();
|
|
40
|
-
}
|
|
41
|
-
public setMin() {
|
|
42
|
-
this.component.resetToMinValue();
|
|
43
|
-
}
|
|
44
|
-
// 重载结束
|
|
45
|
-
/**
|
|
46
|
-
* 恢复实体的生命值
|
|
47
|
-
* @param amount 恢复的生命值。小于 0 时为未定义行为
|
|
48
|
-
* @return 治愈后的生命值
|
|
49
|
-
*/
|
|
50
|
-
public heal(value: number): number {
|
|
51
|
-
const newValue = this.current + value;
|
|
52
|
-
return (this.current = Math.min(newValue, this.max));
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* 消耗实体生命值,这一行为不会被视为攻击
|
|
56
|
-
* @param value 伤害大小。小于 0 时为未定义行为
|
|
57
|
-
* @returns
|
|
58
|
-
*/
|
|
59
|
-
public damage(value: number) {
|
|
60
|
-
const newValue = this.current - value;
|
|
61
|
-
return (this.current = Math.max(newValue, this.min));
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 以指定倍率消耗实体的生命值,这一行为不会被视为攻击
|
|
65
|
-
* @param amplifier 消耗生命的倍率,例如`0.8`将会被视为消耗实体当前 80% 的生命值
|
|
66
|
-
* @returns
|
|
67
|
-
*/
|
|
68
|
-
public damageWithAmplifier(amplifier: number): number {
|
|
69
|
-
return this.damage(this.current * amplifier);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
EntityComponentTypes,
|
|
4
|
+
EntityHealthComponent
|
|
5
|
+
} from "@minecraft/server";
|
|
6
|
+
import { OccultusSDKError } from "@occultus/core";
|
|
7
|
+
|
|
8
|
+
export class EntityHealthUtils {
|
|
9
|
+
private readonly component: EntityHealthComponent;
|
|
10
|
+
public constructor(entity: Entity) {
|
|
11
|
+
this.component =
|
|
12
|
+
entity.getComponent(EntityComponentTypes.Health) ??
|
|
13
|
+
(() => {
|
|
14
|
+
throw new OccultusSDKError(
|
|
15
|
+
`Entity ${entity.typeId} (id ${entity.id}) 没有 EntityHealthComponent!`
|
|
16
|
+
);
|
|
17
|
+
})();
|
|
18
|
+
}
|
|
19
|
+
// 对于 component 方法的重载,便于直接代替原来的 component
|
|
20
|
+
public get current() {
|
|
21
|
+
return this.component.currentValue;
|
|
22
|
+
}
|
|
23
|
+
public set current(value: number) {
|
|
24
|
+
this.component.setCurrentValue(value);
|
|
25
|
+
}
|
|
26
|
+
public get default() {
|
|
27
|
+
return this.component.defaultValue;
|
|
28
|
+
}
|
|
29
|
+
public get max() {
|
|
30
|
+
return this.component.effectiveMax;
|
|
31
|
+
}
|
|
32
|
+
public get min() {
|
|
33
|
+
return this.component.effectiveMin;
|
|
34
|
+
}
|
|
35
|
+
public reset() {
|
|
36
|
+
this.component.resetToDefaultValue();
|
|
37
|
+
}
|
|
38
|
+
public setMax() {
|
|
39
|
+
this.component.resetToMaxValue();
|
|
40
|
+
}
|
|
41
|
+
public setMin() {
|
|
42
|
+
this.component.resetToMinValue();
|
|
43
|
+
}
|
|
44
|
+
// 重载结束
|
|
45
|
+
/**
|
|
46
|
+
* 恢复实体的生命值
|
|
47
|
+
* @param amount 恢复的生命值。小于 0 时为未定义行为
|
|
48
|
+
* @return 治愈后的生命值
|
|
49
|
+
*/
|
|
50
|
+
public heal(value: number): number {
|
|
51
|
+
const newValue = this.current + value;
|
|
52
|
+
return (this.current = Math.min(newValue, this.max));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 消耗实体生命值,这一行为不会被视为攻击
|
|
56
|
+
* @param value 伤害大小。小于 0 时为未定义行为
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
public damage(value: number) {
|
|
60
|
+
const newValue = this.current - value;
|
|
61
|
+
return (this.current = Math.max(newValue, this.min));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 以指定倍率消耗实体的生命值,这一行为不会被视为攻击
|
|
65
|
+
* @param amplifier 消耗生命的倍率,例如`0.8`将会被视为消耗实体当前 80% 的生命值
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
public damageWithAmplifier(amplifier: number): number {
|
|
69
|
+
return this.damage(this.current * amplifier);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 确保命名空间存在,若不存在则自动加上`minecraft:`命名空间
|
|
3
|
-
* @param identifier 要检查的标识符
|
|
4
|
-
* @return 存在命名空间的标识符
|
|
5
|
-
*/
|
|
6
|
-
export function ensureNamespace(identifier: string): string {
|
|
7
|
-
if (identifier.includes(":")) {
|
|
8
|
-
return identifier;
|
|
9
|
-
}
|
|
10
|
-
return `minecraft:${identifier}`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 确保命名空间**不**存在,若存在则自动去掉命名空间
|
|
15
|
-
* @param identifier 要检查的标识符
|
|
16
|
-
* @return 不存在命名空间的标识符
|
|
17
|
-
*/
|
|
18
|
-
export function ensureNoNamespace(identifier: string): string {
|
|
19
|
-
if (identifier.includes(":")) {
|
|
20
|
-
return identifier.split(":")[1];
|
|
21
|
-
}
|
|
22
|
-
return identifier;
|
|
23
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 确保命名空间存在,若不存在则自动加上`minecraft:`命名空间
|
|
3
|
+
* @param identifier 要检查的标识符
|
|
4
|
+
* @return 存在命名空间的标识符
|
|
5
|
+
*/
|
|
6
|
+
export function ensureNamespace(identifier: string): string {
|
|
7
|
+
if (identifier.includes(":")) {
|
|
8
|
+
return identifier;
|
|
9
|
+
}
|
|
10
|
+
return `minecraft:${identifier}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 确保命名空间**不**存在,若存在则自动去掉命名空间
|
|
15
|
+
* @param identifier 要检查的标识符
|
|
16
|
+
* @return 不存在命名空间的标识符
|
|
17
|
+
*/
|
|
18
|
+
export function ensureNoNamespace(identifier: string): string {
|
|
19
|
+
if (identifier.includes(":")) {
|
|
20
|
+
return identifier.split(":")[1];
|
|
21
|
+
}
|
|
22
|
+
return identifier;
|
|
23
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module toolkit
|
|
3
|
-
*/
|
|
4
|
-
export * from "./entity/EntitiesUtils";
|
|
5
|
-
export * from "./entity/entityUtils";
|
|
6
|
-
export * from "./
|
|
7
|
-
export * from "./item/
|
|
8
|
-
export * from "./
|
|
9
|
-
export * from "./
|
|
1
|
+
/**
|
|
2
|
+
* @module toolkit
|
|
3
|
+
*/
|
|
4
|
+
export * from "./entity/EntitiesUtils";
|
|
5
|
+
export * from "./entity/entityUtils";
|
|
6
|
+
export * from "./entity/health";
|
|
7
|
+
export * from "./item/item";
|
|
8
|
+
export * from "./item/container";
|
|
9
|
+
export * from "./identifier/namespace";
|
|
10
|
+
export * from "./item/cooldown";
|
package/src/item/container.ts
CHANGED
|
@@ -1,227 +1,227 @@
|
|
|
1
|
-
import { Container, EquipmentSlot, ItemStack, Player } from "@minecraft/server";
|
|
2
|
-
import {
|
|
3
|
-
getContainer,
|
|
4
|
-
getEquipmentItem,
|
|
5
|
-
setEquipmentItem
|
|
6
|
-
} from "../entity/entityUtils";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 获取容器中指定含指定物品标签的物品的数量
|
|
10
|
-
* @param container 容器对象
|
|
11
|
-
* @param tag 要获取的物品标签
|
|
12
|
-
* @returns 容器中指定物品的数量
|
|
13
|
-
* @author RawDiamondMC, FangLiulii
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export function getTagItemAmountInContainer(
|
|
17
|
-
container: Container,
|
|
18
|
-
tag: string
|
|
19
|
-
): number {
|
|
20
|
-
let amount = 0;
|
|
21
|
-
for (let slot = 0; slot < container.size; slot++) {
|
|
22
|
-
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
23
|
-
if (itemStack?.hasTag(tag)) {
|
|
24
|
-
amount += itemStack.amount;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return amount;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* 从容器中移除指定数量的含有特定标签的物品
|
|
32
|
-
* @param container 容器对象
|
|
33
|
-
* @param tag 物品标签
|
|
34
|
-
* @param amount 要移除物品的数量
|
|
35
|
-
* @author RawDiamondMC, FangLiulii
|
|
36
|
-
*/
|
|
37
|
-
export function removeTagItemInContainer(
|
|
38
|
-
container: Container,
|
|
39
|
-
tag: string,
|
|
40
|
-
amount: number
|
|
41
|
-
): void {
|
|
42
|
-
for (let slot = 0; slot < container.size; slot++) {
|
|
43
|
-
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
44
|
-
if (itemStack?.hasTag(tag)) {
|
|
45
|
-
if (itemStack.amount > amount) {
|
|
46
|
-
itemStack.amount -= amount;
|
|
47
|
-
container.setItem(slot, itemStack);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
container.setItem(slot);
|
|
51
|
-
amount -= itemStack.amount;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 获取容器中指定物品的数量
|
|
58
|
-
* @param container 容器对象
|
|
59
|
-
* @param typeId 要获取的物品 ID
|
|
60
|
-
* @returns 容器中指定物品的数量
|
|
61
|
-
* @author RawDiamondMC
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
|
-
export function getItemAmountInContainer(
|
|
65
|
-
container: Container,
|
|
66
|
-
typeId: string
|
|
67
|
-
): number {
|
|
68
|
-
let amount = 0;
|
|
69
|
-
for (let slot = 0; slot < container.size; slot++) {
|
|
70
|
-
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
71
|
-
if (itemStack?.typeId === typeId) {
|
|
72
|
-
amount += itemStack.amount;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return amount;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* 获取玩家身上的所有物品(包含装备栏与副手)
|
|
80
|
-
* @param player 玩家对象
|
|
81
|
-
* @param typeId 要获取的物品 ID
|
|
82
|
-
* @returns 容器中指定物品的数量
|
|
83
|
-
* @author RawDiamondMC
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
export function getItemAmountOfPlayer(player: Player, typeId: string): number {
|
|
87
|
-
const container = player.getComponent("minecraft:inventory")?.container;
|
|
88
|
-
if (!container) return 0;
|
|
89
|
-
let amount = getItemAmountInContainer(container, typeId);
|
|
90
|
-
// 不包含主手,防止重复计算
|
|
91
|
-
const slots = [
|
|
92
|
-
EquipmentSlot.Head,
|
|
93
|
-
EquipmentSlot.Chest,
|
|
94
|
-
EquipmentSlot.Legs,
|
|
95
|
-
EquipmentSlot.Feet,
|
|
96
|
-
EquipmentSlot.Offhand
|
|
97
|
-
];
|
|
98
|
-
for (const slot of slots) {
|
|
99
|
-
const itemStack = getEquipmentItem(player, slot);
|
|
100
|
-
if (itemStack?.typeId === typeId) {
|
|
101
|
-
amount += itemStack.amount;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return amount;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* 从容器中移除指定数量的物品
|
|
109
|
-
* @param container 容器对象
|
|
110
|
-
* @param typeId 物品 ID
|
|
111
|
-
* @param amount 要移除物品的数量
|
|
112
|
-
* @returns 未能够移除完的物品数量
|
|
113
|
-
* @author RawDiamondMC
|
|
114
|
-
*/
|
|
115
|
-
export function removeItemInContainer(
|
|
116
|
-
container: Container,
|
|
117
|
-
typeId: string,
|
|
118
|
-
amount: number
|
|
119
|
-
): number {
|
|
120
|
-
for (let slot = 0; slot < container.size; slot++) {
|
|
121
|
-
// 物品已经移除完毕
|
|
122
|
-
if (amount <= 0) return 0;
|
|
123
|
-
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
124
|
-
if (itemStack?.typeId === typeId) {
|
|
125
|
-
// 这个槽位的物品数量足够移除
|
|
126
|
-
if (itemStack.amount > amount) {
|
|
127
|
-
itemStack.amount -= amount;
|
|
128
|
-
container.setItem(slot, itemStack);
|
|
129
|
-
// 直接返回,因为肯定移除完毕了
|
|
130
|
-
return 0;
|
|
131
|
-
}
|
|
132
|
-
container.setItem(slot);
|
|
133
|
-
amount -= itemStack.amount;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return amount;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* 从玩家身上移除一定量的物品
|
|
141
|
-
* @param player 玩家对象
|
|
142
|
-
* @param typeId 物品 ID
|
|
143
|
-
* @param amount 要移除物品的数量
|
|
144
|
-
* @returns 未能够移除完的物品数量
|
|
145
|
-
* @author RawDiamondMC
|
|
146
|
-
*/
|
|
147
|
-
export function removeItemOfPlayer(
|
|
148
|
-
player: Player,
|
|
149
|
-
typeId: string,
|
|
150
|
-
amount: number
|
|
151
|
-
): number {
|
|
152
|
-
// 玩家肯定得有inventory组件
|
|
153
|
-
let remaining = removeItemInContainer(getContainer(player)!, typeId, amount);
|
|
154
|
-
// 已经移除完毕
|
|
155
|
-
if (remaining <= 0) return 0;
|
|
156
|
-
// 不包含主手,防止重复计算
|
|
157
|
-
const slots = [
|
|
158
|
-
EquipmentSlot.Head,
|
|
159
|
-
EquipmentSlot.Chest,
|
|
160
|
-
EquipmentSlot.Legs,
|
|
161
|
-
EquipmentSlot.Feet,
|
|
162
|
-
EquipmentSlot.Offhand
|
|
163
|
-
];
|
|
164
|
-
for (const slot of slots) {
|
|
165
|
-
// 物品已经移除完毕
|
|
166
|
-
if (remaining <= 0) return 0;
|
|
167
|
-
const itemStack = getEquipmentItem(player, slot);
|
|
168
|
-
if (itemStack?.typeId === typeId) {
|
|
169
|
-
// 这个槽位的物品数量足够移除
|
|
170
|
-
if (itemStack.amount > remaining) {
|
|
171
|
-
itemStack.amount -= remaining;
|
|
172
|
-
setEquipmentItem(player, itemStack, slot);
|
|
173
|
-
// 直接返回,因为肯定移除完毕了
|
|
174
|
-
return 0;
|
|
175
|
-
}
|
|
176
|
-
setEquipmentItem(player, itemStack, slot);
|
|
177
|
-
remaining -= itemStack.amount;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return remaining;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* 在容器中查找替换物品
|
|
185
|
-
* @param item 要替换的物品,如果为`undefined`,则替换所有空槽
|
|
186
|
-
* @param newItem 替换后的物品,如果为`undefined`,则清空所有物品
|
|
187
|
-
* @param container 要搜索的容器
|
|
188
|
-
* @author RawDiamondMC
|
|
189
|
-
*/
|
|
190
|
-
export function replaceItemStack(
|
|
191
|
-
item: ItemStack | undefined,
|
|
192
|
-
newItem: ItemStack | undefined,
|
|
193
|
-
container: Container
|
|
194
|
-
): number {
|
|
195
|
-
let amount = 0;
|
|
196
|
-
for (let slot = 0; slot < container.size; slot++) {
|
|
197
|
-
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
198
|
-
if (itemStack?.typeId === item?.typeId) {
|
|
199
|
-
container.setItem(slot, newItem);
|
|
200
|
-
amount++;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return amount;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* 在容器中根据标签查找替换物品
|
|
208
|
-
* @param itemTag 要替换的物品标签
|
|
209
|
-
* @param newItem 替换后的物品,如果为`undefined`,则清空所有物品
|
|
210
|
-
* @param container 要搜索的容器
|
|
211
|
-
*/
|
|
212
|
-
|
|
213
|
-
export function replaceItemByTag(
|
|
214
|
-
itemTag: string,
|
|
215
|
-
newItem: ItemStack | undefined,
|
|
216
|
-
container: Container
|
|
217
|
-
): number {
|
|
218
|
-
let amount = 0;
|
|
219
|
-
for (let slot = 0; slot < container.size; slot++) {
|
|
220
|
-
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
221
|
-
if (itemStack?.hasTag(itemTag)) {
|
|
222
|
-
container.setItem(slot, newItem);
|
|
223
|
-
amount++;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return amount;
|
|
227
|
-
}
|
|
1
|
+
import { Container, EquipmentSlot, ItemStack, Player } from "@minecraft/server";
|
|
2
|
+
import {
|
|
3
|
+
getContainer,
|
|
4
|
+
getEquipmentItem,
|
|
5
|
+
setEquipmentItem
|
|
6
|
+
} from "../entity/entityUtils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 获取容器中指定含指定物品标签的物品的数量
|
|
10
|
+
* @param container 容器对象
|
|
11
|
+
* @param tag 要获取的物品标签
|
|
12
|
+
* @returns 容器中指定物品的数量
|
|
13
|
+
* @author RawDiamondMC, FangLiulii
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export function getTagItemAmountInContainer(
|
|
17
|
+
container: Container,
|
|
18
|
+
tag: string
|
|
19
|
+
): number {
|
|
20
|
+
let amount = 0;
|
|
21
|
+
for (let slot = 0; slot < container.size; slot++) {
|
|
22
|
+
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
23
|
+
if (itemStack?.hasTag(tag)) {
|
|
24
|
+
amount += itemStack.amount;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return amount;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 从容器中移除指定数量的含有特定标签的物品
|
|
32
|
+
* @param container 容器对象
|
|
33
|
+
* @param tag 物品标签
|
|
34
|
+
* @param amount 要移除物品的数量
|
|
35
|
+
* @author RawDiamondMC, FangLiulii
|
|
36
|
+
*/
|
|
37
|
+
export function removeTagItemInContainer(
|
|
38
|
+
container: Container,
|
|
39
|
+
tag: string,
|
|
40
|
+
amount: number
|
|
41
|
+
): void {
|
|
42
|
+
for (let slot = 0; slot < container.size; slot++) {
|
|
43
|
+
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
44
|
+
if (itemStack?.hasTag(tag)) {
|
|
45
|
+
if (itemStack.amount > amount) {
|
|
46
|
+
itemStack.amount -= amount;
|
|
47
|
+
container.setItem(slot, itemStack);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
container.setItem(slot);
|
|
51
|
+
amount -= itemStack.amount;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 获取容器中指定物品的数量
|
|
58
|
+
* @param container 容器对象
|
|
59
|
+
* @param typeId 要获取的物品 ID
|
|
60
|
+
* @returns 容器中指定物品的数量
|
|
61
|
+
* @author RawDiamondMC
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
export function getItemAmountInContainer(
|
|
65
|
+
container: Container,
|
|
66
|
+
typeId: string
|
|
67
|
+
): number {
|
|
68
|
+
let amount = 0;
|
|
69
|
+
for (let slot = 0; slot < container.size; slot++) {
|
|
70
|
+
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
71
|
+
if (itemStack?.typeId === typeId) {
|
|
72
|
+
amount += itemStack.amount;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return amount;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 获取玩家身上的所有物品(包含装备栏与副手)
|
|
80
|
+
* @param player 玩家对象
|
|
81
|
+
* @param typeId 要获取的物品 ID
|
|
82
|
+
* @returns 容器中指定物品的数量
|
|
83
|
+
* @author RawDiamondMC
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
export function getItemAmountOfPlayer(player: Player, typeId: string): number {
|
|
87
|
+
const container = player.getComponent("minecraft:inventory")?.container;
|
|
88
|
+
if (!container) return 0;
|
|
89
|
+
let amount = getItemAmountInContainer(container, typeId);
|
|
90
|
+
// 不包含主手,防止重复计算
|
|
91
|
+
const slots = [
|
|
92
|
+
EquipmentSlot.Head,
|
|
93
|
+
EquipmentSlot.Chest,
|
|
94
|
+
EquipmentSlot.Legs,
|
|
95
|
+
EquipmentSlot.Feet,
|
|
96
|
+
EquipmentSlot.Offhand
|
|
97
|
+
];
|
|
98
|
+
for (const slot of slots) {
|
|
99
|
+
const itemStack = getEquipmentItem(player, slot);
|
|
100
|
+
if (itemStack?.typeId === typeId) {
|
|
101
|
+
amount += itemStack.amount;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return amount;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 从容器中移除指定数量的物品
|
|
109
|
+
* @param container 容器对象
|
|
110
|
+
* @param typeId 物品 ID
|
|
111
|
+
* @param amount 要移除物品的数量
|
|
112
|
+
* @returns 未能够移除完的物品数量
|
|
113
|
+
* @author RawDiamondMC
|
|
114
|
+
*/
|
|
115
|
+
export function removeItemInContainer(
|
|
116
|
+
container: Container,
|
|
117
|
+
typeId: string,
|
|
118
|
+
amount: number
|
|
119
|
+
): number {
|
|
120
|
+
for (let slot = 0; slot < container.size; slot++) {
|
|
121
|
+
// 物品已经移除完毕
|
|
122
|
+
if (amount <= 0) return 0;
|
|
123
|
+
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
124
|
+
if (itemStack?.typeId === typeId) {
|
|
125
|
+
// 这个槽位的物品数量足够移除
|
|
126
|
+
if (itemStack.amount > amount) {
|
|
127
|
+
itemStack.amount -= amount;
|
|
128
|
+
container.setItem(slot, itemStack);
|
|
129
|
+
// 直接返回,因为肯定移除完毕了
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
container.setItem(slot);
|
|
133
|
+
amount -= itemStack.amount;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return amount;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 从玩家身上移除一定量的物品
|
|
141
|
+
* @param player 玩家对象
|
|
142
|
+
* @param typeId 物品 ID
|
|
143
|
+
* @param amount 要移除物品的数量
|
|
144
|
+
* @returns 未能够移除完的物品数量
|
|
145
|
+
* @author RawDiamondMC
|
|
146
|
+
*/
|
|
147
|
+
export function removeItemOfPlayer(
|
|
148
|
+
player: Player,
|
|
149
|
+
typeId: string,
|
|
150
|
+
amount: number
|
|
151
|
+
): number {
|
|
152
|
+
// 玩家肯定得有inventory组件
|
|
153
|
+
let remaining = removeItemInContainer(getContainer(player)!, typeId, amount);
|
|
154
|
+
// 已经移除完毕
|
|
155
|
+
if (remaining <= 0) return 0;
|
|
156
|
+
// 不包含主手,防止重复计算
|
|
157
|
+
const slots = [
|
|
158
|
+
EquipmentSlot.Head,
|
|
159
|
+
EquipmentSlot.Chest,
|
|
160
|
+
EquipmentSlot.Legs,
|
|
161
|
+
EquipmentSlot.Feet,
|
|
162
|
+
EquipmentSlot.Offhand
|
|
163
|
+
];
|
|
164
|
+
for (const slot of slots) {
|
|
165
|
+
// 物品已经移除完毕
|
|
166
|
+
if (remaining <= 0) return 0;
|
|
167
|
+
const itemStack = getEquipmentItem(player, slot);
|
|
168
|
+
if (itemStack?.typeId === typeId) {
|
|
169
|
+
// 这个槽位的物品数量足够移除
|
|
170
|
+
if (itemStack.amount > remaining) {
|
|
171
|
+
itemStack.amount -= remaining;
|
|
172
|
+
setEquipmentItem(player, itemStack, slot);
|
|
173
|
+
// 直接返回,因为肯定移除完毕了
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
setEquipmentItem(player, itemStack, slot);
|
|
177
|
+
remaining -= itemStack.amount;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return remaining;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 在容器中查找替换物品
|
|
185
|
+
* @param item 要替换的物品,如果为`undefined`,则替换所有空槽
|
|
186
|
+
* @param newItem 替换后的物品,如果为`undefined`,则清空所有物品
|
|
187
|
+
* @param container 要搜索的容器
|
|
188
|
+
* @author RawDiamondMC
|
|
189
|
+
*/
|
|
190
|
+
export function replaceItemStack(
|
|
191
|
+
item: ItemStack | undefined,
|
|
192
|
+
newItem: ItemStack | undefined,
|
|
193
|
+
container: Container
|
|
194
|
+
): number {
|
|
195
|
+
let amount = 0;
|
|
196
|
+
for (let slot = 0; slot < container.size; slot++) {
|
|
197
|
+
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
198
|
+
if (itemStack?.typeId === item?.typeId) {
|
|
199
|
+
container.setItem(slot, newItem);
|
|
200
|
+
amount++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return amount;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 在容器中根据标签查找替换物品
|
|
208
|
+
* @param itemTag 要替换的物品标签
|
|
209
|
+
* @param newItem 替换后的物品,如果为`undefined`,则清空所有物品
|
|
210
|
+
* @param container 要搜索的容器
|
|
211
|
+
*/
|
|
212
|
+
|
|
213
|
+
export function replaceItemByTag(
|
|
214
|
+
itemTag: string,
|
|
215
|
+
newItem: ItemStack | undefined,
|
|
216
|
+
container: Container
|
|
217
|
+
): number {
|
|
218
|
+
let amount = 0;
|
|
219
|
+
for (let slot = 0; slot < container.size; slot++) {
|
|
220
|
+
const itemStack: undefined | ItemStack = container.getItem(slot);
|
|
221
|
+
if (itemStack?.hasTag(itemTag)) {
|
|
222
|
+
container.setItem(slot, newItem);
|
|
223
|
+
amount++;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return amount;
|
|
227
|
+
}
|