Compare commits
10
Commits
8b1b3c4b5a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a2bf854d6b | ||
|
|
f51efad599 | ||
|
|
9f07d983bd | ||
|
|
f7962b8faa | ||
|
|
465cbd17fc | ||
|
|
f25e696448 | ||
|
|
e46e8b2e32 | ||
|
|
c6d7f02cef | ||
|
|
7da09d7601 | ||
|
|
d3c4f77931 |
@@ -4,10 +4,8 @@ import com.alttd.easter.commands.Command;
|
|||||||
import com.alttd.easter.config.Config;
|
import com.alttd.easter.config.Config;
|
||||||
import com.alttd.easter.config.Messages;
|
import com.alttd.easter.config.Messages;
|
||||||
import com.alttd.easter.data.DataManager;
|
import com.alttd.easter.data.DataManager;
|
||||||
import com.alttd.easter.glow.GlowManager;
|
|
||||||
import com.alttd.easter.gui.TurnInGuiManager;
|
import com.alttd.easter.gui.TurnInGuiManager;
|
||||||
import com.alttd.easter.listeners.DeathListener;
|
import com.alttd.easter.listeners.DeathListener;
|
||||||
import com.alttd.easter.listeners.SpawnListener;
|
|
||||||
import com.alttd.easter.npc.RabbitNpcManager;
|
import com.alttd.easter.npc.RabbitNpcManager;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@@ -16,19 +14,16 @@ public final class Easter extends JavaPlugin {
|
|||||||
|
|
||||||
private DataManager dataManager;
|
private DataManager dataManager;
|
||||||
private RabbitNpcManager rabbitNpcManager;
|
private RabbitNpcManager rabbitNpcManager;
|
||||||
private GlowManager glowManager;
|
|
||||||
private TurnInGuiManager turnInGuiManager;
|
private TurnInGuiManager turnInGuiManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
reloadConfigs();
|
reloadConfigs();
|
||||||
this.dataManager = new DataManager(this);
|
this.dataManager = new DataManager(this);
|
||||||
this.glowManager = new GlowManager(this);
|
|
||||||
this.turnInGuiManager = new TurnInGuiManager(dataManager);
|
this.turnInGuiManager = new TurnInGuiManager(dataManager);
|
||||||
this.rabbitNpcManager = new RabbitNpcManager(this, turnInGuiManager);
|
this.rabbitNpcManager = new RabbitNpcManager(this, turnInGuiManager, dataManager);
|
||||||
registerCommands();
|
registerCommands();
|
||||||
registerEvents();
|
registerEvents();
|
||||||
registerSchedulers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -44,7 +39,6 @@ public final class Easter extends JavaPlugin {
|
|||||||
|
|
||||||
private void registerEvents() {
|
private void registerEvents() {
|
||||||
PluginManager pluginManager = getServer().getPluginManager();
|
PluginManager pluginManager = getServer().getPluginManager();
|
||||||
pluginManager.registerEvents(new SpawnListener(glowManager), this);
|
|
||||||
pluginManager.registerEvents(new DeathListener(), this);
|
pluginManager.registerEvents(new DeathListener(), this);
|
||||||
pluginManager.registerEvents(rabbitNpcManager, this);
|
pluginManager.registerEvents(rabbitNpcManager, this);
|
||||||
pluginManager.registerEvents(turnInGuiManager, this);
|
pluginManager.registerEvents(turnInGuiManager, this);
|
||||||
@@ -57,8 +51,4 @@ public final class Easter extends JavaPlugin {
|
|||||||
rabbitNpcManager.reload();
|
rabbitNpcManager.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerSchedulers() {
|
|
||||||
// No schedulers required currently
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.alttd.easter.commands;
|
|||||||
import com.alttd.easter.Easter;
|
import com.alttd.easter.Easter;
|
||||||
import com.alttd.easter.commands.subcommands.Reload;
|
import com.alttd.easter.commands.subcommands.Reload;
|
||||||
import com.alttd.easter.commands.subcommands.SetPrize;
|
import com.alttd.easter.commands.subcommands.SetPrize;
|
||||||
|
import com.alttd.easter.commands.subcommands.SpawnEggs;
|
||||||
|
import com.alttd.easter.commands.subcommands.GetPrizes;
|
||||||
import com.alttd.easter.config.Messages;
|
import com.alttd.easter.config.Messages;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -33,11 +35,12 @@ public class Command implements CommandExecutor, TabExecutor {
|
|||||||
}
|
}
|
||||||
command.setExecutor(this);
|
command.setExecutor(this);
|
||||||
command.setTabCompleter(this);
|
command.setTabCompleter(this);
|
||||||
command.setAliases(List.of("pu"));
|
|
||||||
|
|
||||||
subCommands = List.of(
|
subCommands = List.of(
|
||||||
new Reload(easter),
|
new Reload(easter),
|
||||||
new SetPrize()
|
new SetPrize(),
|
||||||
|
new GetPrizes(),
|
||||||
|
new SpawnEggs()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.alttd.easter.commands.subcommands;
|
||||||
|
|
||||||
|
import com.alttd.easter.commands.SubCommand;
|
||||||
|
import com.alttd.easter.config.Config;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||||
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GetPrizes extends SubCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, String[] args) {
|
||||||
|
List<ItemStack> list = Config.PRIZES.LIST;
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
commandSender.sendRichMessage("<red>No prizes are configured.</red>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
commandSender.sendRichMessage("<gold>Configured prizes (index : material - name)</gold>");
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
ItemStack item = list.get(i);
|
||||||
|
String material = item.getType().name();
|
||||||
|
String name = material;
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
if (meta != null && meta.hasDisplayName()) {
|
||||||
|
Component component = meta.displayName();
|
||||||
|
if (component != null) {
|
||||||
|
name = PlainTextComponentSerializer.plainText().serialize(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commandSender.sendRichMessage("<gray><index></gray> : <yellow><material></yellow> - <green><name></green>",
|
||||||
|
TagResolver.resolver(
|
||||||
|
Placeholder.parsed("index", String.valueOf(i)),
|
||||||
|
Placeholder.parsed("material", material),
|
||||||
|
Placeholder.parsed("name", name)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "getprizes";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpMessage() {
|
||||||
|
return "<green>List configured prizes with index: <gold>/easter getprizes</gold></green>";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import org.bukkit.command.CommandSender;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SetPrize extends SubCommand {
|
public class SetPrize extends SubCommand {
|
||||||
@@ -22,8 +23,23 @@ public class SetPrize extends SubCommand {
|
|||||||
player.sendRichMessage(Messages.SETPRIZE.EMPTY_HAND);
|
player.sendRichMessage(Messages.SETPRIZE.EMPTY_HAND);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// args[0] is the subcommand name. Optional args[1] may be index.
|
||||||
|
if (args.length >= 2) {
|
||||||
|
try {
|
||||||
|
int index = Integer.parseInt(args[1]);
|
||||||
|
if (index < 0 || index > Config.PRIZES.LIST.size()) {
|
||||||
|
player.sendRichMessage("<red>Index out of bounds. Valid range: 0 - " + Config.PRIZES.LIST.size() + "</red>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Config.PRIZES.setPrizeAt(index, item.clone());
|
||||||
|
player.sendRichMessage("<green>Set prize at index </green><yellow>" + index + "</yellow>");
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
player.sendRichMessage("<red>Invalid index. Usage: /easter setprize [index]</red>");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Config.PRIZES.addPrize(item.clone());
|
Config.PRIZES.addPrize(item.clone());
|
||||||
player.sendRichMessage(Messages.SETPRIZE.SUCCESS);
|
player.sendRichMessage(Messages.SETPRIZE.SUCCESS);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +50,14 @@ public class SetPrize extends SubCommand {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
|
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
|
||||||
|
if (args.length == 2) {
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
int maxIndex = Config.PRIZES.LIST.size();
|
||||||
|
for (int i = 0; i <= maxIndex; i++) {
|
||||||
|
res.add(String.valueOf(i));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package com.alttd.easter.commands.subcommands;
|
||||||
|
|
||||||
|
import com.alttd.easter.commands.SubCommand;
|
||||||
|
import com.alttd.easter.config.Messages;
|
||||||
|
import com.alttd.easter.egg.EggType;
|
||||||
|
import com.alttd.easter.util.ItemUtils;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SpawnEggs extends SubCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, String[] args) {
|
||||||
|
if (!(commandSender instanceof Player player)) {
|
||||||
|
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int amount = 1;
|
||||||
|
if (args.length >= 2) {
|
||||||
|
try {
|
||||||
|
amount = Math.max(1, Integer.parseInt(args[1]));
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
// keep default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: allow spawning a single type via argument
|
||||||
|
if (args.length >= 2) {
|
||||||
|
EggType specific = parseEggType(args[1]);
|
||||||
|
if (specific != null) {
|
||||||
|
giveEgg(player, specific, amount);
|
||||||
|
player.sendRichMessage("<green>Spawned </green><gold>" + amount + "</gold> <green>of </green><type> <green>egg(s).</green>",
|
||||||
|
Placeholder.component("type", ItemUtils.typeNameComponent(specific))
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args.length >= 3) {
|
||||||
|
EggType specific = parseEggType(args[2]);
|
||||||
|
if (specific != null) {
|
||||||
|
giveEgg(player, specific, amount);
|
||||||
|
player.sendRichMessage("<green>Spawned </green><gold>" + amount + "</gold> <green>of </green><type> <green>egg(s).</green>",
|
||||||
|
Placeholder.component("type", ItemUtils.typeNameComponent(specific))
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (EggType type : EggType.values()) {
|
||||||
|
giveEgg(player, type, amount);
|
||||||
|
}
|
||||||
|
player.sendRichMessage("<green>Spawned </green><gold>" + amount + "</gold> <green>of every easter egg in your inventory for debugging.</green>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giveEgg(Player player, EggType type, int amount) {
|
||||||
|
ItemStack item = ItemUtils.createEggItem(type);
|
||||||
|
item.setAmount(Math.max(1, Math.min(64, amount)));
|
||||||
|
var left = player.getInventory().addItem(item);
|
||||||
|
if (!left.isEmpty()) {
|
||||||
|
// drop leftovers at the player's location
|
||||||
|
left.values().forEach(stack -> player.getWorld().dropItemNaturally(player.getLocation(), stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EggType parseEggType(String arg) {
|
||||||
|
String key = arg.trim().toUpperCase().replace('-', '_').replace(' ', '_');
|
||||||
|
// try direct enum name
|
||||||
|
try {
|
||||||
|
return EggType.valueOf(key);
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
}
|
||||||
|
// try match by pretty color words contained
|
||||||
|
for (EggType type : EggType.values()) {
|
||||||
|
if (ItemUtils.prettify(type.name()).replace(" ", "").equalsIgnoreCase(arg.replace(" ", ""))) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "spawneggs";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getTabComplete(CommandSender commandSender, String[] args) {
|
||||||
|
List<String> res = new ArrayList<>();
|
||||||
|
if (args.length == 2) {
|
||||||
|
// amount suggestions
|
||||||
|
res.addAll(List.of("1", "4", "16", "64"));
|
||||||
|
// also allow type in 2nd arg for convenience
|
||||||
|
for (EggType type : EggType.values()) {
|
||||||
|
res.add(type.name().toLowerCase());
|
||||||
|
}
|
||||||
|
} else if (args.length == 3) {
|
||||||
|
for (EggType type : EggType.values()) {
|
||||||
|
res.add(type.name().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpMessage() {
|
||||||
|
return Messages.HELP.SPAWN_EGGS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,11 +31,19 @@ public class Config extends AbstractConfig {
|
|||||||
|
|
||||||
public static class EGGS {
|
public static class EGGS {
|
||||||
private static final String prefix = "eggs.";
|
private static final String prefix = "eggs.";
|
||||||
public static double SPAWN_CHANCE = 0.02; // ~2 per night per player
|
public static double EASY_CHANCE = 0.01;
|
||||||
|
public static double NORMAL_CHANCE = 0.05;
|
||||||
|
public static double HARD_CHANCE = 1;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static void load() {
|
private static void load() {
|
||||||
SPAWN_CHANCE = config.getDouble(prefix, "spawn-chance", SPAWN_CHANCE);
|
EASY_CHANCE = config.getDouble(prefix, "easy-chance", EASY_CHANCE);
|
||||||
|
NORMAL_CHANCE = config.getDouble(prefix, "normal-chance", NORMAL_CHANCE);
|
||||||
|
HARD_CHANCE = config.getDouble(prefix, "hard-chance", HARD_CHANCE);
|
||||||
|
// ensure paths exist in config file with their current values
|
||||||
|
config.yaml.addDefault(prefix + "easy-chance", EASY_CHANCE);
|
||||||
|
config.yaml.addDefault(prefix + "normal-chance", NORMAL_CHANCE);
|
||||||
|
config.yaml.addDefault(prefix + "hard-chance", HARD_CHANCE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +77,7 @@ public class Config extends AbstractConfig {
|
|||||||
public static class PRIZES {
|
public static class PRIZES {
|
||||||
private static final String prefix = "prizes.";
|
private static final String prefix = "prizes.";
|
||||||
public static List<ItemStack> LIST = new ArrayList<>();
|
public static List<ItemStack> LIST = new ArrayList<>();
|
||||||
|
private static int NEXT_INDEX = 0;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static void load() {
|
private static void load() {
|
||||||
@@ -83,18 +92,44 @@ public class Config extends AbstractConfig {
|
|||||||
}
|
}
|
||||||
// ensure path exists
|
// ensure path exists
|
||||||
config.yaml.addDefault(prefix + "list", LIST);
|
config.yaml.addDefault(prefix + "list", LIST);
|
||||||
|
// load next index and clamp to range
|
||||||
|
NEXT_INDEX = config.getInt(prefix, "next-index", 0);
|
||||||
|
if (LIST.isEmpty()) {
|
||||||
|
NEXT_INDEX = 0;
|
||||||
|
} else if (NEXT_INDEX < 0 || NEXT_INDEX >= LIST.size()) {
|
||||||
|
NEXT_INDEX = NEXT_INDEX % LIST.size();
|
||||||
|
if (NEXT_INDEX < 0) NEXT_INDEX += LIST.size();
|
||||||
|
}
|
||||||
|
config.yaml.addDefault(prefix + "next-index", NEXT_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addPrize(ItemStack item) {
|
public static void addPrize(ItemStack item) {
|
||||||
LIST.add(item);
|
LIST.add(item);
|
||||||
config.set(prefix, "list", LIST);
|
config.set(prefix, "list", LIST);
|
||||||
|
// keep NEXT_INDEX valid
|
||||||
|
if (NEXT_INDEX < 0 || NEXT_INDEX >= LIST.size()) {
|
||||||
|
NEXT_INDEX = 0;
|
||||||
|
}
|
||||||
|
config.set(prefix, "next-index", NEXT_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack getRandomPrize() {
|
public static void setPrizeAt(int index, ItemStack item) {
|
||||||
if (LIST.isEmpty()) {
|
if (index < 0 || index > LIST.size()) {
|
||||||
return null;
|
throw new IndexOutOfBoundsException("Index must be between 0 and " + LIST.size());
|
||||||
}
|
}
|
||||||
return LIST.get((int) (Math.random() * LIST.size())).clone();
|
if (index == LIST.size()) {
|
||||||
|
LIST.add(item);
|
||||||
|
} else {
|
||||||
|
LIST.set(index, item);
|
||||||
|
}
|
||||||
|
config.set(prefix, "list", LIST);
|
||||||
|
// adjust NEXT_INDEX if necessary
|
||||||
|
if (LIST.isEmpty()) {
|
||||||
|
NEXT_INDEX = 0;
|
||||||
|
} else if (NEXT_INDEX >= LIST.size()) {
|
||||||
|
NEXT_INDEX = NEXT_INDEX % LIST.size();
|
||||||
|
}
|
||||||
|
config.set(prefix, "next-index", NEXT_INDEX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public class Messages extends AbstractConfig {
|
|||||||
public static String HELP_MESSAGE = "<green>Show this menu: <gold>/pu help</gold></green>";
|
public static String HELP_MESSAGE = "<green>Show this menu: <gold>/pu help</gold></green>";
|
||||||
public static String RELOAD = "<green>Reload the configs for Easter: <gold>/pu reload</gold></green>";
|
public static String RELOAD = "<green>Reload the configs for Easter: <gold>/pu reload</gold></green>";
|
||||||
public static String SET_PRIZE = "<green>Add the item in your hand as a prize: <gold>/pu setprize</gold></green>";
|
public static String SET_PRIZE = "<green>Add the item in your hand as a prize: <gold>/pu setprize</gold></green>";
|
||||||
|
public static String SPAWN_EGGS = "<green>Give yourself debug eggs: <gold>/pu spawneggs [amount|type] [type]</gold></green>";
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static void load() {
|
private static void load() {
|
||||||
@@ -33,6 +34,7 @@ public class Messages extends AbstractConfig {
|
|||||||
HELP_MESSAGE = config.getString(prefix, "help", HELP_MESSAGE);
|
HELP_MESSAGE = config.getString(prefix, "help", HELP_MESSAGE);
|
||||||
RELOAD = config.getString(prefix, "reload", RELOAD);
|
RELOAD = config.getString(prefix, "reload", RELOAD);
|
||||||
SET_PRIZE = config.getString(prefix, "set-prize", SET_PRIZE);
|
SET_PRIZE = config.getString(prefix, "set-prize", SET_PRIZE);
|
||||||
|
SPAWN_EGGS = config.getString(prefix, "spawn-eggs", SPAWN_EGGS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,21 +68,23 @@ public class Messages extends AbstractConfig {
|
|||||||
private static final String prefix = "rabbit.";
|
private static final String prefix = "rabbit.";
|
||||||
public static String LEFT_CLICK_INTRO = "<green>Hi <player>. A bunch of different mobs have stolen my easter eggs! Can you find them and kill them for me? If you bring the eggs back I will reward you!</green>";
|
public static String LEFT_CLICK_INTRO = "<green>Hi <player>. A bunch of different mobs have stolen my easter eggs! Can you find them and kill them for me? If you bring the eggs back I will reward you!</green>";
|
||||||
public static String NO_EGGS = "<yellow>Please come back when you've found some eggs!</yellow>";
|
public static String NO_EGGS = "<yellow>Please come back when you've found some eggs!</yellow>";
|
||||||
public static String THANK_YOU = "<green>Thank you for finding my eggs <player>! Keep looking for more!</green>";
|
public static String ONE_EGG = "<green>Thank you for finding my eggs <player>! I have received the <egg1> egg from you. Please keep looking for more!</green>";
|
||||||
public static String ONE_EGG = "<green>Thank you for finding my eggs <player>! I have received the <egg1> from you. Please keep looking for more!</green>";
|
public static String MULTI_EGGS = "<green>Thank you for finding my eggs <player>! I have received <eggs> eggs from you. Please keep looking for more!</green>";
|
||||||
public static String MULTI_EGGS = "<green>Thank you for finding my eggs <player>! I have received the <egg1>, <egg2>, and <egg3> from you. Please keep looking for more!</green>";
|
|
||||||
public static String REWARD = "<green>Thank you! You've turned in 4 unique eggs and earned a prize!</green>";
|
public static String REWARD = "<green>Thank you! You've turned in 4 unique eggs and earned a prize!</green>";
|
||||||
public static String DUPLICATE_EGGS = "<yellow>Those are duplicates I already have. Bring me new colors!</yellow>";
|
|
||||||
public static String GUI_TITLE = "<gold>Turn in Eggs</gold>";
|
public static String GUI_TITLE = "<gold>Turn in Eggs</gold>";
|
||||||
|
public static String TURNED_IN_NONE = "<yellow>You haven't turned in any eggs yet.</yellow>";
|
||||||
|
public static String TURNED_IN_LIST = "<green>You have turned in: <eggs></green>";
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static void load() {
|
private static void load() {
|
||||||
LEFT_CLICK_INTRO = config.getString(prefix, "left-click-intro", LEFT_CLICK_INTRO);
|
LEFT_CLICK_INTRO = config.getString(prefix, "left-click-intro", LEFT_CLICK_INTRO);
|
||||||
NO_EGGS = config.getString(prefix, "no-eggs", NO_EGGS);
|
NO_EGGS = config.getString(prefix, "no-eggs", NO_EGGS);
|
||||||
THANK_YOU = config.getString(prefix, "thank-you", THANK_YOU);
|
|
||||||
REWARD = config.getString(prefix, "reward", REWARD);
|
REWARD = config.getString(prefix, "reward", REWARD);
|
||||||
DUPLICATE_EGGS = config.getString(prefix, "duplicate-eggs", DUPLICATE_EGGS);
|
|
||||||
GUI_TITLE = config.getString(prefix, "gui-title", GUI_TITLE);
|
GUI_TITLE = config.getString(prefix, "gui-title", GUI_TITLE);
|
||||||
|
TURNED_IN_NONE = config.getString(prefix, "turned-in-none", TURNED_IN_NONE);
|
||||||
|
TURNED_IN_LIST = config.getString(prefix, "turned-in-list", TURNED_IN_LIST);
|
||||||
|
ONE_EGG = config.getString(prefix, "one-egg", ONE_EGG);
|
||||||
|
MULTI_EGGS = config.getString(prefix, "multi-eggs", MULTI_EGGS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,30 @@
|
|||||||
package com.alttd.easter.egg;
|
package com.alttd.easter.egg;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
|
||||||
public enum EggType {
|
public enum EggType {
|
||||||
BROWN_HUSK(Material.BROWN_GLAZED_TERRACOTTA, EntityType.HUSK, Enchantment.FIRE_PROTECTION, 2),
|
BROWN_HUSK(Material.BROWN_GLAZED_TERRACOTTA, EntityType.HUSK, Enchantment.FIRE_PROTECTION, 2, Difficulty.NORMAL, TextColor.color(0x8F4F2A)),
|
||||||
RED_SPIDER(Material.RED_GLAZED_TERRACOTTA, EntityType.SPIDER, Enchantment.BANE_OF_ARTHROPODS, 2),
|
RED_SPIDER(Material.RED_GLAZED_TERRACOTTA, EntityType.SPIDER, Enchantment.BANE_OF_ARTHROPODS, 2, Difficulty.NORMAL, TextColor.color(0xB02E26)),
|
||||||
ORANGE_BLAZE(Material.ORANGE_GLAZED_TERRACOTTA, EntityType.BLAZE, Enchantment.FIRE_ASPECT, 2),
|
ORANGE_BLAZE(Material.ORANGE_GLAZED_TERRACOTTA, EntityType.BLAZE, Enchantment.FIRE_ASPECT, 2, Difficulty.NORMAL, TextColor.color(0xF9801D)),
|
||||||
YELLOW_PIGLIN(Material.YELLOW_GLAZED_TERRACOTTA, EntityType.PIGLIN, Enchantment.FORTUNE, 2),
|
YELLOW_PIGLIN(Material.YELLOW_GLAZED_TERRACOTTA, EntityType.PIGLIN, Enchantment.FORTUNE, 2, Difficulty.NORMAL, TextColor.color(0xFED83D)),
|
||||||
LIME_CREEPER(Material.LIME_GLAZED_TERRACOTTA, EntityType.CREEPER, Enchantment.BLAST_PROTECTION, 2),
|
LIME_CREEPER(Material.LIME_GLAZED_TERRACOTTA, EntityType.CREEPER, Enchantment.BLAST_PROTECTION, 2, Difficulty.NORMAL, TextColor.color(0x80C71F)),
|
||||||
GREEN_ZOMBIE(Material.GREEN_GLAZED_TERRACOTTA, EntityType.ZOMBIE, Enchantment.FEATHER_FALLING, 2),
|
GREEN_ZOMBIE(Material.GREEN_GLAZED_TERRACOTTA, EntityType.ZOMBIE, Enchantment.FEATHER_FALLING, 2, Difficulty.NORMAL, TextColor.color(0x5E7C16)),
|
||||||
LIGHT_BLUE_STRAY(Material.LIGHT_BLUE_GLAZED_TERRACOTTA, EntityType.STRAY, Enchantment.FROST_WALKER, 2),
|
LIGHT_BLUE_STRAY(Material.LIGHT_BLUE_GLAZED_TERRACOTTA, EntityType.STRAY, Enchantment.FROST_WALKER, 2, Difficulty.NORMAL, TextColor.color(0x3AB3DA)),
|
||||||
CYAN_GUARDIAN(Material.CYAN_GLAZED_TERRACOTTA, EntityType.GUARDIAN, Enchantment.THORNS, 2),
|
CYAN_GUARDIAN(Material.CYAN_GLAZED_TERRACOTTA, EntityType.GUARDIAN, Enchantment.THORNS, 2, Difficulty.EASY, TextColor.color(0x169C9C)),
|
||||||
BLUE_WARDEN(Material.BLUE_GLAZED_TERRACOTTA, EntityType.WARDEN, Enchantment.SWIFT_SNEAK, 2),
|
BLUE_WARDEN(Material.BLUE_GLAZED_TERRACOTTA, EntityType.WARDEN, Enchantment.SWIFT_SNEAK, 2, Difficulty.HARD, TextColor.color(0x3C44AA)),
|
||||||
PURPLE_ENDER_DRAGON(Material.PURPLE_GLAZED_TERRACOTTA, EntityType.ENDER_DRAGON, Enchantment.POWER, 2),
|
PURPLE_ENDER_DRAGON(Material.PURPLE_GLAZED_TERRACOTTA, EntityType.ENDER_DRAGON, Enchantment.POWER, 2, Difficulty.HARD, TextColor.color(0x8932B8)),
|
||||||
MAGENTA_ENDERMAN(Material.MAGENTA_GLAZED_TERRACOTTA, EntityType.ENDERMAN, Enchantment.INFINITY, 2),
|
MAGENTA_ENDERMAN(Material.MAGENTA_GLAZED_TERRACOTTA, EntityType.ENDERMAN, Enchantment.INFINITY, 2, Difficulty.EASY, TextColor.color(0xC74EBD)),
|
||||||
PINK_HOGLIN(Material.PINK_GLAZED_TERRACOTTA, EntityType.HOGLIN, Enchantment.PIERCING, 2),
|
PINK_HOGLIN(Material.PINK_GLAZED_TERRACOTTA, EntityType.HOGLIN, Enchantment.PIERCING, 2, Difficulty.NORMAL, TextColor.color(0xF38BAA)),
|
||||||
WHITE_SKELETON(Material.WHITE_GLAZED_TERRACOTTA, EntityType.SKELETON, Enchantment.MULTISHOT, 2),
|
WHITE_SKELETON(Material.WHITE_GLAZED_TERRACOTTA, EntityType.SKELETON, Enchantment.MULTISHOT, 2, Difficulty.NORMAL, TextColor.color(0xFFFFFF)),
|
||||||
LIGHT_GRAY_SILVERFISH(Material.LIGHT_GRAY_GLAZED_TERRACOTTA, EntityType.SILVERFISH, Enchantment.EFFICIENCY, 2),
|
LIGHT_GRAY_SILVERFISH(Material.LIGHT_GRAY_GLAZED_TERRACOTTA, EntityType.SILVERFISH, Enchantment.EFFICIENCY, 2, Difficulty.EASY, TextColor.color(0x9D9D97)),
|
||||||
GRAY_WITHER(Material.GRAY_GLAZED_TERRACOTTA, EntityType.WITHER, Enchantment.SMITE, 2),
|
GRAY_WITHER(Material.GRAY_GLAZED_TERRACOTTA, EntityType.WITHER, Enchantment.SMITE, 2, Difficulty.HARD, TextColor.color(0x474F52)),
|
||||||
BLACK_WITHER_SKELETON(Material.BLACK_GLAZED_TERRACOTTA, EntityType.WITHER_SKELETON, Enchantment.LOOTING, 2);
|
BLACK_WITHER_SKELETON(Material.BLACK_GLAZED_TERRACOTTA, EntityType.WITHER_SKELETON, Enchantment.LOOTING, 2, Difficulty.NORMAL, TextColor.color(0x1D1D21));
|
||||||
|
|
||||||
|
public enum Difficulty {EASY, NORMAL, HARD}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Material material;
|
private final Material material;
|
||||||
@@ -30,12 +33,18 @@ public enum EggType {
|
|||||||
private final Enchantment enchantment;
|
private final Enchantment enchantment;
|
||||||
@Getter
|
@Getter
|
||||||
private final int enchantLevel;
|
private final int enchantLevel;
|
||||||
|
@Getter
|
||||||
|
private final Difficulty difficulty;
|
||||||
|
@Getter
|
||||||
|
private final TextColor color;
|
||||||
|
|
||||||
EggType(Material material, EntityType entityType, Enchantment enchantment, int enchantLevel) {
|
EggType(Material material, EntityType entityType, Enchantment enchantment, int enchantLevel, Difficulty difficulty, TextColor color) {
|
||||||
this.material = material;
|
this.material = material;
|
||||||
this.entityType = entityType;
|
this.entityType = entityType;
|
||||||
this.enchantment = enchantment;
|
this.enchantment = enchantment;
|
||||||
this.enchantLevel = enchantLevel;
|
this.enchantLevel = enchantLevel;
|
||||||
|
this.difficulty = difficulty;
|
||||||
|
this.color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EggType fromEntityType(EntityType entityType) {
|
public static EggType fromEntityType(EntityType entityType) {
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
package com.alttd.easter.glow;
|
|
||||||
|
|
||||||
import com.alttd.easter.egg.EggType;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.scoreboard.Scoreboard;
|
|
||||||
import org.bukkit.scoreboard.Team;
|
|
||||||
|
|
||||||
public class GlowManager {
|
|
||||||
|
|
||||||
private final Scoreboard scoreboard;
|
|
||||||
|
|
||||||
public GlowManager(org.bukkit.plugin.Plugin plugin) {
|
|
||||||
this.scoreboard = Bukkit.getScoreboardManager().getMainScoreboard();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyGlow(Entity entity, EggType type) {
|
|
||||||
String teamName = ("easter_" + type.name()).toLowerCase();
|
|
||||||
Team team = scoreboard.getTeam(teamName);
|
|
||||||
if (team == null) {
|
|
||||||
team = scoreboard.registerNewTeam(teamName);
|
|
||||||
team.setCanSeeFriendlyInvisibles(false);
|
|
||||||
team.setAllowFriendlyFire(true);
|
|
||||||
team.color(colorFor(type));
|
|
||||||
}
|
|
||||||
String entry = entity.getUniqueId().toString();
|
|
||||||
if (!team.hasEntry(entry)) {
|
|
||||||
team.addEntry(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private NamedTextColor colorFor(EggType type) {
|
|
||||||
return switch (type) {
|
|
||||||
case BROWN_HUSK -> NamedTextColor.DARK_RED; // closest
|
|
||||||
case RED_SPIDER -> NamedTextColor.RED;
|
|
||||||
case ORANGE_BLAZE -> NamedTextColor.GOLD;
|
|
||||||
case YELLOW_PIGLIN -> NamedTextColor.YELLOW;
|
|
||||||
case LIME_CREEPER -> NamedTextColor.GREEN;
|
|
||||||
case GREEN_ZOMBIE -> NamedTextColor.DARK_GREEN;
|
|
||||||
case LIGHT_BLUE_STRAY -> NamedTextColor.AQUA;
|
|
||||||
case CYAN_GUARDIAN -> NamedTextColor.DARK_AQUA;
|
|
||||||
case BLUE_WARDEN -> NamedTextColor.BLUE;
|
|
||||||
case PURPLE_ENDER_DRAGON -> NamedTextColor.DARK_PURPLE;
|
|
||||||
case MAGENTA_ENDERMAN -> NamedTextColor.LIGHT_PURPLE;
|
|
||||||
case PINK_HOGLIN -> NamedTextColor.LIGHT_PURPLE;
|
|
||||||
case WHITE_SKELETON -> NamedTextColor.WHITE;
|
|
||||||
case LIGHT_GRAY_SILVERFISH -> NamedTextColor.GRAY;
|
|
||||||
case GRAY_WITHER -> NamedTextColor.DARK_GRAY;
|
|
||||||
case BLACK_WITHER_SKELETON -> NamedTextColor.BLACK;
|
|
||||||
default -> NamedTextColor.WHITE;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
package com.alttd.easter.gui;
|
package com.alttd.easter.gui;
|
||||||
|
|
||||||
|
import com.alttd.easter.config.Config;
|
||||||
import com.alttd.easter.config.Messages;
|
import com.alttd.easter.config.Messages;
|
||||||
import com.alttd.easter.data.DataManager;
|
import com.alttd.easter.data.DataManager;
|
||||||
import com.alttd.easter.egg.EggType;
|
import com.alttd.easter.egg.EggType;
|
||||||
import com.alttd.easter.util.ItemUtils;
|
import com.alttd.easter.util.ItemUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.JoinConfiguration;
|
||||||
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -16,6 +21,7 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class TurnInGuiManager implements Listener {
|
public class TurnInGuiManager implements Listener {
|
||||||
|
|
||||||
private final DataManager dataManager;
|
private final DataManager dataManager;
|
||||||
@@ -25,14 +31,8 @@ public class TurnInGuiManager implements Listener {
|
|||||||
this.dataManager = dataManager;
|
this.dataManager = dataManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String title() {
|
private Component title() {
|
||||||
// crude strip of minimessage tags for inventory title
|
return MiniMessage.miniMessage().deserialize(Messages.RABBIT.GUI_TITLE);
|
||||||
String mm = Messages.RABBIT.GUI_TITLE;
|
|
||||||
String plain = mm.replaceAll("<[^>]+>", "");
|
|
||||||
if (plain.isBlank()) {
|
|
||||||
plain = "Turn in Eggs";
|
|
||||||
}
|
|
||||||
return plain;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open(Player player) {
|
public void open(Player player) {
|
||||||
@@ -76,14 +76,17 @@ public class TurnInGuiManager implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onClose(InventoryCloseEvent event) {
|
public void onClose(InventoryCloseEvent event) {
|
||||||
Player player = (Player) event.getPlayer();
|
Player player = (Player) event.getPlayer();
|
||||||
Inventory top = openInventories.remove(player.getUniqueId());
|
Inventory top = openInventories.get(player.getUniqueId());
|
||||||
if (top == null) {
|
if (top == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!event.getInventory().equals(top)) {
|
if (!event.getView().getTopInventory().equals(top)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// collect egg items and clear them from the GUI so they don't drop
|
|
||||||
|
openInventories.remove(player.getUniqueId());
|
||||||
|
|
||||||
|
// collect egg items for submission and then clear GUI so eggs don't drop
|
||||||
Set<EggType> submitted = new HashSet<>();
|
Set<EggType> submitted = new HashSet<>();
|
||||||
for (ItemStack item : top.getContents()) {
|
for (ItemStack item : top.getContents()) {
|
||||||
if (ItemUtils.isEggItem(item)) {
|
if (ItemUtils.isEggItem(item)) {
|
||||||
@@ -98,30 +101,58 @@ public class TurnInGuiManager implements Listener {
|
|||||||
player.sendRichMessage(Messages.RABBIT.NO_EGGS);
|
player.sendRichMessage(Messages.RABBIT.NO_EGGS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dataManager.addEggs(player.getUniqueId(), submitted);
|
// determine how many new unique egg types were added so we can award correct number of prizes
|
||||||
|
int prevTotal = dataManager.getPlayerEggs(player.getUniqueId()).size();
|
||||||
|
int newlyAdded = dataManager.addEggs(player.getUniqueId(), submitted);
|
||||||
dataManager.save();
|
dataManager.save();
|
||||||
// Dialog formatting for submission summary
|
// Dialog formatting for submission summary
|
||||||
List<String> colors = submitted.stream().map(ItemUtils::colorName).toList();
|
List<Component> eggComponents = new ArrayList<>();
|
||||||
if (colors.size() == 1) {
|
for (EggType type : submitted) {
|
||||||
|
eggComponents.add(ItemUtils.colorNameComponent(type));
|
||||||
|
}
|
||||||
|
if (eggComponents.size() == 1) {
|
||||||
player.sendRichMessage(Messages.RABBIT.ONE_EGG,
|
player.sendRichMessage(Messages.RABBIT.ONE_EGG,
|
||||||
Placeholder.parsed("player", player.getName()),
|
Placeholder.parsed("player", player.getName()),
|
||||||
Placeholder.parsed("egg1", colors.getFirst())
|
Placeholder.component("egg1", eggComponents.getFirst())
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
String c1 = !colors.isEmpty() ? colors.get(0) : "";
|
Component eggsJoined;
|
||||||
String c2 = colors.size() > 1 ? colors.get(1) : "";
|
if (eggComponents.size() == 2) {
|
||||||
String c3 = colors.size() > 2 ? colors.get(2) : "";
|
eggsJoined = Component.join(
|
||||||
player.sendRichMessage(Messages.RABBIT.MULTI_EGGS,
|
JoinConfiguration.builder()
|
||||||
Placeholder.parsed("player", player.getName()),
|
.lastSeparator(Component.text(" and "))
|
||||||
Placeholder.parsed("egg1", c1),
|
.build(),
|
||||||
Placeholder.parsed("egg2", c2),
|
eggComponents
|
||||||
Placeholder.parsed("egg3", c3)
|
);
|
||||||
|
} else {
|
||||||
|
eggsJoined = Component.join(
|
||||||
|
JoinConfiguration.builder()
|
||||||
|
.separator(Component.text(", "))
|
||||||
|
.lastSeparator(Component.text(", and "))
|
||||||
|
.build(),
|
||||||
|
eggComponents
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
int total = dataManager.getPlayerEggs(player.getUniqueId()).size();
|
player.sendRichMessage(Messages.RABBIT.MULTI_EGGS,
|
||||||
if (total % 4 == 0) {
|
Placeholder.parsed("player", player.getName()),
|
||||||
var prize = com.alttd.easter.config.Config.PRIZES.getRandomPrize();
|
Placeholder.component("eggs", eggsJoined)
|
||||||
if (prize != null) {
|
);
|
||||||
|
}
|
||||||
|
int newTotal = prevTotal + newlyAdded;
|
||||||
|
int prevMilestones = prevTotal / 4;
|
||||||
|
int newMilestones = newTotal / 4;
|
||||||
|
int prizesToGive = Math.max(0, newMilestones - prevMilestones);
|
||||||
|
List<ItemStack> prizeList = Config.PRIZES.LIST;
|
||||||
|
for (int i = 0; i < prizesToGive; i++) {
|
||||||
|
int intendedIndex = prevMilestones + i;
|
||||||
|
if (prizeList.isEmpty()) {
|
||||||
|
log.warn("No prizes configured. Tried to give prize for intended index {}. Staff should configure prizes using /easter setprize.", intendedIndex);
|
||||||
|
} else {
|
||||||
|
int wrappedIndex = intendedIndex % prizeList.size();
|
||||||
|
if (intendedIndex >= prizeList.size() || intendedIndex < 0) {
|
||||||
|
log.warn("Prize index overflow: intended index {} -> wrapped to {} (prize list size {}).", intendedIndex, wrappedIndex, prizeList.size());
|
||||||
|
}
|
||||||
|
ItemStack prize = prizeList.get(wrappedIndex).clone();
|
||||||
player.getInventory().addItem(prize);
|
player.getInventory().addItem(prize);
|
||||||
}
|
}
|
||||||
player.sendRichMessage(Messages.RABBIT.REWARD);
|
player.sendRichMessage(Messages.RABBIT.REWARD);
|
||||||
|
|||||||
@@ -1,30 +1,41 @@
|
|||||||
package com.alttd.easter.listeners;
|
package com.alttd.easter.listeners;
|
||||||
|
|
||||||
|
import com.alttd.easter.config.Config;
|
||||||
import com.alttd.easter.egg.EggType;
|
import com.alttd.easter.egg.EggType;
|
||||||
import com.alttd.easter.util.ItemUtils;
|
import com.alttd.easter.util.ItemUtils;
|
||||||
import com.alttd.easter.util.Keys;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Mob;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityDeathEvent;
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public class DeathListener implements Listener {
|
public class DeathListener implements Listener {
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onDeath(EntityDeathEvent event) {
|
public void onDeath(EntityDeathEvent event) {
|
||||||
LivingEntity entity = event.getEntity();
|
LivingEntity entity = event.getEntity();
|
||||||
String eggName = entity.getPersistentDataContainer().get(Keys.EGG_ENTITY, PersistentDataType.STRING);
|
// Only consider AI-capable mobs
|
||||||
if (eggName == null) {
|
if (!(entity instanceof Mob mob) || !mob.isAware()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EggType type;
|
EggType eggType = EggType.fromEntityType(entity.getType());
|
||||||
try {
|
if (eggType == null) {
|
||||||
type = EggType.valueOf(eggName);
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Ensure the egg drops
|
double chance;
|
||||||
event.getDrops().add(ItemUtils.createEggItem(type));
|
switch (eggType.getDifficulty()) {
|
||||||
|
case EASY -> chance = Config.EGGS.EASY_CHANCE;
|
||||||
|
case NORMAL -> chance = Config.EGGS.NORMAL_CHANCE;
|
||||||
|
case HARD -> chance = Config.EGGS.HARD_CHANCE;
|
||||||
|
default -> chance = 0.0;
|
||||||
|
}
|
||||||
|
if (chance <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ThreadLocalRandom.current().nextDouble() < chance) {
|
||||||
|
event.getDrops().add(ItemUtils.createEggItem(eggType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
package com.alttd.easter.listeners;
|
|
||||||
|
|
||||||
import com.alttd.easter.config.Config;
|
|
||||||
import com.alttd.easter.egg.EggType;
|
|
||||||
import com.alttd.easter.glow.GlowManager;
|
|
||||||
import com.alttd.easter.util.ItemUtils;
|
|
||||||
import com.alttd.easter.util.Keys;
|
|
||||||
import org.bukkit.entity.Creature;
|
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.inventory.EntityEquipment;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
|
|
||||||
@SuppressWarnings("ClassCanBeRecord")
|
|
||||||
public class SpawnListener implements Listener {
|
|
||||||
|
|
||||||
private final GlowManager glowManager;
|
|
||||||
|
|
||||||
public SpawnListener(GlowManager glowManager) {
|
|
||||||
this.glowManager = glowManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onNaturalSpawn(CreatureSpawnEvent event) {
|
|
||||||
if (event.getSpawnReason() != CreatureSpawnEvent.SpawnReason.NATURAL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(event.getEntity() instanceof Creature creature)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
EntityType type = event.getEntityType();
|
|
||||||
EggType eggType = EggType.fromEntityType(type);
|
|
||||||
if (eggType == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double chance = Config.EGGS.SPAWN_CHANCE;
|
|
||||||
if (ThreadLocalRandom.current().nextDouble() >= chance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack eggItem = ItemUtils.createEggItem(eggType);
|
|
||||||
EntityEquipment equipment = creature.getEquipment();
|
|
||||||
equipment.setHelmet(eggItem);
|
|
||||||
equipment.setHelmetDropChance(1.0f);
|
|
||||||
// tag entity so we know it's an egg carrier
|
|
||||||
creature.getPersistentDataContainer().set(Keys.EGG_ENTITY, PersistentDataType.STRING, eggType.name());
|
|
||||||
creature.setGlowing(true);
|
|
||||||
glowManager.applyGlow(creature, eggType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,15 +2,16 @@ package com.alttd.easter.npc;
|
|||||||
|
|
||||||
import com.alttd.easter.config.Config;
|
import com.alttd.easter.config.Config;
|
||||||
import com.alttd.easter.config.Messages;
|
import com.alttd.easter.config.Messages;
|
||||||
|
import com.alttd.easter.data.DataManager;
|
||||||
|
import com.alttd.easter.egg.EggType;
|
||||||
import com.alttd.easter.gui.TurnInGuiManager;
|
import com.alttd.easter.gui.TurnInGuiManager;
|
||||||
|
import com.alttd.easter.util.ItemUtils;
|
||||||
import com.alttd.easter.util.Keys;
|
import com.alttd.easter.util.Keys;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.entity.EntityType;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.entity.Rabbit;
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
@@ -18,15 +19,21 @@ import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
|||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@SuppressWarnings("ClassCanBeRecord")
|
@SuppressWarnings("ClassCanBeRecord")
|
||||||
public class RabbitNpcManager implements Listener {
|
public class RabbitNpcManager implements Listener {
|
||||||
|
|
||||||
private final org.bukkit.plugin.Plugin plugin;
|
private final org.bukkit.plugin.Plugin plugin;
|
||||||
private final com.alttd.easter.gui.TurnInGuiManager turnInGuiManager;
|
private final com.alttd.easter.gui.TurnInGuiManager turnInGuiManager;
|
||||||
|
private final DataManager dataManager;
|
||||||
|
|
||||||
public RabbitNpcManager(Plugin plugin, TurnInGuiManager turnInGuiManager) {
|
public RabbitNpcManager(Plugin plugin, TurnInGuiManager turnInGuiManager, DataManager dataManager) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.turnInGuiManager = turnInGuiManager;
|
this.turnInGuiManager = turnInGuiManager;
|
||||||
|
this.dataManager = dataManager;
|
||||||
spawnOrFindRabbit();
|
spawnOrFindRabbit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,8 +44,8 @@ public class RabbitNpcManager implements Listener {
|
|||||||
private void spawnOrFindRabbit() {
|
private void spawnOrFindRabbit() {
|
||||||
// Find existing rabbit with tag, else spawn new at config location
|
// Find existing rabbit with tag, else spawn new at config location
|
||||||
for (World world : Bukkit.getWorlds()) {
|
for (World world : Bukkit.getWorlds()) {
|
||||||
for (Entity e : world.getEntitiesByClass(Rabbit.class)) {
|
for (Entity entity : world.getEntitiesByClass(Rabbit.class)) {
|
||||||
if (e.getPersistentDataContainer().has(Keys.RABBIT_NPC, PersistentDataType.BYTE)) {
|
if (entity.getPersistentDataContainer().has(Keys.RABBIT_NPC, PersistentDataType.BYTE)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,13 +56,20 @@ public class RabbitNpcManager implements Listener {
|
|||||||
}
|
}
|
||||||
Rabbit rabbit = (Rabbit) loc.getWorld().spawnEntity(loc, EntityType.RABBIT);
|
Rabbit rabbit = (Rabbit) loc.getWorld().spawnEntity(loc, EntityType.RABBIT);
|
||||||
rabbit.setCustomNameVisible(true);
|
rabbit.setCustomNameVisible(true);
|
||||||
rabbit.customName(net.kyori.adventure.text.Component.text("Easter Bunny"));
|
rabbit.setInvulnerable(true);
|
||||||
|
rabbit.setSilent(true);
|
||||||
|
rabbit.setGlowing(true);
|
||||||
|
rabbit.setGravity(false);
|
||||||
|
rabbit.setAI(false);
|
||||||
|
rabbit.customName(Component.text("Easter Bunny"));
|
||||||
rabbit.getPersistentDataContainer().set(Keys.RABBIT_NPC, PersistentDataType.BYTE, (byte) 1);
|
rabbit.getPersistentDataContainer().set(Keys.RABBIT_NPC, PersistentDataType.BYTE, (byte) 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onInteract(PlayerInteractAtEntityEvent event) {
|
public void onInteract(PlayerInteractAtEntityEvent event) {
|
||||||
if (!(event.getRightClicked() instanceof Rabbit) && !(event.getRightClicked() instanceof org.bukkit.entity.LivingEntity le && le.getPersistentDataContainer().has(Keys.RABBIT_NPC, PersistentDataType.BYTE))) {
|
if (!(event.getRightClicked() instanceof Rabbit)
|
||||||
|
&& !(event.getRightClicked() instanceof LivingEntity livingEntity
|
||||||
|
&& livingEntity.getPersistentDataContainer().has(Keys.RABBIT_NPC, PersistentDataType.BYTE))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
@@ -79,10 +93,25 @@ public class RabbitNpcManager implements Listener {
|
|||||||
player.sendRichMessage(Messages.RABBIT.LEFT_CLICK_INTRO,
|
player.sendRichMessage(Messages.RABBIT.LEFT_CLICK_INTRO,
|
||||||
Placeholder.parsed("player", player.getName())
|
Placeholder.parsed("player", player.getName())
|
||||||
);
|
);
|
||||||
|
var eggs = dataManager.getPlayerEggs(player.getUniqueId());
|
||||||
|
if (eggs.isEmpty()) {
|
||||||
|
player.sendRichMessage(Messages.RABBIT.TURNED_IN_NONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<EggType> sorted = eggs.stream()
|
||||||
|
.sorted(Comparator.comparingInt(Enum::ordinal))
|
||||||
|
.toList();
|
||||||
|
var components = sorted.stream()
|
||||||
|
.map(ItemUtils::colorNameComponent)
|
||||||
|
.toList();
|
||||||
|
var joined = net.kyori.adventure.text.Component.join(net.kyori.adventure.text.JoinConfiguration.builder()
|
||||||
|
.separator(net.kyori.adventure.text.Component.text(", "))
|
||||||
|
.build(), components);
|
||||||
|
player.sendRichMessage(Messages.RABBIT.TURNED_IN_LIST,
|
||||||
|
Placeholder.component("eggs", joined));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openTurnIn(Player player) {
|
private void openTurnIn(Player player) {
|
||||||
// Delegate to TurnInGuiManager which controls the inventory and submission flow
|
|
||||||
turnInGuiManager.open(player);
|
turnInGuiManager.open(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.alttd.easter.util;
|
|||||||
import com.alttd.easter.egg.EggType;
|
import com.alttd.easter.egg.EggType;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
|
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||||
import org.bukkit.inventory.ItemFlag;
|
import org.bukkit.inventory.ItemFlag;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
@@ -13,7 +16,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public final class ItemUtils {
|
public final class ItemUtils {
|
||||||
|
|
||||||
public static String colorName(EggType type) {
|
private static String colorName(EggType type) {
|
||||||
return switch (type) {
|
return switch (type) {
|
||||||
case BROWN_HUSK -> "Brown";
|
case BROWN_HUSK -> "Brown";
|
||||||
case RED_SPIDER -> "Red";
|
case RED_SPIDER -> "Red";
|
||||||
@@ -28,18 +31,29 @@ public final class ItemUtils {
|
|||||||
case MAGENTA_ENDERMAN -> "Magenta";
|
case MAGENTA_ENDERMAN -> "Magenta";
|
||||||
case PINK_HOGLIN -> "Pink";
|
case PINK_HOGLIN -> "Pink";
|
||||||
case WHITE_SKELETON -> "White";
|
case WHITE_SKELETON -> "White";
|
||||||
case LIGHT_GRAY_SILVERFISH -> "Light Grey";
|
case LIGHT_GRAY_SILVERFISH -> "Light Gray";
|
||||||
case GRAY_WITHER -> "Grey";
|
case GRAY_WITHER -> "Gray";
|
||||||
case BLACK_WITHER_SKELETON -> "Black";
|
case BLACK_WITHER_SKELETON -> "Black";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Component colorNameComponent(EggType type) {
|
||||||
|
return Component.text(colorName(type), type.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Component typeNameComponent(EggType type) {
|
||||||
|
return Component.text(prettify(type.name()), type.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
public static ItemStack createEggItem(EggType type) {
|
public static ItemStack createEggItem(EggType type) {
|
||||||
ItemStack item = new ItemStack(type.getMaterial());
|
ItemStack item = new ItemStack(type.getMaterial());
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
meta.addEnchant(type.getEnchantment(), type.getEnchantLevel(), true);
|
meta.addEnchant(type.getEnchantment(), type.getEnchantLevel(), true);
|
||||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||||
meta.displayName(Component.text("Easter Egg - " + prettify(type.name()), NamedTextColor.GOLD));
|
Component name = MiniMessage.miniMessage().deserialize("<gold>Easter Egg - </gold><type>",
|
||||||
|
Placeholder.component("type", typeNameComponent(type))
|
||||||
|
);
|
||||||
|
meta.displayName(name);
|
||||||
meta.getPersistentDataContainer().set(Keys.EGG_ITEM, PersistentDataType.STRING, type.name());
|
meta.getPersistentDataContainer().set(Keys.EGG_ITEM, PersistentDataType.STRING, type.name());
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
return item;
|
return item;
|
||||||
|
|||||||
@@ -17,3 +17,9 @@ permissions:
|
|||||||
easter.setprize:
|
easter.setprize:
|
||||||
description: Set the held item as a prize
|
description: Set the held item as a prize
|
||||||
default: op
|
default: op
|
||||||
|
easter.getprizes:
|
||||||
|
description: List configured prizes with their index
|
||||||
|
default: op
|
||||||
|
easter.spawneggs:
|
||||||
|
description: Give yourself debug eggs
|
||||||
|
default: op
|
||||||
|
|||||||
Reference in New Issue
Block a user