Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: "🐛 Bug Report"
description: Report a bug or unexpected behavior
labels: ["bug"]
body:
- type: input
id: summary
attributes:
label: Summary
description: One-line summary of the bug
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to Reproduce
description: Step-by-step instructions to reproduce
placeholder: |
1. Start server with plugin version X
2. Run command /...
3. Observe error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: What should happen?
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Behavior
description: What actually happens?
validations:
required: true
- type: input
id: plugin_version
attributes:
label: Plugin Version
placeholder: "e.g. v1.2.10"
validations:
required: true
- type: input
id: server_version
attributes:
label: Server Version
description: Output of /version
placeholder: "e.g. Paper 1.21.4-123"
validations:
required: true
- type: input
id: java_version
attributes:
label: Java Version
placeholder: "e.g. Java 21.0.2"
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs / Stacktrace
description: Relevant console output (use code block)
render: shell
- type: textarea
id: extra
attributes:
label: Additional Context
description: Screenshots, configs, other plugins installed, etc.
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: "💬 Discord Support"
url: https://discord.gg/RYFamQzkcB
about: Get help or chat with the community
- name: "📖 Documentation"
url: https://chafficplugins.github.io
about: Check the docs before filing an issue
33 changes: 33 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: "✨ Feature Request"
description: Suggest a new feature or improvement
labels: ["feature"]
body:
- type: textarea
id: problem
attributes:
label: Problem / Motivation
description: What problem does this solve? Why is it needed?
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: How should this work?
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: Other approaches you've thought about
- type: textarea
id: acceptance
attributes:
label: Acceptance Criteria
description: How do we know this is done?
placeholder: |
- [ ] Criterion 1
- [ ] Criterion 2
validations:
required: true
24 changes: 24 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## What
<!-- What does this PR do? Keep it short. -->

## Why
<!-- Why is this change needed? Link the issue. -->

Closes #

## How
<!-- How was this implemented? Key technical decisions. -->

## Testing
<!-- How was this tested? -->

- [ ] Unit tests added/updated
- [ ] `mvn verify` passes locally
- [ ] Tested manually on a test server (if applicable)

## Checklist
- [ ] Issue linked above
- [ ] Tests pass
- [ ] No new warnings
- [ ] Docs updated (if user-facing change)
- [ ] Changelog entry added (if user-facing change)
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package io.github.chafficui.CrucialLib.Utils.api;

import io.github.chafficui.CrucialLib.Main;
import org.bukkit.Bukkit;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.HashMap;

public class Bossbar {
private static final Main PLUGIN = Main.getPlugin(Main.class);
private static final HashMap<Player, Bar> bossbars = new HashMap<>();

private static JavaPlugin getPlugin() {
return (JavaPlugin) Bukkit.getPluginManager().getPlugin("CrucialLib");
}

private static class Bar {
BossBar bar;
Player player;
Expand All @@ -28,7 +31,7 @@ public void run() {
bar.removePlayer(player);
}
};
runnable.runTaskLater(PLUGIN, ticks);
runnable.runTaskLater(getPlugin(), ticks);
}

public void newTime(long ticks) {
Expand All @@ -39,7 +42,7 @@ public void run() {
bar.removePlayer(player);
}
};
runnable.runTaskLater(PLUGIN, ticks);
runnable.runTaskLater(getPlugin(), ticks);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package io.github.chafficui.CrucialLib.Utils.customItems;

import io.github.chafficui.CrucialLib.Utils.Server;
import io.github.chafficui.CrucialLib.Main;
import io.github.chafficui.CrucialLib.exceptions.CrucialException;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.List;
import java.util.Objects;
import java.util.UUID;

