Skip to content

Commit ba38ac9

Browse files
committed
Beta v1.0.0 MVP
Drop Spigot support (as Fancy Npcs not have), make data store logic, make corpse break logic and moore...
1 parent 21c35c5 commit ba38ac9

File tree

14 files changed

+530
-47
lines changed

14 files changed

+530
-47
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build and Publish
1+
name: Build and Archive
22

33
on:
44
push:
@@ -16,7 +16,7 @@ jobs:
1616
- name: Set up JDK
1717
uses: actions/setup-java@v4
1818
with:
19-
distribution: "temurin"
19+
distribution: "zulu"
2020
java-version: "21"
2121

2222
- name: Make gradlew executable

.github/workflows/release.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ on:
99
status:
1010
required: true
1111
description: "Status (beta, stable)"
12+
description:
13+
required: false
14+
description: "Release description"
1215

1316
env:
1417
VERSION: ${{ github.event.inputs.tag }}-${{ github.event.inputs.status }}
@@ -24,7 +27,7 @@ jobs:
2427
- name: Set up JDK
2528
uses: actions/setup-java@v4
2629
with:
27-
distribution: "temurin"
30+
distribution: "zulu"
2831
java-version: "21"
2932

3033
- name: Cache Gradle dependencies
@@ -73,7 +76,8 @@ jobs:
7376
with:
7477
prerelease: false
7578
tag: ${{ github.event.inputs.tag }}
76-
artifacts: build/libs/PlayerCorpses-*.jar
79+
artifacts: build/libs/PlayerCorpses-*-shaded.jar
80+
body: ${{ github.event.inputs.description }}
7781
env:
7882
GITHUB_REPOSITORY: AvionBlock/PlayerCorpses
7983

@@ -83,6 +87,7 @@ jobs:
8387
with:
8488
prerelease: true
8589
tag: ${{ github.event.inputs.tag }}
86-
artifacts: build/libs/PlayerCorpses-*.jar
90+
artifacts: build/libs/PlayerCorpses-*-shaded.jar
91+
body: ${{ github.event.inputs.description }}
8792
env:
8893
GITHUB_REPOSITORY: AvionBlock/PlayerCorpses

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ java {
5555
}
5656

