Skip to content

Commit a54d4b4

Browse files
authored
Add permissions, reload command and workflows (#7)
2 parents 912425c + 06ec15b commit a54d4b4

File tree

11 files changed

+223
-42
lines changed

11 files changed

+223
-42
lines changed

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "maven"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"

.github/workflows/maven.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
3+
4+
# This workflow uses actions that are not certified by GitHub.
5+
# They are provided by a third-party and are governed by
6+
# separate terms of service, privacy policy, and support
7+
# documentation.
8+
9+
name: Java CI with Maven
10+
11+
permissions:
12+
contents: write
13+
14+
on:
15+
push:
16+
branches: [ "main" ]
17+
pull_request:
18+
branches: [ "main" ]
19+
20+
jobs:
21+
build:
22+
23+
runs-on: ubuntu-latest
24+
25+
steps:
26+
- uses: actions/checkout@v3
27+
- name: Set up JDK 17
28+
uses: actions/setup-java@v3
29+
with:
30+
java-version: '17'
31+
distribution: 'temurin'
32+
cache: maven
33+
- name: Build with Maven
34+
run: mvn -B package --file pom.xml
35+
36+
# Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
37+
- name: Submit Dependency Snapshot
38+
uses: advanced-security/maven-dependency-submission-action@v3

.github/workflows/release.yml

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,42 @@
11
name: Maven Release
22

33
on:
4-
release:
5-
types: [ published ]
4+
release:
5+
types: [ published ]
66

77
jobs:
8-
package-and-upload:
9-
name: Build and Upload JARs
10-
runs-on: ubuntu-latest
11-
12-
steps:
13-
- name: Checkout code
14-
uses: actions/checkout@v3
15-
16-
- name: Set up Java
17-
uses: actions/setup-java@v3
18-
with:
19-
java-version: '17'
20-
distribution: 'corretto'
21-
22-
- name: Build and package Maven project
23-
run: mvn clean package
24-
25-
- name: Upload to release
26-
uses: JasonEtco/upload-to-release@master
27-
with:
28-
args: target/EnchantBookPlus-${{ github.event.release.tag_name }}.jar application/java-archive
29-
env:
30-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8+
package-and-upload:
9+
name: Build and Upload JARs
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v3
15+
16+
- name: Set up Java
17+
uses: actions/setup-java@v3
18+
with:
19+
java-version: '17'
20+
distribution: 'temurin'
21+
22+
- name: Set project version
23+
run: mvn -B versions:set -DnewVersion=${{ github.event.release.tag_name }} -DgenerateBackupPoms=false
24+
25+
- name: Build and package Maven project
26+
run: mvn clean package
27+
28+
- name: Upload to release
29+
uses: JasonEtco/upload-to-release@master
30+
with:
31+
args: target/EnchantBookPlus-${{ github.event.release.tag_name }}.jar application/java-archive
32+
env:
33+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34+
35+
- name: Upload to Modrinth
36+
uses: cloudnode-pro/[email protected]
37+
with:
38+
token: '${{ secrets.MODRINTH_TOKEN }}'
39+
project: '${{ github.event.repository.custom_properties.modrinth_id }}'
40+
file: target/EnchantBookPlus-${{ github.event.release.tag_name }}.jar
41+
changelog: ${{ github.event.release.body }}
42+
loaders: paper

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ This plugin allows you to combine enchantments, e.g. Efficiency V + Efficiency V
1313

1414
You can configure which enchantments can be combined above the Vanilla Minecraft levels. You can set the max level for each enchantment, and add XP cost in levels.
1515

16+
> [!IMPORTANT]
17+
> This plugin requires [AnvilUnlocker](https://github.com/Jikoo/AnvilUnlocker/releases/latest) for anvil costs above 40 lvl.
18+
19+
## Permissions
20+
21+
> [!NOTE]
22+
> `<echantment>` is the enchantment ID, e.g. `swift_sneak`, `efficiency`, etc. Replace with `*` for all enchantments.
23+
>
24+
> Example: `enchantbookplus.enchant.*` or `enchantbookplus.enchant.unbreaking`
25+
26+
| Permission | Description |
27+
|-----------------------------------------|----------------------------------------------------------------------------------------|
28+
| `enchantbookplus.enchant.<enchantment>` | Allow enchanting `<enchantment>` above the vanilla level, as configured in the plugin. |
29+
| `enchantbookplus.reload` | Reload plugin config using `/enchantbookplus reload` |
30+
1631
## Reporting issues
1732
Fixing bugs is the utmost priority for this project. If you find any issue, check the [GitHub Issue Tracker](https://github.com/cloudnode-pro/EnchantBookPlus/issues) to see if it has already been reported. If not, create a new issue.
1833

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>pro.cloudnode.smp</groupId>
88
<artifactId>EnchantBookPlus</artifactId>
9-
<version>0.0.0</version>
9+
<version>0.0.0-SNAPSHOT</version>
1010
<packaging>jar</packaging>
1111

1212
<name>EnchantBookPlus</name>

src/main/java/pro/cloudnode/smp/enchantbookplus/ConfigEnchantmentEntry.java

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,43 @@
1212
import java.util.Optional;
1313
import java.util.stream.Collectors;
1414

15-
public final class ConfigEnchantmentEntry {
15+
public class ConfigEnchantmentEntry {
1616
/**
1717
* Name of the enchantment.
1818
*/
19-
private final @NotNull String name;
19+
public final @NotNull String name;
2020

2121
/**
2222
* Maximum level of the enchantment.
2323
*/
24-
private final @Nullable Integer maxLevel;
24+
protected final @Nullable Integer maxLevel;
2525

2626
/**
2727
* Max level relative
2828
*/
29-
private final boolean maxLevelRelative;
29+
protected final boolean maxLevelRelative;
3030

3131
/**
3232
* Cost of the enchantment.
3333
*/
34-
private final int cost;
34+
protected final int cost;
3535

3636
/**
3737
* Multiply cost by level.
3838
*/
39-
private final boolean multiplyCostByLevel;
39+
protected final boolean multiplyCostByLevel;
4040

4141
/**
4242
* Name of the enchantment.
4343
*/
44-
public @NotNull String getName() {
44+
public final @NotNull String getName() {
4545
return name;
4646
}
4747

4848
/**
4949
* Maximum level of the enchantment.
5050
*/
51-
public @NotNull Optional<Integer> getMaxLevel() {
51+
public final @NotNull Optional<@NotNull Integer> getMaxLevel() {
5252
if (Optional.ofNullable(maxLevel).isEmpty()) return Optional.empty();
5353
if (maxLevelRelative) return Optional.of(getEnchantment().getMaxLevel() + maxLevel);
5454
return Optional.of(maxLevel);
@@ -57,21 +57,21 @@ public final class ConfigEnchantmentEntry {
5757
/**
5858
* Cost of the enchantment.
5959
*/
60-
public int getCost() {
60+
public final int getCost() {
6161
return cost;
6262
}
6363

6464
/**
6565
* Multiply cost by level.
6666
*/
67-
public boolean getMultiplyCostByLevel() {
67+
public final boolean getMultiplyCostByLevel() {
6868
return multiplyCostByLevel;
6969
}
7070

7171
/**
7272
* Get enchantment
7373
*/
74-
public Enchantment getEnchantment() {
74+
public final Enchantment getEnchantment() {
7575
return Enchantment.getByKey(NamespacedKey.minecraft(name));
7676
}
7777

@@ -80,7 +80,7 @@ public Enchantment getEnchantment() {
8080
*
8181
* @param enchantment The enchantment
8282
*/
83-
public boolean isEnchantment(final @NotNull Enchantment enchantment) {
83+
public final boolean isEnchantment(final @NotNull Enchantment enchantment) {
8484
return name.equalsIgnoreCase(enchantment.getKey().getKey());
8585
}
8686

@@ -104,7 +104,7 @@ public ConfigEnchantmentEntry(final @NotNull String name, final @Nullable Intege
104104
*
105105
* @param configValue Config object
106106
*/
107-
public static ConfigEnchantmentEntry configValue(final @NotNull HashMap<@NotNull String, @NotNull Object> configValue) {
107+
public static @NotNull ConfigEnchantmentEntry configValue(final @NotNull HashMap<@NotNull String, @NotNull Object> configValue) {
108108
final @NotNull String name = (String) Objects.requireNonNull(configValue.get("name"));
109109
final @Nullable Integer maxLevel;
110110
final boolean maxLevelRelative;
@@ -192,4 +192,18 @@ private static boolean isValidConfigValue(final @Nullable Object configValue) {
192192
if (!isValidConfigValue(configValue)) throw new IllegalArgumentException("Invalid config value");
193193
return configArray((ArrayList<HashMap<String, Object>>) configValue);
194194
}
195+
196+
public static final class AllConfigEnchantmentEntry extends ConfigEnchantmentEntry {
197+
private AllConfigEnchantmentEntry(final @Nullable Integer maxLevel, final boolean maxLevelRelative, final int cost, final boolean multiplyCostByLevel) {
198+
super("ALL", maxLevel, maxLevelRelative, cost, multiplyCostByLevel);
199+
}
200+
201+
public static @NotNull AllConfigEnchantmentEntry from(final @NotNull ConfigEnchantmentEntry configEnchantmentEntry) {
202+
return new AllConfigEnchantmentEntry(configEnchantmentEntry.maxLevel, configEnchantmentEntry.maxLevelRelative, configEnchantmentEntry.cost, configEnchantmentEntry.multiplyCostByLevel);
203+
}
204+
205+
public @NotNull ConfigEnchantmentEntry enchant(final @NotNull Enchantment enchantment) {
206+
return new ConfigEnchantmentEntry(enchantment.getKey().getKey(), this.maxLevel, maxLevelRelative, cost, multiplyCostByLevel);
207+
}
208+
}
195209
}

src/main/java/pro/cloudnode/smp/enchantbookplus/EnchantBookPlus.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
import org.bukkit.enchantments.Enchantment;
44
import org.bukkit.plugin.java.JavaPlugin;
55
import org.jetbrains.annotations.NotNull;
6+
import org.jetbrains.annotations.Nullable;
67
import pro.cloudnode.smp.enchantbookplus.event.PrepareAnvil;
78

89
import java.util.ArrayList;
910
import java.util.List;
11+
import java.util.Objects;
1012
import java.util.Optional;
1113
import java.util.logging.Level;
14+
import java.util.stream.Collectors;
1215

1316
public final class EnchantBookPlus extends JavaPlugin {
1417
/**
@@ -34,35 +37,54 @@ private void registerEvents() {
3437
* Config enchantments cache
3538
*/
3639
public @NotNull List<@NotNull ConfigEnchantmentEntry> getConfigEnchantments() {
37-
if (configEnchantments.size() == 0) reload();
3840
return configEnchantments;
3941
}
4042

43+
/**
44+
* "ALL" enchantment cache
45+
*/
46+
private @Nullable ConfigEnchantmentEntry.AllConfigEnchantmentEntry allConfigEnchantment;
47+
48+
/**
49+
* "ALL" enchantment cache
50+
*/
51+
public @NotNull Optional<ConfigEnchantmentEntry.@NotNull AllConfigEnchantmentEntry> getAllConfigEnchantment() {
52+
return Optional.ofNullable(allConfigEnchantment);
53+
}
54+
4155
/**
4256
* Get enchantment from cache
4357
*
4458
* @param enchantment The Minecraft enchantment
4559
*/
4660
public @NotNull Optional<@NotNull ConfigEnchantmentEntry> getConfigEnchantment(final @NotNull Enchantment enchantment) {
47-
return getConfigEnchantments().stream().filter(c -> c.isEnchantment(enchantment)).findFirst();
61+
final @NotNull Optional<@NotNull ConfigEnchantmentEntry> entry = getConfigEnchantments().stream().filter(c -> c.isEnchantment(enchantment)).findFirst();
62+
return entry.isEmpty() ? getAllConfigEnchantment().map(a -> a.enchant(enchantment)) : entry;
4863
}
4964

5065
/**
5166
* Reload config
5267
*/
5368
public void reload() {
5469
reloadConfig();
70+
final @NotNull List<@NotNull ConfigEnchantmentEntry> enchants;
5571
try {
56-
configEnchantments = ConfigEnchantmentEntry.config(getConfig().get("enchantments"));
72+
enchants = ConfigEnchantmentEntry.config(getConfig().get("enchantments"));
5773
}
5874
catch (final @NotNull Exception exception) {
5975
getLogger().log(Level.SEVERE, "Failed to load config", exception);
6076
getServer().getPluginManager().disablePlugin(this);
77+
return;
6178
}
79+
allConfigEnchantment = enchants.stream()
80+
.filter(c -> c.name.equalsIgnoreCase("ALL")).findFirst().map(ConfigEnchantmentEntry.AllConfigEnchantmentEntry::from).orElse(null);
81+
configEnchantments = enchants.stream().filter(c -> !c.name.equalsIgnoreCase("ALL")).collect(Collectors.toList());
6282
}
6383

6484
@Override
6585
public void onEnable() {
86+
Objects.requireNonNull(getCommand("enchantbookplus")).setExecutor(new MainCommand());
87+
6688
registerEvents();
6789
saveDefaultConfig();
6890
reload();
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package pro.cloudnode.smp.enchantbookplus;
2+
3+
import net.kyori.adventure.text.minimessage.MiniMessage;
4+
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
5+
import org.bukkit.command.Command;
6+
import org.bukkit.command.CommandExecutor;
7+
import org.bukkit.command.CommandSender;
8+
import org.bukkit.command.TabCompleter;
9+
import org.jetbrains.annotations.NotNull;
10+
import org.jetbrains.annotations.Nullable;
11+
12+
import java.util.List;
13+
import java.util.Optional;
14+
15+
public final class MainCommand implements CommandExecutor, TabCompleter {
16+
@Override
17+
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
18+
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) reload(sender, command);
19+
return overview(sender);
20+
}
21+
22+
@Override
23+
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
24+
return null;
25+
}
26+
27+
/**
28+
* Plugin overview
29+
*/
30+
public static boolean overview(final @NotNull CommandSender sender) {
31+
final @NotNull EnchantBookPlus plugin = EnchantBookPlus.getInstance();
32+
sender.sendMessage(MiniMessage.miniMessage()
33+
.deserialize("<green><name></green> <white>v<version> by</white> <gray><author></gray>", Placeholder.unparsed("name", plugin
34+
.getPluginMeta().getName()), Placeholder.unparsed("version", plugin.getPluginMeta()
35+
.getVersion()), Placeholder.unparsed("author", String.join(", ", plugin.getPluginMeta()
36+
.getAuthors()))));
37+
38+
return true;
39+
}
40+
41+
/**
42+
* Reload plugin configuration
43+
*/
44+
public static boolean reload(final @NotNull CommandSender sender, final @NotNull Command command) {
45+
if (!sender.hasPermission(Permissions.RELOAD)) {
46+
sender.sendMessage(Optional.ofNullable(command.permissionMessage()).orElse(sender.getServer().permissionMessage()));
47+
return true;
48+
}
49+
EnchantBookPlus.getInstance().reload();
50+
sender.sendMessage(MiniMessage.miniMessage().deserialize("<green>(!) Plugin configuration reloaded."));
51+
return true;
52+
}
53+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package pro.cloudnode.smp.enchantbookplus;
2+
3+
import org.bukkit.enchantments.Enchantment;
4+
import org.jetbrains.annotations.NotNull;
5+
6+
public final class Permissions {
7+
public static @NotNull String enchant(final @NotNull Enchantment enchantment) {
8+
return "enchantbookplus.enchant." + enchantment.getKey().getKey();
9+
}
10+
11+
public static @NotNull String RELOAD = "enchantbookplus.reload";
12+
}

0 commit comments

Comments
 (0)