Skip to content

Commit ad73cb2

Browse files
Fly1337Archy-X
authored andcommitted
Add configurable requirements for blocks (#342)
1 parent 8583fa4 commit ad73cb2

File tree

11 files changed

+274
-0
lines changed

11 files changed

+274
-0
lines changed

bukkit/src/main/java/dev/aurelium/auraskills/bukkit/commands/ReloadExecutor.java

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public void reload(CommandSender sender) {
3232
plugin.config().loadOptions();
3333
plugin.getMessageProvider().loadDefaultLanguageOption();
3434
plugin.getRequirementManager().load();
35+
plugin.getRequirementManager().loadBlocks();
3536
// Load blocked/disabled worlds lists
3637
plugin.getWorldManager().loadWorlds();
3738
// Load skills

bukkit/src/main/java/dev/aurelium/auraskills/bukkit/requirement/RequirementListener.java

+56
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,25 @@
44
import dev.aurelium.auraskills.api.skill.Skill;
55
import dev.aurelium.auraskills.bukkit.AuraSkills;
66
import dev.aurelium.auraskills.bukkit.item.SkillsItem;
7+
import dev.aurelium.auraskills.bukkit.requirement.blocks.BlockRequirement;
8+
import dev.aurelium.auraskills.bukkit.requirement.blocks.RequirementNode;
79
import dev.aurelium.auraskills.bukkit.util.armor.ArmorEquipEvent;
810
import dev.aurelium.auraskills.common.config.Option;
11+
import dev.aurelium.auraskills.common.hooks.PlaceholderHook;
912
import dev.aurelium.auraskills.common.message.MessageKey;
1013
import dev.aurelium.auraskills.common.message.type.CommandMessage;
14+
import dev.aurelium.auraskills.common.user.User;
1115
import dev.aurelium.auraskills.common.util.math.RomanNumber;
1216
import dev.aurelium.auraskills.common.util.text.TextUtil;
17+
import dev.aurelium.slate.text.TextFormatter;
1318
import org.bukkit.Material;
1419
import org.bukkit.entity.Player;
1520
import org.bukkit.event.*;
1621
import org.bukkit.event.block.BlockBreakEvent;
1722
import org.bukkit.event.block.BlockPlaceEvent;
1823
import org.bukkit.event.entity.EntityDamageByEntityEvent;
1924
import org.bukkit.event.entity.EntityShootBowEvent;
25+
import org.bukkit.event.player.PlayerHarvestBlockEvent;
2026
import org.bukkit.event.player.PlayerInteractEvent;
2127
import org.bukkit.inventory.ItemStack;
2228

@@ -96,6 +102,9 @@ public void onBlockBreak(BlockBreakEvent event) {
96102
if (item.getType() == Material.AIR) return;
97103
checkItemRequirements(player, item, event);
98104
}
105+
106+
if (plugin.configBoolean(Option.REQUIREMENT_BLOCKS_ENABLED)) return;
107+
checkBlockRequirements(event.getPlayer(), event.getBlock().getType(), event);
99108
}
100109

101110
@EventHandler(priority = EventPriority.HIGH)
@@ -107,8 +116,19 @@ public void onPlace(BlockPlaceEvent event) {
107116
if (item.getType() == Material.AIR) return;
108117
checkItemRequirements(player, item, event);
109118
}
119+
120+
if (plugin.configBoolean(Option.REQUIREMENT_BLOCKS_ENABLED)) return;
121+
checkBlockRequirements(event.getPlayer(), event.getBlock().getType(), event);
110122
}
111123

124+
@EventHandler(priority = EventPriority.HIGH)
125+
public void onHarvest(PlayerHarvestBlockEvent event) {
126+
if (event.isCancelled()) return;
127+
if (plugin.configBoolean(Option.REQUIREMENT_BLOCKS_ENABLED)) return;
128+
checkBlockRequirements(event.getPlayer(), event.getHarvestedBlock().getType(), event);
129+
}
130+
131+
112132
@EventHandler(priority = EventPriority.HIGH)
113133
public void onAttack(EntityDamageByEntityEvent event) {
114134
if (event.isCancelled()) return;
@@ -163,4 +183,40 @@ private void checkItemRequirements(Player player, ItemStack item, Cancellable ev
163183
}
164184
}
165185