5757
shadowJar {
58-
archiveClassifier.set('all')
58+
archiveClassifier.set('shaded')
5959
// Relocate package to avoid conflicts
6060
relocate "com.tcoded.folialib", "io.greitan.avion.lib.folialib"
6161
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

src/main/java/io/greitan/avion/PlayerCorpses.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1+
/*
2+
* Comments generated using 0xAlpha AI Comment Generator v1.4.1
3+
* Copyright (c) 2025 by 0xAlpha. All rights reserved.
4+
* This software is provided "as-is", without warranty of any kind, express or implied.
5+
*/
16
package io.greitan.avion;
27

38
import org.bukkit.plugin.java.JavaPlugin;
4-
59
import io.greitan.avion.listeners.*;
610
import io.greitan.avion.utils.*;
7-
811
import lombok.Getter;
12+
import net.kyori.adventure.text.minimessage.MiniMessage;
913

14+
/**
15+
* Main class for the PlayerCorpses plugin.
16+
*/
1017
public class PlayerCorpses extends JavaPlugin {
18+
1119
private static @Getter PlayerCorpses instance;
1220
private static @Getter LocaleManager locManager;
21+
private static @Getter MiniMessage MM = MiniMessage.miniMessage();
1322

23+
/**
24+
* Called when the plugin is enabled. Initializes locale manager and registers
25+
* event listeners.
26+
*/
1427
@Override
1528
public void onEnable() {
1629
instance = this;
@@ -22,11 +35,17 @@ public void onEnable() {
2235
Logger.info(locManager.getMessage("plugin.enabled"));
2336
}
2437

38+
/**
39+
* Called when the plugin is disabled. Logs the shutdown message.
40+
*/
2541
@Override
2642
public void onDisable() {
2743
Logger.info(locManager.getMessage("plugin.disabled"));
2844
}
2945

46+
/**
47+
* Reloads the plugin configuration and sets the locale.
48+
*/
3049
public void reload() {
3150
saveDefaultConfig();
3251
reloadConfig();
@@ -36,4 +55,4 @@ public void reload() {
3655

3756
Logger.info("Language set to: " + locale);
3857
}
39-
}
58+
}
Lines changed: 180 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,198 @@
1+
/*
2+
* Comments generated using 0xAlpha AI Comment Generator v1.4.1
3+
* Copyright (c) 2025 by 0xAlpha. All rights reserved.
4+
* This software is provided "as-is", without warranty of any kind, express or implied.
5+
*/
16
package io.greitan.avion.listeners;
27

8+
import org.bukkit.Bukkit;
9+
import org.bukkit.Location;
10+
import org.bukkit.Material;
11+
import org.bukkit.NamespacedKey;
12+
import org.bukkit.configuration.file.YamlConfiguration;
13+
import org.bukkit.entity.Player;
314
import org.bukkit.event.EventHandler;
415
import org.bukkit.event.Listener;
16+
import org.bukkit.event.inventory.InventoryClickEvent;
17+
import org.bukkit.event.inventory.InventoryType;
18+
import org.bukkit.inventory.Inventory;
19+
import org.bukkit.inventory.ItemStack;
20+
import org.bukkit.persistence.PersistentDataType;
521

22+
import de.oliver.fancynpcs.api.FancyNpcsPlugin;
23+
import de.oliver.fancynpcs.api.Npc;
624
import de.oliver.fancynpcs.api.events.NpcInteractEvent;
25+
import de.oliver.fancynpcs.api.events.NpcRemoveEvent;
26+
import de.oliver.fancynpcs.api.events.NpcStopLookingEvent;
27+
import io.greitan.avion.PlayerCorpses;
728
import io.greitan.avion.utils.LocaleManager;
829
import io.greitan.avion.utils.Logger;
30+
import io.greitan.avion.utils.MenuBuilder;
31+
import io.greitan.avion.utils.YamlBase;
32+
import net.kyori.adventure.text.Component;
33+
34+
import java.util.stream.IntStream;
935

1036
public class NpcInteractListener implements Listener {
11-
// private final LocaleManager localeManager;
37+
private final LocaleManager localeManager;
38+
private final Component MENU_TITLE;
1239

40+
/**
41+
* Constructor initializes the listener with a locale manager.
42+
*
43+
* @param localeManager Locale manager for handling messages.
44+
*/
1345
public NpcInteractListener(LocaleManager localeManager) {
14-
// this.localeManager = localeManager;
46+
this.localeManager = localeManager;
47+
this.MENU_TITLE = PlayerCorpses.getMM().deserialize(localeManager.getMessage("menu.title"));
1548
}
1649

50+
/**
51+
* Handles NPC interaction, shows the menu when a player interacts with an NPC.
52+
*
53+
* @param e The NPC interaction event.
54+
*/
1755
@EventHandler
1856
public void npcInteract(NpcInteractEvent e) {
19-
Logger.info(e.getNpc().getData().getName());
57+
showMenu(e.getPlayer(), e.getNpc());
58+
}
59+
60+
/**
61+
* Handles inventory click events in the menu.
62+
*
63+
* @param event The inventory click event.
64+
*/
65+
@EventHandler
66+
public void onInventoryClick(InventoryClickEvent event) {
67+
if (!(event.getWhoClicked() instanceof Player player))
68+
return;
69+
if (event.getInventory().getType() != InventoryType.CHEST)
70+
return;
71+
if (!event.getView().title().equals(MENU_TITLE))
72+
return;
73+
74+
event.setCancelled(true);
75+
76+
ItemStack clickedItem = event.getCurrentItem();
77+
if (clickedItem == null || clickedItem.getType() == Material.AIR)
78+
return;
79+
80+
// Handle actions based on the clicked item
81+
String action = switch (clickedItem.getType()) {
82+
case ARROW -> "break";
83+
case BARRIER -> "back";
84+
default -> null;
85+
};
86+
87+
if (action != null) {
88+
player.closeInventory();
89+
handleAction(player, action, clickedItem);
90+
}
91+
}
92+
93+
/**
94+
* Executes the appropriate action based on the clicked item.
95+
*
96+
* @param player The player who clicked the item.
97+
* @param action The action to perform.
98+
* @param clickedItem The item clicked.
99+
*/
100+
private void handleAction(Player player, String action, ItemStack clickedItem) {
101+
NamespacedKey key = new NamespacedKey(PlayerCorpses.getInstance(), "corpse");
102+
String npcID = clickedItem.getItemMeta().getPersistentDataContainer().get(key, PersistentDataType.STRING);
103+
switch (action) {
104+
case "break" -> {
105+
if (npcID != null)
106+
breakCorpse(player, npcID);
107+
player.sendMessage(PlayerCorpses.getMM().deserialize(localeManager.getMessage("menu.action.break")));
108+
}
109+
case "back" -> {
110+
player.sendMessage(PlayerCorpses.getMM().deserialize(localeManager.getMessage("menu.action.back")));
111+
}
112+
default -> {
113+
}
114+
}
115+
}
116+
117+
/**
118+
* Breaks the corpse NPC and handles the drop of items from the corpse.
119+
*
120+
* @param player The player interacting with the NPC.
121+
* @param npcID The NPC ID.
122+
*/
123+
private void breakCorpse(Player player, String npcID) {
124+
Npc npc = FancyNpcsPlugin.get().getNpcManager().getNpcById(npcID);
125+
String containerId = npc.getData().getName();
126+
YamlConfiguration containerData;
127+
128+
try {
129+
containerData = YamlBase.loadPlayerData(player.getName(), containerId);
130+
} catch (IllegalStateException e) {
131+
Logger.error(e);
132+
return;
133+
}
134+
135+
Location dropLocation = npc.getData().getLocation();
136+
137+
// Remove NPC and handle its drops
138+
if (new NpcRemoveEvent(npc, Bukkit.getServer().getConsoleSender()).callEvent()) {
139+
npc.removeForAll();
140+
for (Player onlinePlayer : Bukkit.getOnlinePlayers()) {
141+
if (npc.getIsLookingAtPlayer().getOrDefault(onlinePlayer.getUniqueId(), false)) {
142+
npc.getIsLookingAtPlayer().put(onlinePlayer.getUniqueId(), false);
143+
new NpcStopLookingEvent(npc, onlinePlayer).callEvent();
144+
}
145+
}
146+
FancyNpcsPlugin.get().getNpcManager().removeNpc(npc);
147+
148+
// Drop items if any exist
149+
if (containerData.contains("inventory")) {
150+
try {
151+
ItemStack[] inventoryContents = YamlBase
152+
.itemStackArrayFromBase64(containerData.getString("inventory"));
153+
for (ItemStack item : inventoryContents) {
154+
if (item != null) {
155+
dropLocation.getWorld().dropItemNaturally(dropLocation, item);
156+
}
157+
}
158+
} catch (IllegalStateException e) {
159+
Logger.error(e);
160+
}
161+
}
162+
163+
YamlBase.deletePlayerData(player.getName(), containerId);
164+
} else {
165+
player.sendMessage(PlayerCorpses.getMM().deserialize(localeManager.getMessage("corpse.break_error")));
166+
}
167+
}
168+
169+
/**
170+
* Shows the interaction menu for a player and NPC.
171+
*
172+
* @param player The player to show the menu to.
173+
* @param npc The NPC the player is interacting with.
174+
*/
175+
private void showMenu(Player player, Npc npc) {
176+
Inventory inv = Bukkit.createInventory(null, 27, MENU_TITLE);
177+
fillBorders(inv);
178+
inv.setItem(11,
179+
MenuBuilder.createItem(Material.BARRIER, localeManager.getMessage("menu.button.back"),
180+
null, npc.getData().getId()));
181+
inv.setItem(15,
182+
MenuBuilder.createItem(Material.ARROW, localeManager.getMessage("menu.button.break"),
183+
null, npc.getData().getId()));
184+
player.openInventory(inv);
185+
}
186+
187+
/**
188+
* Fills the borders of the inventory with decorative items.
189+
*
190+
* @param inv The inventory to fill.
191+
*/
192+
private void fillBorders(Inventory inv) {
193+
IntStream.range(0, 27)
194+
.filter(i -> i != 11 && i != 15)
195+
.forEach(i -> inv.setItem(i,
196+
MenuBuilder.createItem(Material.LIGHT_BLUE_STAINED_GLASS_PANE, "", null, null)));
20197
}
21198
}

0 commit comments

Comments
 (0)