Skip to content

Commit 9d640d0

Browse files
committed
ItemComponents - added more components
1 parent 870444d commit 9d640d0

File tree

8 files changed

+715
-0
lines changed

8 files changed

+715
-0
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.shanebeestudios.skbee.elements.itemcomponent.expressions;
2+
3+
import ch.njol.skript.classes.Changer.ChangeMode;
4+
import ch.njol.skript.doc.Description;
5+
import ch.njol.skript.doc.Examples;
6+
import ch.njol.skript.doc.Name;
7+
import ch.njol.skript.doc.Since;
8+
import ch.njol.util.coll.CollectionUtils;
9+
import com.shanebeestudios.skbee.api.skript.base.SimplePropertyExpression;
10+
import com.shanebeestudios.skbee.api.util.ItemComponentUtils;
11+
import com.shanebeestudios.skbee.api.util.ItemUtils;
12+
import com.shanebeestudios.skbee.api.util.Util;
13+
import io.papermc.paper.datacomponent.DataComponentTypes;
14+
import org.bukkit.damage.DamageType;
15+
import org.bukkit.event.Event;
16+
import org.bukkit.inventory.ItemStack;
17+
import org.jspecify.annotations.Nullable;
18+
19+
@SuppressWarnings("UnstableApiUsage")
20+
@Name("ItemComponent - Damage Type")
21+
@Description({"Represents the damage type component of an item.",
22+
"See [**Damage Type**](https://minecraft.wiki/w/Data_component_format#damage_type) on McWiki for more details.",
23+
"Requires Minecraft 1.21.11+",
24+
"",
25+
"**Changers**:",
26+
"`set` = Will set the damage type of the item.",
27+
"`delete` = Will delete the damage type of this item.",
28+
"`reset` = Will reset the damage type back to the original value."})
29+
@Examples({"set damage type of player's tool to cactus",
30+
"delete damage type of player's tool",
31+
"reset damage type component of player's tool"})
32+
@Since("INSERT VERSION")
33+
public class ExprDamageTypeComponent extends SimplePropertyExpression<Object, DamageType> {
34+
35+
static {
36+
if (Util.IS_RUNNING_MC_1_21_11) {
37+
register(ExprDamageTypeComponent.class, DamageType.class,
38+
"damage type [component]", "itemstacks/itemtypes/slots");
39+
}
40+
}
41+
42+
@Override
43+
public @Nullable DamageType convert(Object from) {
44+
ItemStack itemStack = ItemUtils.getItemStackFromObjects(from);
45+
if (itemStack != null && itemStack.hasData(DataComponentTypes.DAMAGE_TYPE)) {
46+
return itemStack.getData(DataComponentTypes.DAMAGE_TYPE);
47+
}
48+
return null;
49+
}
50+
51+
@Override
52+
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
53+
if (mode == ChangeMode.SET) return CollectionUtils.array(DamageType.class);
54+
else if (mode == ChangeMode.DELETE || mode == ChangeMode.RESET) return CollectionUtils.array();
55+
return null;
56+
}
57+
58+
@Override
59+
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
60+
DamageType damageType = delta != null && delta[0] instanceof DamageType dt ? dt : null;
61+
62+
ItemComponentUtils.modifyComponent(getExpr().getArray(event), mode, DataComponentTypes.DAMAGE_TYPE, damageType);
63+
}
64+
65+
@Override
66+
protected String getPropertyName() {
67+
return "damage type component";
68+
}
69+
70+
@Override
71+
public Class<? extends DamageType> getReturnType() {
72+
return DamageType.class;
73+
}
74+
75+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.shanebeestudios.skbee.elements.itemcomponent.expressions;
2+
3+
import ch.njol.skript.classes.Changer.ChangeMode;
4+
import ch.njol.skript.doc.Description;
5+
import ch.njol.skript.doc.Examples;
6+
import ch.njol.skript.doc.Name;
7+
import ch.njol.skript.doc.Since;
8+
import ch.njol.util.coll.CollectionUtils;
9+
import com.shanebeestudios.skbee.api.skript.base.SimplePropertyExpression;
10+
import com.shanebeestudios.skbee.api.util.ItemComponentUtils;
11+
import com.shanebeestudios.skbee.api.util.ItemUtils;
12+
import com.shanebeestudios.skbee.api.util.MathUtil;
13+
import com.shanebeestudios.skbee.api.util.Util;
14+
import io.papermc.paper.datacomponent.DataComponentTypes;
15+
import org.bukkit.event.Event;
16+
import org.bukkit.inventory.ItemStack;
17+
import org.jspecify.annotations.Nullable;
18+
19+
@SuppressWarnings("UnstableApiUsage")
20+
@Name("ItemComponent - Minimum Attack Charge")
21+
@Description({"Represents the minimum attack charge component of an item.",
22+
"The minimum attack charge on the attack indicator required to attack with this item. Must be a non-negative float between 0.0 and 1.0",
23+
"See [**Minimum Attack Charge**](https://minecraft.wiki/w/Data_component_format#minimum_attack_charge) on McWiki for more details.",
24+
"Requires Minecraft 1.21.11+",
25+
"",
26+
"**Changers**:",
27+
"`set` = Will set the minimum attack charge of the item.",
28+
"`delete` = Will delete the minimum attack charge of this item.",
29+
"`reset` = Will reset the minimum attack charge back to the original value."})
30+
@Examples({"set minimum attack charge of player's tool to 0.5",
31+
"delete minimum attack charge of player's tool",
32+
"reset minimum attack charge component of player's tool"})
33+
@Since("INSERT VERSION")
34+
public class ExprMinAttackChargeComponent extends SimplePropertyExpression<Object, Number> {
35+
36+
static {
37+
if (Util.IS_RUNNING_MC_1_21_11) {
38+
register(ExprMinAttackChargeComponent.class, Number.class,
39+
"min[imum] attack charge [component]", "itemstacks/itemtypes/slots");
40+
}
41+
}
42+
43+
@Override
44+
public @Nullable Number convert(Object from) {
45+
ItemStack itemStack = ItemUtils.getItemStackFromObjects(from);
46+
if (itemStack != null && itemStack.hasData(DataComponentTypes.MINIMUM_ATTACK_CHARGE)) {
47+
return itemStack.getData(DataComponentTypes.MINIMUM_ATTACK_CHARGE);
48+
}
49+
return null;
50+
}
51+
52+
@Override
53+
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
54+
if (mode == ChangeMode.SET) return CollectionUtils.array(Number.class);
55+
else if (mode == ChangeMode.DELETE || mode == ChangeMode.RESET) return CollectionUtils.array();
56+
return null;
57+
}
58+
59+
@Override
60+
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
61+
Number chargeNum = delta != null && delta[0] instanceof Number num ? num : null;
62+
63+
float charge = chargeNum != null ? chargeNum.floatValue() : 1.0f;
64+
charge = MathUtil.clamp(charge, 0.0f, 1.0f);
65+
66+
ItemComponentUtils.modifyComponent(getExpr().getArray(event), mode, DataComponentTypes.MINIMUM_ATTACK_CHARGE, charge);
67+
}
68+
69+
@Override
70+
protected String getPropertyName() {
71+
return "minimum attack charge component";
72+
}
73+
74+
@Override
75+
public Class<? extends Number> getReturnType() {
76+
return Number.class;
77+
}
78+
79+
}

