forked from nisovin/MagicSpells
-
Notifications
You must be signed in to change notification settings - Fork 66
/
MobGoalEditSpell.java
151 lines (124 loc) · 5.06 KB
/
MobGoalEditSpell.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package com.nisovin.magicspells.spells.targeted;
import java.util.*;
import org.bukkit.Bukkit;
import org.bukkit.entity.Mob;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.LivingEntity;
import org.bukkit.configuration.ConfigurationSection;
import com.destroystokyo.paper.entity.ai.Goal;
import com.destroystokyo.paper.entity.ai.GoalKey;
import com.destroystokyo.paper.entity.ai.GoalType;
import com.nisovin.magicspells.util.*;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.util.ai.CustomGoal;
import com.nisovin.magicspells.util.ai.CustomGoals;
import com.nisovin.magicspells.spells.TargetedSpell;
import com.nisovin.magicspells.util.config.ConfigData;
import com.nisovin.magicspells.spells.TargetedEntitySpell;
public class MobGoalEditSpell extends TargetedSpell implements TargetedEntitySpell {
private final List<GoalData> add;
private final List<GoalKey<Mob>> remove;
private final EnumSet<GoalType> removeTypes;
private final List<GoalKey<?>> removeVanilla;
private final ConfigData<Boolean> removeAll;
public MobGoalEditSpell(MagicConfig config, String spellName) {
super(config, spellName);
removeAll = getConfigDataBoolean("remove-all", false);
removeTypes = EnumSet.noneOf(GoalType.class);
List<String> removeTypeStrings = getConfigStringList("remove-types", null);
if (removeTypeStrings != null) {
for (String string : removeTypeStrings) {
GoalType type = Util.enumValueSafe(GoalType.class, string.toUpperCase());
if (type == null) {
MagicSpells.error("MobGoalEditSpell '" + internalName + "' lists an invalid value in 'remove-types': " + string);
continue;
}
removeTypes.add(type);
}
}
removeVanilla = new ArrayList<>();
List<String> removeVanillaStrings = getConfigStringList("remove-vanilla", null);
if (removeVanillaStrings != null) {
for (String string : removeVanillaStrings) {
GoalKey<?> vanillaGoal = CustomGoals.getVanillaGoal(string);
if (vanillaGoal == null) {
MagicSpells.error("MobGoalEditSpell '" + internalName + "' lists an invalid vanilla goal in 'remove-vanilla': " + string);
continue;
}
removeVanilla.add(vanillaGoal);
}
}
remove = new ArrayList<>();
List<String> removeStrings = getConfigStringList("remove", null);
if (removeStrings != null) {
for (String string : removeStrings) {
NamespacedKey key = null;
try {
key = NamespacedKey.fromString(string, MagicSpells.getInstance());
} catch (IllegalArgumentException ignored) {}
if (key == null) {
MagicSpells.error("MobGoalEditSpell '" + internalName + "' lists an invalid key in 'remove': " + string);
continue;
}
remove.add(GoalKey.of(Mob.class, key));
}
}
add = new ArrayList<>();
List<?> addList = getConfigList("add", new ArrayList<>());
if (addList != null) {
for (Object object : addList) {
if (!(object instanceof Map<?, ?> map)) continue;
ConfigurationSection section = ConfigReaderUtil.mapToSection(map);
int priority = section.getInt("priority", 0);
String goalName = section.getString("goal", "").toLowerCase();
ConfigurationSection goalSection = section.getConfigurationSection("data");
if (!CustomGoals.getGoals().containsKey(goalName)) {
MagicSpells.error("MobGoalEditSpell '" + internalName + "' lists an invalid goal name: '" + goalName + "'");
continue;
}
add.add(new GoalData(goalName, priority, goalSection));
}
}
}
@Override
public CastResult cast(SpellData data) {
TargetInfo<LivingEntity> info = getTargetedEntity(data);
if (info.noTarget()) return noTarget(info);
return castAtEntity(info.spellData());
}
@Override
public CastResult castAtEntity(SpellData data) {
if (!(data.target() instanceof Mob mob)) return noTarget(data);
if (removeAll.get(data)) Bukkit.getMobGoals().removeAllGoals(mob);
for (GoalType type : removeTypes) {
Bukkit.getMobGoals().removeAllGoals(mob, type);
}
for (GoalKey<Mob> key : remove) {
Bukkit.getMobGoals().removeGoal(mob, key);
}
for (GoalKey<?> key : removeVanilla) {
// We have to loop through because casting to parameter types is tricky.
// It loops through on each MobGoals#removeGoal call anyway.
for (Goal<Mob> goal : Bukkit.getMobGoals().getAllGoals(mob)) {
if (!goal.getKey().equals(key)) continue;
Bukkit.getMobGoals().removeGoal(mob, goal);
}
}
for (GoalData goalData : add) {
CustomGoal goal = CustomGoals.getGoal(goalData.goalName(), mob, data);
if (goal == null) {
MagicSpells.error("MobGoalEditSpell '" + internalName + "' lists an invalid goal name on 'add': '" + goalData.goalName() + "'");
continue;
}
boolean success = goal.initialize(goalData.section());
if (!success) {
MagicSpells.error("MobGoalEditSpell '" + internalName +"' is missing a 'data' option under 'add' for goal: " + goalData.goalName());
continue;
}
Bukkit.getMobGoals().addGoal(mob, goalData.priority(), goal);
}
playSpellEffects(data);
return new CastResult(PostCastAction.HANDLE_NORMALLY, data);
}
private record GoalData(String goalName, int priority, ConfigurationSection section) {}
}