Skip to content

Commit 4bc76e7

Browse files
authored
Merge pull request #839 from JasperLorelai/main
Mob Goals (Core)
2 parents 7ce7a43 + a60aa88 commit 4bc76e7

14 files changed

+597
-269
lines changed

core/src/main/java/com/nisovin/magicspells/Perm.java

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public enum Perm {
3939
COMMAND_UTIL_DOWNLOAD("magicspells.command.util.download"),
4040
COMMAND_UTIL_UPDATE("magicspells.command.util.update"),
4141
COMMAND_UTIL_SAVE_SKIN("magicspells.command.util.saveskin"),
42+
COMMAND_UTIL_LIST_GOALS("magicspells.command.util.listgoals"),
4243
COMMAND_PROFILE_REPORT("magicspells.command.profilereport"),
4344
COMMAND_DEBUG("magicspells.command.debug"),
4445
COMMAND_TASKINFO("magicspells.command.taskinfo"),

core/src/main/java/com/nisovin/magicspells/commands/MagicCommand.java

+113-55
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,39 @@
22

33
import java.util.*;
44
import java.io.File;
5-
import java.io.Writer;
6-
import java.io.FileWriter;
5+
import java.io.IOException;
76
import java.util.regex.Pattern;
87

98
import org.bukkit.*;
9+
import org.bukkit.entity.Mob;
1010
import org.bukkit.block.Block;
1111
import org.bukkit.entity.Entity;
1212
import org.bukkit.entity.Player;
13+
import org.bukkit.util.RayTraceResult;
1314
import org.bukkit.entity.LivingEntity;
1415
import org.bukkit.inventory.ItemStack;
1516
import org.bukkit.scheduler.BukkitTask;
1617
import org.bukkit.command.CommandSender;
1718
import org.bukkit.inventory.EntityEquipment;
1819
import org.bukkit.command.ConsoleCommandSender;
20+
import org.bukkit.configuration.file.YamlConfiguration;
1921

2022
import co.aikar.commands.*;
2123
import co.aikar.commands.annotation.*;
2224
import co.aikar.commands.annotation.Optional;
2325
import co.aikar.commands.bukkit.contexts.OnlinePlayer;
2426

27+
import com.destroystokyo.paper.entity.ai.Goal;
28+
import com.destroystokyo.paper.profile.ProfileProperty;
29+
2530
import com.nisovin.magicspells.Perm;
2631
import com.nisovin.magicspells.Spell;
2732
import com.nisovin.magicspells.util.*;
2833
import com.nisovin.magicspells.Spellbook;
2934
import com.nisovin.magicspells.MagicSpells;
3035
import com.nisovin.magicspells.variables.Variable;
3136
import com.nisovin.magicspells.spells.PassiveSpell;
37+
import com.nisovin.magicspells.Spell.PostCastAction;
3238
import com.nisovin.magicspells.mana.ManaChangeReason;
3339
import com.nisovin.magicspells.handlers.MagicXpHandler;
3440
import com.nisovin.magicspells.util.magicitems.MagicItem;
@@ -53,17 +59,15 @@ public MagicCommand() {
5359
});
5460