186+
private void checkBlockRequirements(Player player, Material material, Cancellable event) {
187+
BlockRequirement blockRequirement = null;
188+
189+
for (BlockRequirement block : manager.getBlocks()) {
190+
if (block.getMaterial() == material) {
191+
blockRequirement = block;
192+
break;
193+
}
194+
}
195+
196+
if (blockRequirement != null) {
197+
if (event instanceof BlockBreakEvent) {
198+
if (!blockRequirement.checksBreaking()) return;
199+
} else if (event instanceof BlockPlaceEvent) {
200+
if (!blockRequirement.checksPlacing()) return;
201+
}
202+
203+
for (RequirementNode node : blockRequirement.getNodes()) {
204+
if (!node.check(player)) {
205+
event.setCancelled(true);
206+
String message = node.getDenyMessage();
207+
if (!message.isEmpty()) {
208+
TextFormatter formatter = new TextFormatter();
209+
User user = plugin.getUser(player);
210+
211+
if (plugin.getHookManager().isRegistered(PlaceholderHook.class)) {
212+
message = plugin.getHookManager().getHook(PlaceholderHook.class).setPlaceholders(user, message);
213+
}
214+
215+
user.sendMessage(formatter.toComponent(message));
216+
}
217+
break;
218+
}
219+
}
220+
}
221+
}
166222
}

bukkit/src/main/java/dev/aurelium/auraskills/bukkit/requirement/RequirementManager.java

+63
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import dev.aurelium.auraskills.api.item.ModifierType;
44
import dev.aurelium.auraskills.api.registry.NamespacedId;
55
import dev.aurelium.auraskills.api.skill.Skill;
6+
import dev.aurelium.auraskills.api.stat.Stat;
67
import dev.aurelium.auraskills.bukkit.AuraSkills;
8+
import dev.aurelium.auraskills.bukkit.requirement.blocks.*;
79
import dev.aurelium.auraskills.common.config.ConfigurateLoader;
810
import dev.aurelium.auraskills.common.scheduler.TaskRunnable;
911
import org.bukkit.Material;
@@ -20,13 +22,15 @@
2022
public class RequirementManager implements Listener {
2123

2224
private Set<GlobalRequirement> globalRequirements;
25+
private List<BlockRequirement> blockRequirements;
2326
private final Map<UUID, Integer> errorMessageTimer;
2427
private final AuraSkills plugin;
2528

2629
public RequirementManager(AuraSkills plugin) {
2730
errorMessageTimer = new HashMap<>();
2831
this.plugin = plugin;
2932
load();
33+
loadBlocks();
3034
tickTimer();
3135
}
3236

@@ -74,10 +78,69 @@ public void load() {
7478
}
7579
}
7680