src/main/java/com/shanebeestudios/skbee/elements/itemcomponent/sections/SecAdventureComponent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public class SecAdventureComponent extends Section {
7070
.build();
7171
Skript.registerSection(SecAdventureComponent.class,
7272
"apply (place:can place on|can break) [adventure] predicate to %itemstacks/itemtypes/slots%");
73+
7374
}
7475

7576
private Expression<?> items;
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package com.shanebeestudios.skbee.elements.itemcomponent.sections;
2+
3+
import ch.njol.skript.Skript;
4+
import ch.njol.skript.classes.Changer.ChangeMode;
5+
import ch.njol.skript.config.SectionNode;
6+
import ch.njol.skript.doc.Description;
7+
import ch.njol.skript.doc.Examples;
8+
import ch.njol.skript.doc.Name;
9+
import ch.njol.skript.doc.Since;
10+
import ch.njol.skript.lang.Expression;
11+
import ch.njol.skript.lang.SkriptParser.ParseResult;
12+
import ch.njol.skript.lang.TriggerItem;
13+
import ch.njol.util.Kleenean;
14+
import com.shanebeestudios.skbee.api.skript.base.Section;
15+
import com.shanebeestudios.skbee.api.util.ItemComponentUtils;
16+
import com.shanebeestudios.skbee.api.util.MathUtil;
17+
import com.shanebeestudios.skbee.api.util.SimpleEntryValidator;
18+
import com.shanebeestudios.skbee.api.util.Util;
19+
import io.papermc.paper.datacomponent.DataComponentTypes;
20+
import io.papermc.paper.datacomponent.item.AttackRange;
21+
import org.bukkit.event.Event;
22+
import org.jetbrains.annotations.Nullable;
23+
import org.skriptlang.skript.lang.entry.EntryContainer;
24+
import org.skriptlang.skript.lang.entry.EntryValidator;
25+
26+
import java.util.List;
27+
28+
@SuppressWarnings("UnstableApiUsage")
29+
@Name("ItemComponent - Attack Range Component Apply")
30+
@Description({"Enables a custom attack range when using the item.",
31+
"See [**Attack Range Component**](https://minecraft.wiki/w/Data_component_format#attack_range) on McWiki for more details.",
32+
"Requires Minecraft 1.21.11+",
33+
"",
34+
"**ENTRIES**:",
35+
"All entries are optional and will use their defaults when omitted.",
36+
"- `min_reach` = The minimum distance in blocks from the attacker to the target to be considered valid. Default = 0, valid range = 0 to 64",
37+
"- `max_reach` = The maximum distance in blocks from the attacker to the target to be considered valid. Default = 3, valid range = 0 to 64",
38+
"- `min_creative_reach` = The minimum distance in blocks from the attacker to the target to be considered valid in creative mode. Default = 0, valid range = 0 to 64",
39+
"- `max_creative_reach` = The maximum distance in blocks from the attacker to the target to be considered valid in creative mode. Default = 5, valid range = 0 to 64",
40+
"- `hitbox_margin` = Tthe margin applied to the target bounding box when checking for valid hitbox collision. Default = 0.3, valid range = 0 to 1",
41+
"- `mob_factor` = The multiplier applied to the min_range and max_range when checking for valid distance when item is used by a mob. Default = 1, valid range = 0 to 2"})
42+
@Examples({"set {_i} to 1 of diamond shovel",
43+
"apply attack range component to {_i}:",
44+
"\tmin_reach: 0.0",
45+
"\tmax_reach: 64.0",
46+
"\tmin_creative_reach: 0",
47+
"\tmax_creative_reach: 64",
48+
"\thitbox_margin: 0.3",
49+
"\tmob_factor: 1",
50+
"",
51+
"give player 1 of {_i}"})
52+
@Since("INSERT VERSION")
53+
public class SecAttackRangeComponent extends Section {
54+
55+
private static EntryValidator VALIDATOR;
56+
57+
static {
58+
if (Util.IS_RUNNING_MC_1_21_11) {
59+
VALIDATOR = SimpleEntryValidator.builder()
60+
.addOptionalEntry("min_reach", Number.class)
61+
.addOptionalEntry("max_reach", Number.class)
62+
.addOptionalEntry("min_creative_reach", Number.class)
63+
.addOptionalEntry("max_creative_reach", Number.class)
64+
.addOptionalEntry("hitbox_margin", Number.class)
65+
.addOptionalEntry("mob_factor", Number.class)
66+
.build();
67+
68+
Skript.registerSection(SecAttackRangeComponent.class,
69+
"apply attack range component to %itemstacks/itemtypes/slots%");
70+
}
71+
}
72+
73+
private Expression<?> items;
74+
private Expression<Number> minReach;
75+
private Expression<Number> maxReach;
76+
private Expression<Number> minCreativeReach;
77+
private Expression<Number> maxCreativeReach;
78+
private Expression<Number> hitboxMargin;
79+
private Expression<Number> mobFactor;
80+
81+
@SuppressWarnings("unchecked")
82+
@Override
83+
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List<TriggerItem> triggerItems) {
84+
if (sectionNode == null) return false;
85+
EntryContainer validate = VALIDATOR.validate(sectionNode);
86+
if (validate == null) {
87+
return false;
88+
}
89+
this.items = exprs[0];
90+
91+
this.minReach = (Expression<Number>) validate.getOptional("min_reach", false);
92+
this.maxReach = (Expression<Number>) validate.getOptional("max_reach", false);
93+
this.minCreativeReach = (Expression<Number>) validate.getOptional("min_creative_reach", false);
94+
this.maxCreativeReach = (Expression<Number>) validate.getOptional("max_creative_reach", false);
95+
this.hitboxMargin = (Expression<Number>) validate.getOptional("hitbox_margin", false);
96+
this.mobFactor = (Expression<Number>) validate.getOptional("mob_factor", false);
97+
98+
return true;
99+
}
100+
101+
@Override
102+
protected @Nullable TriggerItem walk(Event event) {
103+
AttackRange.Builder builder = AttackRange.attackRange();
104+
105+
if (this.minReach != null) {
106+
Number single = this.minReach.getSingle(event);
107+
if (single != null) builder.minReach(MathUtil.clamp(single.floatValue(), 0.0f, 64.0f));
108+
}
109+
if (this.maxReach != null) {
110+
Number single = this.maxReach.getSingle(event);
111+
if (single != null) builder.maxReach(MathUtil.clamp(single.floatValue(), 0.0f, 64.0f));
112+
}
113+
if (this.minCreativeReach != null) {
114+
Number single = this.minCreativeReach.getSingle(event);
115+
if (single != null) builder.minCreativeReach(MathUtil.clamp(single.floatValue(), 0.0f, 64.0f));
116+
}
117+
if (this.maxCreativeReach != null) {
118+
Number single = this.maxCreativeReach.getSingle(event);
119+
if (single != null) builder.maxCreativeReach(MathUtil.clamp(single.floatValue(), 0.0f, 64.0f));
120+
}
121+
if (this.hitboxMargin != null) {
122+
Number single = this.hitboxMargin.getSingle(event);
123+
if (single != null) builder.hitboxMargin(MathUtil.clamp(single.floatValue(), 0.0f, 1.0f));
124+
}
125+
if (this.mobFactor != null) {
126+
Number single = this.mobFactor.getSingle(event);
127+
if (single != null) builder.mobFactor(MathUtil.clamp(single.floatValue(), 0.0f, 2.0f));
128+
}
129+
130+
ItemComponentUtils.modifyComponent(this.items.getArray(event), ChangeMode.SET, DataComponentTypes.ATTACK_RANGE, builder.build());
131+
return super.walk(event, false);
132+
}
133+
134+
@Override
135+
public String toString(@Nullable Event e, boolean d) {
136+
return "apply attack range component to " + this.items.toString(e, d);
137+
}
138+
139+
}

0 commit comments

Comments
 (0)