adds a difficulty parameter
All checks were successful
Build / build (push) Successful in 3m10s

This commit is contained in:
unurled 2024-05-30 22:52:01 +02:00
parent 22fa239f38
commit 92fd2242b3
Signed by: unurled
GPG key ID: FDBC9CBE1F82423F
12 changed files with 436 additions and 12 deletions

View file

@ -14,7 +14,7 @@ version = "0.1.0"
description = "The main SR plugin."
val mcVersion = "1.20.6-R0.1-SNAPSHOT"
val redisVersion = "5.2.0-beta1"
val redisVersion = "5.2.0-beta2"
val invuiVersion = "1.30"
val javaVersion = 21

View file

@ -11,6 +11,7 @@ import me.unurled.sacredrealms.sr.commands.admin.ItemCommand;
import me.unurled.sacredrealms.sr.commands.admin.LevelCommand;
import me.unurled.sacredrealms.sr.commands.admin.SpawnEntityCommand;
import me.unurled.sacredrealms.sr.commands.admin.TreasureCommand;
import me.unurled.sacredrealms.sr.commands.player.DifficultyCommand;
import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand;
import me.unurled.sacredrealms.sr.managers.Manager;
import org.bukkit.command.PluginCommand;
@ -49,5 +50,6 @@ public class CommandManager extends Manager {
registerCommand("treasure", TreasureCommand.class);
registerCommand("resetadventure", ResetAdventureCommand.class);
registerCommand("difficulty", DifficultyCommand.class);
}
}

View file