81+
public void loadBlocks() {
82+
ConfigurateLoader loader = new ConfigurateLoader(plugin, TypeSerializerCollection.builder().build());
83+
try {
84+
ConfigurationNode config = loader.loadUserFile("config.yml");
85+
86+
this.blockRequirements = new ArrayList<>();
87+
List<? extends ConfigurationNode> blockNodes = config.node("requirement.blocks", "list").childrenList();
88+
for (ConfigurationNode blockNode : blockNodes) {
89+
Material material = Material.valueOf(blockNode.node("material").getString().toUpperCase(Locale.ROOT));
90+
boolean allowPlace = blockNode.node("allow_place").getBoolean();
91+
boolean allowBreak = blockNode.node("allow_break").getBoolean();
92+
boolean allowHarvest = blockNode.node("allow_harvest").getBoolean();
93+
List<? extends ConfigurationNode> requirementNodes = blockNode.node("requirements").childrenList();
94+
List<RequirementNode> nodes = new ArrayList<>();
95+
96+
for (ConfigurationNode requirementNode : requirementNodes) {
97+
String type = requirementNode.node("type").getString();
98+
String message = requirementNode.node("message").getString("");
99+
100+
switch (type) {
101+
case "skill_level" -> {
102+
Skill skill = plugin.getSkillRegistry().getOrNull(NamespacedId.fromDefault(requirementNode.node("skill").getString().toLowerCase(Locale.ROOT)));
103+
int level = requirementNode.node("level").getInt();
104+
nodes.add(new SkillNode(plugin, skill, level, message));
105+
}
106+
case "permission" -> {
107+
String permission = requirementNode.node("permission").getString();
108+
nodes.add(new PermissionNode(plugin, permission, message));
109+
}
110+
case "excluded_world" -> {
111+
String[] worlds = (String[]) requirementNode.node("world").getList(String.class).toArray();
112+
nodes.add(new ExcludedWorldNode(plugin, worlds, message));
113+
}
114+
case "stat" -> {
115+
Stat stat = plugin.getStatManager().getEnabledStats().stream().filter(s -> s.getId().equals(NamespacedId.fromDefault(requirementNode.node("stat").getString().toLowerCase(Locale.ROOT)))).findFirst().orElse(null);
116+
int value = requirementNode.node("value").getInt();
117+
nodes.add(new StatNode(plugin, stat, value, message));
118+
}
119+
default ->
120+
plugin.logger().warn("Unknown requirement type: " + type);
121+
}
122+
}
123+
124+
BlockRequirement blockRequirement = new BlockRequirement(material, allowPlace, allowBreak, allowHarvest, nodes);
125+
blockRequirements.add(blockRequirement);
126+
}
127+
if (!blockRequirements.isEmpty()) {
128+
plugin.logger().info("Loaded " + blockRequirements.size() + " global requirement" + (blockRequirements.size() != 1 ? "s" : ""));
129+
}
130+
} catch (IOException e) {
131+
plugin.logger().warn("Error loading block requirements: " + e.getMessage());
132+
e.printStackTrace();
133+
}
134+
}
135+
77136
public Set<GlobalRequirement> getGlobalRequirements() {
78137
return globalRequirements;
79138
}
80139