5561
// Create command completions.
56-
commandManager.getCommandCompletions().registerAsyncCompletion("spells", context -> {
57-
Set<String> spells = new HashSet<>();
58-
if (context.getConfig() != null && context.getConfig().equals("*")) spells.add("*");
59-
// Collect spell names.
60-
spells.addAll(getSpellNames(MagicSpells.spells()));
61-
return spells;
62-
});
62+
commandManager.getCommandCompletions().registerAsyncCompletion("spells", context ->
63+
getSpellNames(MagicSpells.spells())
64+
);
6365
commandManager.getCommandCompletions().registerAsyncCompletion("owned_spells", context -> {
64-
Set<Spell> spells = new HashSet<>();
6566
Player player = context.getPlayer();
67+
if (player == null) return getSpellNames(MagicSpells.spells());
68+
6669
Spellbook spellbook = MagicSpells.getSpellbook(player);
70+
Set<Spell> spells = new HashSet<>();
6771
for (Spell spell : MagicSpells.getSpellsOrdered()) {
6872
if (spell.isHelperSpell()) continue;
6973
if (spell instanceof PassiveSpell) continue;
@@ -72,52 +76,72 @@ public MagicCommand() {
7276
}
7377
return getSpellNames(spells);
7478
});
75-
commandManager.getCommandCompletions().registerAsyncCompletion("players+", context -> {
76-
Set<String> players = new HashSet<>();
77-
players.add("*");
78-
for (Player player : Bukkit.getOnlinePlayers()) {
79-
players.add(player.getName());
80-
}
81-
return players;
82-
});
8379
commandManager.getCommandCompletions().registerAsyncCompletion("variables", context ->
8480
MagicSpells.getVariableManager().getVariables().keySet()
8581
);
8682
commandManager.getCommandCompletions().registerAsyncCompletion("magic_items", context ->
8783
MagicItems.getMagicItemKeys()
8884
);
8985
commandManager.getCommandCompletions().registerAsyncCompletion("looking_at", context -> {
90-
Set<String> completions = new HashSet<>();
91-
if (!context.getIssuer().isPlayer()) return completions;
86+
Player player = context.getPlayer();
87+
if (player == null) return Collections.emptySet();
9288

9389
String config = context.getConfig();
94-
if (config == null || config.isEmpty()) return completions;
95-
90+
if (config == null || config.isEmpty()) return Collections.emptySet();
91+
92+
RayTraceResult result = player.rayTraceBlocks(6, FluidCollisionMode.SOURCE_ONLY);
93+
if (result == null) return Collections.emptySet();
94+
95+
Block block = result.getHitBlock();
96+
if (block == null) return Collections.emptySet();
97+
98+
String value = switch (config.toLowerCase()) {
99+
case "x" -> String.valueOf(block.getX());
100+
case "y" -> String.valueOf(block.getY());
101+
case "z" -> String.valueOf(block.getZ());
102+
case "pitch" -> String.valueOf(player.getLocation().getPitch());
103+
case "yaw" -> String.valueOf(player.getLocation().getYaw());
104+
default -> "";
105+
};
106+
return Set.of(value);
107+
});
108+
commandManager.getCommandCompletions().registerAsyncCompletion("spell_target", context -> {
96109
Player player = context.getPlayer();
97-
Block block = player.getTargetBlockExact(6, FluidCollisionMode.SOURCE_ONLY);
98-
if (block == null) return null;
99-
if (block.getType().isAir()) return completions;
100-
101-
Location location = block.getLocation();
102-
String num = "";
103-
switch (config.toLowerCase()) {
104-
case "x" -> num += location.getX();
105-
case "y" -> num += location.getY();
106-
case "z" -> num += location.getZ();
107-
case "pitch" -> num += player.getLocation().getPitch();
108-
case "yaw" -> num += player.getLocation().getYaw();
110+
if (player == null) return getPlayers();
111+
RayTraceResult result = player.rayTraceEntities(6);
112+
113+
Set<String> targets = new HashSet<>();
114+
// Add the targeted entity's uuid/username first.
115+
if (result != null && result.getHitEntity() instanceof LivingEntity entity) {
116+
targets.add(entity instanceof Player pl ? pl.getName() : entity.getUniqueId().toString());
109117
}
110-
if (!num.isEmpty()) completions.add(num);
111-
return completions;
118+
targets.addAll(getPlayers());
119+
return targets;
120+
});
121+
commandManager.getCommandCompletions().registerAsyncCompletion("target_uuid", context -> {
122+
Player player = context.getPlayer();
123+
if (player == null) return Collections.emptySet();
124+
125+
RayTraceResult result = player.rayTraceEntities(6);
126+
if (result == null || !(result.getHitEntity() instanceof LivingEntity entity))
127+
return Collections.emptySet();
128+
return Set.of(entity.getUniqueId().toString());
112129
});
113130
commandManager.getCommandCompletions().registerAsyncCompletion("power", context -> {
114131
Player player = context.getPlayer();
115-
if (player == null) return Collections.emptyList();
116-
if (!Perm.COMMAND_CAST_POWER.has(player)) return Collections.emptyList();
132+
if (player != null && !Perm.COMMAND_CAST_POWER.has(player)) return Collections.emptyList();
117133
return Collections.singleton("-p:");
118134
});
119135
}
120136

137+
private static Set<String> getPlayers() {
138+
Set<String> players = new HashSet<>();
139+
for (Player player : Bukkit.getOnlinePlayers()) {
140+
players.add(player.getName());
141+
}
142+
return players;
143+
}
144+
121145
private static Set<String> getSpellNames(Collection<Spell> spells) {
122146
Set<String> spellNames = new HashSet<>();
123147
boolean added;
@@ -298,7 +322,7 @@ public static void onTask(CommandIssuer issuer) {
298322
}
299323

300324
@Subcommand("resetcd")
301-
@CommandCompletion("@players+ @spells:* @nothing")
325+
@CommandCompletion("*|@players *|@spells @nothing")
302326
@Syntax("[player/*] [spell/*]")
303327
@Description("Reset cooldown of all players or a player for a spell or all spells.")
304328
@HelpPermission(permission = Perm.COMMAND_RESET_COOLDOWN)
@@ -612,26 +636,61 @@ public void onUpdate(CommandIssuer issuer, String[] args) {
612636
@HelpPermission(permission = Perm.COMMAND_UTIL_SAVE_SKIN)
613637
public void onSaveSkin(CommandIssuer issuer, @Optional Player player) {
614638
if (!MagicSpells.isLoaded()) return;
639+
615640
if (noPermission(issuer.getIssuer(), Perm.COMMAND_UTIL_SAVE_SKIN)) return;
616641
if (player == null) player = getPlayerFromIssuer(issuer);
617642
if (player == null) return;
618-
String data = Util.getSkinData(player);
619643

620-
File folder = new File(MagicSpells.getInstance().getDataFolder(), "skins");
644+
List<ProfileProperty> skins = player.getPlayerProfile().getProperties().stream().filter(prop -> prop.getName().equals("textures")).toList();
645+
ProfileProperty latestSkin = skins.get(0);
646+
647+
YamlConfiguration data = new YamlConfiguration();
648+
data.set("skin", latestSkin.getValue());
649+
data.set("signature", latestSkin.getSignature());
650+
651+
File folder = new File(PLUGIN_FOLDER, "skins");
621652
if (!folder.exists()) folder.mkdir();
622-
File file = new File(folder, System.currentTimeMillis() + ".yml");
623653
try {
624-
Writer writer = new FileWriter(file);
625-
writer.write(data);
626-
writer.flush();
627-
writer.close();
628-
} catch (Exception e) {
654+
data.save(new File(folder, System.currentTimeMillis() + ".yml"));
655+
} catch (IOException e) {
629656
e.printStackTrace();
657+
return;
630658
}
631659

632660
issuer.sendMessage(MagicSpells.getTextColor() + TxtUtil.getPossessiveName(player.getName()) + " skin was saved.");
633661
}
634662

663+
@Subcommand("listgoals")
664+
@CommandCompletion("@target_uuid @nothing")
665+
@Syntax("[uuid]")
666+
@Description("List an entity's mob goals.")
667+
@HelpPermission(permission = Perm.COMMAND_UTIL_LIST_GOALS)
668+
public void onListGoals(CommandIssuer issuer, String uuidString) {
669+
if (noPermission(issuer.getIssuer(), Perm.COMMAND_UTIL_LIST_GOALS)) return;
670+
671+
UUID uuid;
672+
try {
673+
uuid = UUID.fromString(uuidString);
674+
} catch (IllegalArgumentException e) {
675+
throw new ConditionFailedException("Passed UUID argument is not a valid UUIO.");
676+
}
677+
if (!(Bukkit.getEntity(uuid) instanceof Mob mob))
678+
throw new ConditionFailedException("UUID did not match an entity of Mob type.");
679+
680+
Collection<Goal<Mob>> goals = Bukkit.getMobGoals().getAllGoals(mob);
681+
if (goals.isEmpty()) {
682+
issuer.sendMessage(MagicSpells.getTextColor() + "Entity '" + uuid + "' has no mob goals.");
683+
return;
684+
}
685+
686+
issuer.sendMessage(MagicSpells.getTextColor() + "Mob goals of entity '" + uuid + "':");
687+
for (Goal<Mob> goal : goals) {
688+
String entity = goal.getKey().getEntityClass().getSimpleName();
689+
String key = goal.getKey().getNamespacedKey().toString();
690+
issuer.sendMessage(MagicSpells.getTextColor() + " - " + entity + ": " + key + " " + goal.getTypes());
691+
}
692+
}
693+
635694
}
636695

637696
@Subcommand("profilereport")
@@ -743,7 +802,7 @@ public void onCastSelf(CommandIssuer issuer, String[] args) {
743802
}
744803

745804
@Subcommand("as")
746-
@CommandCompletion("@players @spells @power @nothing")
805+
@CommandCompletion("@spell_target @spells @power @nothing")
747806
@Syntax("<player/UUID> <spell> (-p:[power]) [spellArgs]")
748807
@Description("Force a player to cast a spell. (You can optionally define power: -p:1.0)")
749808
@HelpPermission(permission = Perm.COMMAND_CAST_AS)
@@ -768,7 +827,7 @@ public void onCastAs(CommandIssuer issuer, String[] args) {
768827
}
769828

770829
@Subcommand("on")
771-
@CommandCompletion("@players @spells @nothing")
830+
@CommandCompletion("@spell_target @spells @nothing")
772831
@Syntax("<player/UUID> <spell>")
773832
@Description("Cast a spell on an entity.")
774833
@HelpPermission(permission = Perm.COMMAND_CAST_ON)
@@ -785,11 +844,10 @@ public void onCastOn(CommandIssuer issuer, String[] args) {
785844
throw new ConditionFailedException("Spell is not a targeted entity spell.");
786845
}
787846

788-
boolean casted;
789-
// Handle with or without caster.
790-
if (issuer.getIssuer() instanceof LivingEntity) casted = newSpell.castAtEntity(issuer.getIssuer(), target, 1F);
791-
else casted = newSpell.castAtEntity(target, 1F);
792-
if (!casted) throw new ConditionFailedException("Spell probably cannot be cast from console.");
847+
LivingEntity caster = issuer.getIssuer() instanceof LivingEntity ? issuer.getIssuer() : null;
848+
CastResult result = newSpell.castAtEntity(new SpellData(caster, target));
849+
if (result.action() == PostCastAction.ALREADY_HANDLED)
850+
throw new ConditionFailedException("Spell probably cannot be cast from console.");
793851
}
794852

795853
@Subcommand("at")
@@ -851,7 +909,7 @@ else if (issuer.getIssuer() instanceof LivingEntity) {
851909
SpellData data = new SpellData(issuer.getIssuer() instanceof LivingEntity le ? le : null, location, 1f, null);
852910
CastResult result = newSpell.castAtLocation(data);
853911

854-
if (result.action() == Spell.PostCastAction.ALREADY_HANDLED)
912+
if (result.action() == PostCastAction.ALREADY_HANDLED)
855913
throw new ConditionFailedException("Spell probably cannot be cast from console.");
856914
}
857915

0 commit comments

Comments
 (0)