@ -0,0 +1,214 @@
package me.unurled.sacredrealms.sr.commands.player;
import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER;
import static me.unurled.sacredrealms.sr.utils.Component.NO_PERMISSION;
import static me.unurled.sacredrealms.sr.utils.Component.PLAYER_NOT_FOUND;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import java.util.Arrays;
import java.util.List;
import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.gui.difficulty.DifficultyGUI;
import me.unurled.sacredrealms.sr.managers.Manager;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.xenondevs.invui.window.Window;
/**
* /difficulty ~open a gui for current player~ /difficulty [player] ~open a gui for another player~
* /difficulty [player] [difficulty] ~set the difficulty for another player~
*/
public class DifficultyCommand implements TabExecutor {
public static final String DIFFICULTY_SELF = "sr.difficulty.self";
public static final String DIFFICULTY_MANAGE = "sr.difficulty.manage";
public static final String CHOOSE_DIFFICULTY = "Choose Difficulty";
public static void usage(CommandSender sender) {
if (sender instanceof Player p) {
if (p.hasPermission(DIFFICULTY_SELF)) {
sender.sendMessage(textComp("<yellow>Usage: /difficulty"));
}
if (p.hasPermission(DIFFICULTY_MANAGE)) {
sender.sendMessage(textComp("<yellow>Usage: /difficulty [player]"));
sender.sendMessage(textComp("<yellow>Usage: /difficulty [player] [difficulty]"));
}
} else {
sender.sendMessage(textComp("<yellow>Usage: /difficulty [player]"));
sender.sendMessage(textComp("<yellow>Usage: /difficulty [player] [difficulty]"));
}
}
private static void playerHandling(
@NotNull CommandSender sender, @NotNull String[] args, @NotNull Player p) {
if (!p.hasPermission(DIFFICULTY_SELF)) {
sender.sendMessage(textComp(NO_PERMISSION));
return;
}
if (args.length >= 1 && !p.hasPermission(DIFFICULTY_MANAGE)) {
sender.sendMessage(textComp(NO_PERMISSION));
usage(sender);
return;
}
if (args.length == 0) {
// open gui for sender
Window window =
Window.single()
.setViewer(p)
.setTitle(CHOOSE_DIFFICULTY)
.setGui(DifficultyGUI.createGui())
.build();
window.open();
return;
}
if (args.length == 1) {
// open gui for target player
Player target = p.getServer().getPlayer(args[0]);
if (target == null) {
sender.sendMessage(textComp(PLAYER_NOT_FOUND));
return;
}
Window window =
Window.single()
.setViewer(p)
.setTitle(CHOOSE_DIFFICULTY)
.setGui(DifficultyGUI.createGui())
.build();
window.open();
return;
}
if (args.length == 2) {
// set difficulty for target player
Player target = p.getServer().getPlayer(args[0]);
if (target == null) {
sender.sendMessage(textComp(PLAYER_NOT_FOUND));
return;
}
// set difficulty
PlayerManager pm = Manager.getInstance(PlayerManager.class);
if (pm.isSRPlayer(target.getUniqueId())) {
Difficulty difficulty = Difficulty.valueOf(args[1].toUpperCase());
setDifficulty(sender, pm, target, difficulty);
}
}
}
private static void setDifficulty(
@NotNull CommandSender sender,
@NotNull PlayerManager pm,
@NotNull Player target,
Difficulty difficulty) {
SRPlayer sr = pm.getPlayer(target.getUniqueId());
if (sr == null) {
sender.sendMessage(textComp(PLAYER_NOT_FOUND));
return;
}
sr.setDifficulty(difficulty);
Audience.audience(target)
.sendMessage(
Component.text("Your difficulty has been set to ")
.append(difficulty.getName())
.append(textComp("."))
.color(difficulty.getColor()));
}
private static void consoleHandler(
@NotNull CommandSender sender, @NotNull String @NotNull [] args) {
if (args.length == 0) {
sender.sendMessage(textComp(NOT_PLAYER));
usage(sender);
return;
}
Player target = Bukkit.getPlayer(args[0]);
if (target == null) {
sender.sendMessage(textComp(PLAYER_NOT_FOUND));
return;
}
if (args.length == 1) {
Window window =
Window.single()
.setViewer(target)
.setTitle(CHOOSE_DIFFICULTY)
.setGui(DifficultyGUI.createGui())
.build();
window.open();
} else {
Difficulty difficulty;
try {
difficulty = Difficulty.valueOf(args[1].toUpperCase());
} catch (IllegalArgumentException e) {
sender.sendMessage(textComp("<red>Invalid difficulty."));
return;
}
PlayerManager pm = Manager.getInstance(PlayerManager.class);
if (pm.isSRPlayer(target.getUniqueId())) {
setDifficulty(sender, pm, target, difficulty);
}
}
}
/**
* Executes the given command, returning its success. <br>
* If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be
* sent to the player.
*
* @param sender Source of the command
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(
@NotNull CommandSender sender,
@NotNull Command command,
@NotNull String label,
@NotNull String[] args) {
if (sender instanceof Player p) {
playerHandling(sender, args, p);
} else {
consoleHandler(sender, args);
}
return true;
}
/**
* Requests a list of possible completions for a command argument.
*
* @param sender Source of the command. For players tab-completing a command inside of a command
* block, this will be the player, not the command block.
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args The arguments passed to the command, including final partial argument to be
* completed
* @return A List of possible completions for the final argument, or null to default to the
* command executor
*/
@Override
public @Nullable List<String> onTabComplete(
@NotNull CommandSender sender,
@NotNull Command command,
@NotNull String label,
@NotNull String @NotNull [] args) {
if (args.length == 0 && sender.hasPermission(DIFFICULTY_MANAGE)) {
return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();
}
if (args.length == 1 && sender.hasPermission(DIFFICULTY_MANAGE)) {
return Arrays.stream(Difficulty.values()).map(Enum::name).toList();
}
return List.of();
}
}

View file