public class Item {
private static final Main PLUGIN = Main.getPlugin(Main.class);
private static JavaPlugin getPlugin() {
return (JavaPlugin) Bukkit.getPluginManager().getPlugin("CrucialLib");
}

public static NamespacedKey createItem(String key, String name, List<String> lore,
Material material, String[] recipe) throws CrucialException {
Expand Down Expand Up @@ -48,16 +50,19 @@ private static NamespacedKey addRecipe(String key, String name, String[] recipe,
name = name.replaceAll(" ", "_");
key = key.replaceAll(" ", "_");
key = key.replaceAll(":", ".");
NamespacedKey namespacedKey = new NamespacedKey(PLUGIN, name + key);
NamespacedKey namespacedKey = new NamespacedKey(getPlugin(), name + key);
ShapedRecipe shapedRecipe = new ShapedRecipe(namespacedKey, stack);
int num = 48;

shapedRecipe.shape("123","456","789");

for (String item:recipe) {
num++;
char c = (char)num;
shapedRecipe.setIngredient(c, Objects.requireNonNull(Material.getMaterial(item)));
Material mat = Objects.requireNonNull(Material.getMaterial(item));
if (mat != Material.AIR) {
char c = (char)num;
shapedRecipe.setIngredient(c, mat);
}
}

Bukkit.addRecipe(shapedRecipe);
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/io/github/chafficui/CrucialLib/io/Yaml.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package io.github.chafficui.CrucialLib.io;

import io.github.chafficui.CrucialLib.Main;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.io.IOException;

public class Yaml {
private static final Main plugin = Main.getPlugin(Main.class);

public static void saveFile(FileConfiguration file, File datafolder, String filename) throws IOException {
file.save(new File(datafolder, filename));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package io.github.chafficui.CrucialLib.Events;

import io.github.chafficui.CrucialLib.Main;
import io.github.chafficui.CrucialLib.Utils.customItems.CrucialItem;
import io.github.chafficui.CrucialLib.exceptions.CrucialException;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockbukkit.mockbukkit.MockBukkit;
import org.mockbukkit.mockbukkit.ServerMock;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class CrucialItemEventsTest {

private ServerMock server;

@BeforeEach
void setUp() {
server = MockBukkit.mock();
MockBukkit.load(Main.class);
CrucialItem.CRUCIAL_ITEMS.clear();
}

@AfterEach
void tearDown() {
CrucialItem.CRUCIAL_ITEMS.clear();
MockBukkit.unmock();
}

// --- Core event logic tests (without relying on MockBukkit event dispatch quirks) ---

@Test
void registeredItemIsInGlobalSet() throws CrucialException {
String[] recipe = new String[]{"AIR", "AIR", "AIR", "AIR", "DIAMOND", "AIR", "AIR", "AIR", "AIR"};
CrucialItem item = new CrucialItem("Blocked", Material.DIAMOND_SWORD, List.of(), recipe, "test", true, false, false);
item.register();

assertTrue(CrucialItem.CRUCIAL_ITEMS.contains(item));
assertFalse(item.isUsable, "Item should be non-usable");
}

@Test
void usableItemFlagIsRespected() throws CrucialException {
String[] recipe = new String[]{"AIR", "AIR", "AIR", "AIR", "DIAMOND", "AIR", "AIR", "AIR", "AIR"};
CrucialItem item = new CrucialItem("Usable", Material.IRON_SWORD, List.of(), recipe, "test", true, true, false);
item.register();

assertTrue(item.isUsable, "Item should be usable");
}

@Test
void craftingFlagIsRespected() throws CrucialException {
String[] recipe = new String[]{"AIR", "AIR", "AIR", "AIR", "DIAMOND", "AIR", "AIR", "AIR", "AIR"};
CrucialItem allowedItem = new CrucialItem("Allowed", Material.DIAMOND, List.of(), recipe, "test", true, true, true);
CrucialItem blockedItem = new CrucialItem("Blocked", Material.GOLD_INGOT, List.of(), recipe, "test2", true, true, false);
allowedItem.register();
blockedItem.register();

assertTrue(allowedItem.isAllowedForCrafting, "Item should be allowed for crafting");
assertFalse(blockedItem.isAllowedForCrafting, "Item should not be allowed for crafting");
}

@Test
void plainItemIsNotRecognizedAsCrucialItem() {
ItemStack plainStack = new ItemStack(Material.STONE);
assertNull(CrucialItem.getByStack(plainStack), "Plain items should not be recognized as CrucialItems");
}

@Test
void nullItemIsNotRecognizedAsCrucialItem() {
assertNull(CrucialItem.getId(null), "Null should not be recognized as a CrucialItem");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.github.chafficui.CrucialLib.Utils.api;

import io.github.chafficui.CrucialLib.Main;
import org.bukkit.boss.BarColor;
import org.bukkit.entity.Player;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockbukkit.mockbukkit.MockBukkit;
import org.mockbukkit.mockbukkit.ServerMock;

import static org.junit.jupiter.api.Assertions.*;

class BossbarTest {

private ServerMock server;

@BeforeEach
void setUp() {
server = MockBukkit.mock();
MockBukkit.load(Main.class);
}

@AfterEach
void tearDown() {
MockBukkit.unmock();
}

@Test
void sendBossbarDoesNotThrow() {
Player player = server.addPlayer();
assertDoesNotThrow(() -> Bossbar.sendBossbar(player, "Test Bar", BarColor.RED, 50f, 100L));
}

@Test
void sendBossbarTwiceToSamePlayerDoesNotThrow() {
Player player = server.addPlayer();
Bossbar.sendBossbar(player, "First", BarColor.BLUE, 25f, 100L);
assertDoesNotThrow(() -> Bossbar.sendBossbar(player, "Updated", BarColor.GREEN, 75f, 200L));
}

@Test
void sendBossbarToDifferentPlayers() {
Player player1 = server.addPlayer();
Player player2 = server.addPlayer();

assertDoesNotThrow(() -> {
Bossbar.sendBossbar(player1, "Bar 1", BarColor.RED, 50f, 100L);
Bossbar.sendBossbar(player2, "Bar 2", BarColor.BLUE, 75f, 100L);
});
}

@Test
void sendBossbarWithZeroProgress() {
Player player = server.addPlayer();
assertDoesNotThrow(() -> Bossbar.sendBossbar(player, "Empty", BarColor.WHITE, 0f, 100L));
}

@Test
void sendBossbarWithFullProgress() {
Player player = server.addPlayer();
assertDoesNotThrow(() -> Bossbar.sendBossbar(player, "Full", BarColor.YELLOW, 100f, 100L));
}
}
Loading
Loading