140+
public List<BlockRequirement> getBlocks() {
141+
return blockRequirements;
142+
}
143+
81144
public Set<GlobalRequirement> getGlobalRequirementsType(ModifierType type) {
82145
Set<GlobalRequirement> matched = new HashSet<>();
83146
for (GlobalRequirement requirement : globalRequirements) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package dev.aurelium.auraskills.bukkit.requirement.blocks;
2+
3+
import org.bukkit.Material;
4+
5+
import java.util.List;
6+
7+
public class BlockRequirement {
8+
9+
private final Material material;
10+
private final boolean checksPlace;
11+
private final boolean checksBreak;
12+
private final boolean checksHarvest;
13+
private final List<RequirementNode> nodes;
14+
15+
public BlockRequirement(Material material, boolean checksPlace, boolean checksBreak, boolean checksHarvest, List<RequirementNode> nodes) {
16+
this.material = material;
17+
this.checksPlace = checksPlace;
18+
this.checksBreak = checksBreak;
19+
this.checksHarvest = checksHarvest;
20+
this.nodes = nodes;
21+
}
22+
23+
public Material getMaterial() {
24+
return material;
25+
}
26+
27+
public boolean checksPlacing() {
28+
return checksPlace;
29+
}
30+
31+
public boolean checksBreaking() {
32+
return checksBreak;
33+
}
34+
35+
public boolean checksHarvesting() {
36+
return checksHarvest;
37+
}
38+
39+
public List<RequirementNode> getNodes() {
40+
return nodes;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dev.aurelium.auraskills.bukkit.requirement.blocks;
2+
3+
import dev.aurelium.auraskills.bukkit.AuraSkills;
4+
import org.bukkit.entity.Player;
5+
6+
public class ExcludedWorldNode extends RequirementNode {
7+
8+
private final String[] worlds;
9+
10+
public ExcludedWorldNode(AuraSkills plugin, String[] worlds, String message) {
11+
super(plugin, message);
12+
this.worlds = worlds;
13+
}
14+
15+
@Override
16+
public boolean check(Player player) {
17+
for (String world : worlds) {
18+
if (player.getWorld().getName().equalsIgnoreCase(world)) {
19+
return false;
20+
}
21+
}
22+
return true;
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dev.aurelium.auraskills.bukkit.requirement.blocks;
2+
3+
import dev.aurelium.auraskills.bukkit.AuraSkills;
4+
import org.bukkit.entity.Player;
5+
6+
public class PermissionNode extends RequirementNode {
7+
8+
private final String permission;
9+
10+
public PermissionNode(AuraSkills plugin, String permission, String message) {
11+
super(plugin, message);
12+
this.permission = permission;
13+
}
14+
15+
@Override
16+
public boolean check(Player player) {
17+
return player.hasPermission(permission);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package dev.aurelium.auraskills.bukkit.requirement.blocks;
2+
3+
import dev.aurelium.auraskills.bukkit.AuraSkills;
4+
import org.bukkit.entity.Player;
5+
6+
public abstract class RequirementNode {
7+
8+
protected AuraSkills plugin;
9+
protected String denyMessage;
10+
11+
public RequirementNode(AuraSkills plugin, String denyMessage) {
12+
this.plugin = plugin;
13+
this.denyMessage = denyMessage;
14+
}
15+
16+
public abstract boolean check(Player player);
17+
18+
public String getDenyMessage() {
19+
return denyMessage;
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dev.aurelium.auraskills.bukkit.requirement.blocks;
2+
3+
import dev.aurelium.auraskills.api.skill.Skill;
4+
import dev.aurelium.auraskills.bukkit.AuraSkills;
5+
import org.bukkit.entity.Player;
6+
7+
public class SkillNode extends RequirementNode {
8+
9+
private final Skill skill;
10+
private final int level;
11+
12+
public SkillNode(AuraSkills plugin, Skill skill, int level, String message) {
13+
super(plugin, message);
14+
this.skill = skill;
15+
this.level = level;
16+
}
17+
18+
@Override
19+
public boolean check(Player player) {
20+
return plugin.getUser(player).getSkillLevel(skill) >= level;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dev.aurelium.auraskills.bukkit.requirement.blocks;
2+
3+
import dev.aurelium.auraskills.api.stat.Stat;
4+
import dev.aurelium.auraskills.bukkit.AuraSkills;
5+
import org.bukkit.entity.Player;
6+
7+
public class StatNode extends RequirementNode {
8+
9+
private final Stat stat;
10+
private final int value;
11+
12+
public StatNode(AuraSkills plugin, Stat stat, int value, String message) {
13+
super(plugin, message);
14+
this.stat = stat;
15+
this.value = value;
16+
}
17+
18+
@Override
19+
public boolean check(Player player) {
20+
return plugin.getUser(player).getStatLevel(stat) >= value;
21+
}
22+
}

common/src/main/java/dev/aurelium/auraskills/common/config/Option.java

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ public enum Option {
141141
REQUIREMENT_ITEM_PREVENT_BLOCK_PLACE("requirement.item.prevent_block_place", OptionType.BOOLEAN),
142142
REQUIREMENT_ITEM_PREVENT_INTERACT("requirement.item.prevent_interact", OptionType.BOOLEAN),
143143
REQUIREMENT_ARMOR_PREVENT_ARMOR_EQUIP("requirement.armor.prevent_armor_equip", OptionType.BOOLEAN),
144+
REQUIREMENT_BLOCKS_ENABLED("requirement.blocks.enabled", OptionType.BOOLEAN),
144145
// Damage options
145146
DAMAGE_CORRECT_LAST_DAMAGE("damage.correct_last_damage", OptionType.BOOLEAN),
146147
// Critical options

common/src/main/resources/config.yml

+3
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ requirement:
235235
armor:
236236
prevent_armor_equip: true
237237
global: [ ]
238+
blocks:
239+
enabled: true
240+
list: [ ]
238241
damage:
239242
correct_last_damage: true
240243
critical:

0 commit comments

Comments
 (0)