@ -46,6 +46,14 @@ public class CombatManager extends Manager {
double luck = dLuck - eLuck;
if (!pm.isSRPlayer(player.getUniqueId())) {
return;
}
SRPlayer sr = pm.getPlayer(player.getUniqueId());
if (sr == null) {
return;
}
if (luck < -1000) {
// 100% chance of miss
player.sendMessage(comp("<red>You dodged!"));
@ -56,7 +64,7 @@ public class CombatManager extends Manager {
// 100% chance of critical hit
luck = 10000d;
player.playSound(player, Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0f, 1.0f);
damage = damage * 2;
damage = damage * 2 * sr.getDifficulty().getDamageMultiplier();
}
if (luck < 0) {
@ -71,7 +79,7 @@ public class CombatManager extends Manager {
// chance of critical hit
player.playSound(player, Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0f, 1.0f);
// damage * 2
damage = damage * 2;
damage = damage * 2 * sr.getDifficulty().getDamageMultiplier();
}
// apply damage

View file

@ -0,0 +1,42 @@
package me.unurled.sacredrealms.sr.components.difficulty;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
public enum Difficulty {
EASY(textComp("Easy"), 1.75, 0.75, NamedTextColor.GREEN),
NORMAL(textComp("Normal"), 1, 1, NamedTextColor.YELLOW),
HARD(textComp("Hard"), 0.75, 1.75, NamedTextColor.RED),
INSANE(textComp("<obf>aa</obf>Insane<obf>aa</obf>"), 0.05, 5, NamedTextColor.DARK_RED);
private final TextComponent name;
private final double damageMultiplier;
private final double xpMultiplier;
private final TextColor color;
Difficulty(TextComponent name, double damageMultiplier, double xpMultiplier, TextColor color) {
this.name = name;
this.damageMultiplier = damageMultiplier;
this.xpMultiplier = xpMultiplier;
this.color = color;
}
public TextComponent getName() {
return this.name;
}
public double getDamageMultiplier() {
return this.damageMultiplier;
}
public double getXpMultiplier() {
return this.xpMultiplier;
}
public TextColor getColor() {
return this.color;
}
}

View file

@ -11,6 +11,7 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import me.unurled.sacredrealms.sr.components.item.Item;
import me.unurled.sacredrealms.sr.events.player.PlayerKillEvent;
import me.unurled.sacredrealms.sr.managers.Manager;
@ -39,6 +40,7 @@ public class SRPlayer {
@Expose private List<PotionEffect> potionEffects = new ArrayList<>();
@Expose private Inventory inventory;
@Expose private List<Integer> treasuresOpened = new ArrayList<>();
@Expose private Difficulty difficulty;
private boolean isClientBuilder = false;
private boolean firstTime = true;
@ -255,7 +257,7 @@ public class SRPlayer {
public void setExperience(Long experience) {
// checks if experience is above next level requirements
if (experience >= levelRequirements.get(level - 1)) {
if (experience >= levelRequirements.get(level - 1) * difficulty.getXpMultiplier()) {
PlayerManager pm = Manager.getInstance(PlayerManager.class);
setLevel(level + 1);
pm.levelUp(this, level - 1);
@ -290,4 +292,12 @@ public class SRPlayer {
public void setFirstTime(boolean b) {
firstTime = b;
}
public Difficulty getDifficulty() {
return difficulty;
}
public void setDifficulty(Difficulty difficulty) {
this.difficulty = difficulty;
}
}

View file

@ -0,0 +1,28 @@
package me.unurled.sacredrealms.sr.gui.difficulty;
import static me.unurled.sacredrealms.sr.utils.Items.cancelItem;
import static me.unurled.sacredrealms.sr.utils.Items.glassPane;
import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import org.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.gui.Gui.Builder.Normal;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.impl.SimpleItem;
public class DifficultyGUI {
public static @NotNull Gui createGui() {
Item cancel = new SimpleItem(cancelItem());
Item glass = new SimpleItem(glassPane());
Normal gui =
Gui.normal()
.setStructure(".........", "..1.2.3..", "....4....", "....5....")
.addIngredient('5', cancel)
.addIngredient('.', glass)
.addIngredient('1', new DifficultyItem(Difficulty.EASY))
.addIngredient('2', new DifficultyItem(Difficulty.NORMAL))
.addIngredient('3', new DifficultyItem(Difficulty.HARD))
.addIngredient('4', new DifficultyItem(Difficulty.INSANE));
return gui.build();
}
}

View file

@ -0,0 +1,96 @@
package me.unurled.sacredrealms.sr.gui.difficulty;
import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.AbstractItem;
import xyz.xenondevs.invui.window.Window;
public class DifficultyItem extends AbstractItem {
private Difficulty difficulty;
public DifficultyItem(Difficulty difficulty) {
this.difficulty = difficulty;
}
/**
* Gets the {@link ItemProvider}. This method gets called every time a {@link Window} is notified
* ({@link #notifyWindows()}).
*
* @return The {@link ItemProvider}
*/
@Override
public ItemProvider getItemProvider() {
return switch (difficulty) {
case EASY ->
new ItemBuilder(Material.BREAD)
.setDisplayName("Easy")
.addLoreLines(
"Is you are a new player or",
"someone who just want to",
"enjoy the game without " + "grinding too much",
"",
"Click Here!");
case NORMAL ->
new ItemBuilder(Material.GRASS_BLOCK)
.setDisplayName("Normal")
.addLoreLines(
"Is you are a regular player",
"who want to enjoy the game",
"without too much grinding",
"",
"Click Here!");
case HARD ->
new ItemBuilder(Material.DIAMOND_SWORD)
.setDisplayName("Hard")
.addLoreLines(
"Is you are a hardcore player",
"who want to enjoy the game",
"with some grinding",
"",
"Click Here!");
case INSANE ->
new ItemBuilder(Material.NETHERITE_SWORD)
.setDisplayName("Insane")
.addLoreLines(
"Is you are a pro player",
"who want to enjoy the game",
"with a lot of grinding",
"some things are hidden very well here...",
"",
"Click Here!");
};
}
/**
* A method called if the {@link ItemStack} associated to this {@link Item} has been clicked by a
* player.
*
* @param clickType The {@link ClickType} the {@link Player} performed.
* @param player The {@link Player} who clicked on the {@link ItemStack}.
* @param event The {@link InventoryClickEvent} associated with this click.
*/
@Override
public void handleClick(
@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
// Set the player's difficulty
PlayerManager pm = Manager.getInstance(PlayerManager.class);
if (pm.isSRPlayer(player.getUniqueId())) {
SRPlayer sr = pm.getPlayer(player.getUniqueId());
if (sr != null) {
sr.setDifficulty(difficulty);
}
}
}
}

View file

@ -1,6 +1,8 @@
package me.unurled.sacredrealms.sr.gui.treasure;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import static me.unurled.sacredrealms.sr.utils.Items.cancelItem;
import static me.unurled.sacredrealms.sr.utils.Items.glassPane;
import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import org.bukkit.Material;
@ -18,10 +20,7 @@ public class TreasureGUI {
@NotNull
public static Gui createGui(@NotNull Treasure treasure) {
ItemStack itemStack = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(textComp(""));
itemStack.setItemMeta(itemMeta);
ItemStack itemStack = glassPane();
Item pane = new SimpleItem(itemStack);
Normal gui =
Gui.normal()
@ -38,10 +37,7 @@ public class TreasureGUI {
}
}
ItemStack cancel = new ItemStack(Material.BARRIER);
ItemMeta cancelMeta = cancel.getItemMeta();
cancelMeta.displayName(textComp("<b><red>Cancel</red></b>"));
cancel.setItemMeta(cancelMeta);
ItemStack cancel = cancelItem();
ItemStack confirm = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
ItemMeta confirmMeta = confirm.getItemMeta();

View file

@ -10,6 +10,8 @@ public class Component {
public static final String NO_PERMISSION = "<red>You do not have permission to use this command.";
public static final String ERROR =
"<red>An error occurred while executing this command. Please" + " contact an admin.";
public static final String PLAYER_NOT_FOUND = "<red>Player not found.";
private static MiniMessage miniMessage;
private Component() {}

View file

@ -1,6 +1,7 @@
package me.unurled.sacredrealms.sr.utils;
import static me.unurled.sacredrealms.sr.utils.Component.comp;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer;
import java.util.ArrayList;
@ -17,6 +18,7 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
@ -26,6 +28,22 @@ public class Items {
private Items() {}
public static @NotNull ItemStack cancelItem() {
ItemStack cancel = new ItemStack(Material.BARRIER);
ItemMeta cancelMeta = cancel.getItemMeta();
cancelMeta.displayName(textComp("<b><red>Cancel</red></b>"));
cancel.setItemMeta(cancelMeta);
return cancel;
}
public static @NotNull ItemStack glassPane() {
ItemStack itemStack = new ItemStack(Material.GRAY_STAINED_GLASS_PANE);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(textComp(""));
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static @NotNull Double getTotalAttribute(@NotNull Player player, Attribute attribute) {
return getTotalAttribute(player.getEquipment(), attribute);
}

View file

@ -38,6 +38,12 @@ permissions:
sr.treasure.manage:
default: op
description: When the player has permission for the command /treasure create
sr.difficulty.manage:
default: op
description: When the player has permission for the command /difficulty set player
sr.difficulty.self:
default: not op
description: When the player has permission for the command /difficulty
commands:
attributes:
@ -56,3 +62,5 @@ commands:
description: Reset the adventure of the player
treasure:
description: Create a treasure chest.
difficulty:
description: Set the difficulty of the player.