Compare commits

...

2 Commits

Author SHA1 Message Date
Teriuihi 6bb4673b08 Add Engineer class and update Tank, Fighter, and GameClass
Introduced the Engineer class with unique tools, functionality, and creation logic. Updated the Tank class to make its constructor public and adjusted its creator to use the appropriate class. Enhanced GameClass to append health and damage details to display item lore dynamically.
2025-02-08 15:19:32 +01:00
Teriuihi a175d1829b Refactor class creators with annotations and utility methods.
Added @Contract, @NotNull, and @Unmodifiable annotations for better code safety and clarity. Refactored utility methods in `TankCreator` and `FighterCreator` to enhance readability and reuse, including extracting item creation logic for tools and display items.
2025-02-08 15:02:42 +01:00
8 changed files with 168 additions and 19 deletions

View File

@ -5,7 +5,6 @@
- [x] Stores all players - [x] Stores all players
- [x] Allows starting, restarting, and ending game - [x] Allows starting, restarting, and ending game
- [ ] Limit playing area (x, y, and z) (could be done through WorldGuard) - [ ] Limit playing area (x, y, and z) (could be done through WorldGuard)
- [ ] Stores location for ppl to watch/wait in or handles putting them in gmsp
- [ ] Team - [ ] Team
- [x] Stores members - [x] Stores members
- [ ] Stores score - [ ] Stores score
@ -28,8 +27,8 @@
- [x] Allows Team member to select class - [x] Allows Team member to select class
- [ ] Classes - [ ] Classes
- [x] Fighter: lower health, higher dmg/throwing speed - [x] Fighter: lower health, higher dmg/throwing speed
- [ ] Tank: Has shield, invincibility effect, slower (short + long cooldown)? - [x] Tank: Has shield, invincibility effect, slower (short + long cooldown)?
- [ ] Engineer: Better shovel, lower health, lower dmg, (can drop snowballs to team members?) store snow at base, can build? - [x] Engineer: Better shovel, lower health, lower dmg, (can drop snowballs to team members?) store snow at base, can build?
- [ ] HARD Mage: Drops snowballs in area (casting cost) - [ ] HARD Mage: Drops snowballs in area (casting cost)
- [ ] HARD Scout: low dmg, high speed, (invisible sometimes?) can see flag carrier through walls or maybe see their path in particles? - [ ] HARD Scout: low dmg, high speed, (invisible sometimes?) can see flag carrier through walls or maybe see their path in particles?
- [ ] Game events - [ ] Game events

View File

@ -5,6 +5,7 @@ import com.alttd.ctf.team.TeamPlayer;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
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.Color; import org.bukkit.Color;
@ -17,10 +18,12 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
public abstract class GameClass { public abstract class GameClass {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
private final List<Material> armor; private final List<Material> armor;
private final List<ItemStack> tools; private final List<ItemStack> tools;
@ -36,7 +39,8 @@ public abstract class GameClass {
@Getter @Getter
private final int damage; private final int damage;
protected GameClass(@NotNull List<Material> armor, @NotNull List<ItemStack> tools, @NotNull ItemStack displayItem, double health, int throwTickSpeed, int damage) { protected GameClass(@NotNull List<Material> armor, @NotNull List<ItemStack> tools, @NotNull ItemStack displayItem,
double health, int throwTickSpeed, int damage) {
if (armor.size() != 4) { if (armor.size() != 4) {
throw new IllegalArgumentException("Armor has to have 4 entries"); throw new IllegalArgumentException("Armor has to have 4 entries");
} }
@ -51,6 +55,17 @@ public abstract class GameClass {
throw new IllegalArgumentException("Display item has no item meta"); throw new IllegalArgumentException("Display item has no item meta");
} }
this.className = itemMeta.displayName(); this.className = itemMeta.displayName();
List<Component> lore = itemMeta.lore();
if (lore == null) {
throw new IllegalArgumentException("Display item has no lore");
}
ArrayList<Component> loreList = new ArrayList<>(lore);
loreList.add(miniMessage.deserialize("<gold>Health: <health>, Damage: <damage></gold>",
Placeholder.parsed("health", String.valueOf(health)),
Placeholder.parsed("damage", String.valueOf(damage))
));
itemMeta.lore(loreList);
displayItem.setItemMeta(itemMeta);
} }
public void apply(TeamPlayer teamPlayer) { public void apply(TeamPlayer teamPlayer) {

View File

@ -0,0 +1,75 @@
package com.alttd.ctf.game_class.creation;
import com.alttd.ctf.game_class.GameClass;
import com.alttd.ctf.game_class.implementations.Engineer;
import com.alttd.ctf.game_class.implementations.Fighter;
import com.alttd.ctf.team.TeamColor;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.util.List;
@Slf4j
public class EngineerCreator {
private static final MiniMessage miniMessage = MiniMessage.miniMessage();
@Contract("_ -> new")
public static @NotNull GameClass createEngineer(@NotNull TeamColor teamColor) {
return new Engineer(getArmor(), getTools(teamColor), getDisplayItem(teamColor),
15, 5, 3);
}
@Contract(value = " -> new", pure = true)
private static @NotNull @Unmodifiable List<Material> getArmor() {
return (List.of(Material.AIR, Material.AIR, Material.LEATHER_CHESTPLATE, Material.AIR));
}
@Contract("_ -> new")
private static @NotNull @Unmodifiable List<ItemStack> getTools(@NotNull TeamColor teamColor) {
return (List.of(getShovel(teamColor), getPotion(teamColor)));
}
private static @NotNull ItemStack getPotion(@NotNull TeamColor teamColor) {
ItemStack healthPot = new ItemStack(Material.POTION);
if (!(healthPot.getItemMeta() instanceof PotionMeta potionMeta)) {
throw new IllegalStateException("No potion meta from a potion");
}
potionMeta.setBasePotionType(PotionType.STRONG_SWIFTNESS);
potionMeta.itemName(miniMessage.deserialize(
String.format("<color:%s>Emergency escape kit</color>", teamColor.hex())));
healthPot.setItemMeta(potionMeta);
healthPot.setAmount(3);
return healthPot;
}
private static @NotNull ItemStack getShovel(@NotNull TeamColor teamColor) {
ItemStack shovel = new ItemStack(Material.IRON_SHOVEL);
ItemMeta meta = shovel.getItemMeta();
meta.itemName(miniMessage.deserialize(String.format("<color:%s>Snow excavator</color>", teamColor.hex())));
meta.addEnchant(Enchantment.EFFICIENCY, 4, false);
shovel.setItemMeta(meta);
return shovel;
}
private static @NotNull ItemStack getDisplayItem(@NotNull TeamColor teamColor) {
ItemStack itemStack = new ItemStack(Material.IRON_SHOVEL);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(miniMessage.deserialize(String.format("<color:%s>Engineer</color>", teamColor.hex())));
itemMeta.lore(List.of(
miniMessage.deserialize("<gold>The Engineer can mine snow fast</gold>"),
miniMessage.deserialize("<gold>They can use speed potions to escape danger</gold>")
));
itemStack.setItemMeta(itemMeta);
return itemStack;
}
}

View File

@ -6,10 +6,14 @@ import com.alttd.ctf.team.TeamColor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.util.List; import java.util.List;
@ -18,28 +22,45 @@ public class FighterCreator {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static GameClass createFighter(TeamColor teamColor) { @Contract("_ -> new")
return new Fighter(getArmor(), getTools(teamColor), getDisplayItem(teamColor), 15, 3, 5); public static @NotNull GameClass createFighter(@NotNull TeamColor teamColor) {
return new Fighter(getArmor(), getTools(teamColor), getDisplayItem(teamColor),
15, 3, 5);
} }
private static List<Material> getArmor() { @Contract(value = " -> new", pure = true)
private static @NotNull @Unmodifiable List<Material> getArmor() {
return (List.of(Material.AIR, Material.AIR, Material.LEATHER_CHESTPLATE, Material.AIR)); return (List.of(Material.AIR, Material.AIR, Material.LEATHER_CHESTPLATE, Material.AIR));
} }
private static List<ItemStack> getTools(TeamColor teamColor) { @Contract("_ -> new")
private static @NotNull @Unmodifiable List<ItemStack> getTools(@NotNull TeamColor teamColor) {
return (List.of(getShovel(teamColor), getPotion(teamColor)));
}
private static @NotNull ItemStack getPotion(@NotNull TeamColor teamColor) {
ItemStack healthPot = new ItemStack(Material.SPLASH_POTION); ItemStack healthPot = new ItemStack(Material.SPLASH_POTION);
if (!(healthPot.getItemMeta() instanceof PotionMeta potionMeta)) { if (!(healthPot.getItemMeta() instanceof PotionMeta potionMeta)) {
throw new IllegalStateException("No potion meta from a splash potion"); throw new IllegalStateException("No potion meta from a splash potion");
} }
potionMeta.setBasePotionType(PotionType.STRONG_HEALING); potionMeta.setBasePotionType(PotionType.STRONG_HEALING);
potionMeta.itemName(MiniMessage.miniMessage().deserialize( potionMeta.itemName(miniMessage.deserialize(
String.format("<color:%s>Emergency AOE med kit</color>", teamColor.hex()))); String.format("<color:%s>Emergency AOE med kit</color>", teamColor.hex())));
healthPot.setItemMeta(potionMeta); healthPot.setItemMeta(potionMeta);
healthPot.setAmount(3); healthPot.setAmount(3);
return (List.of(healthPot)); return healthPot;
} }
private static ItemStack getDisplayItem(TeamColor teamColor) { private static @NotNull ItemStack getShovel(@NotNull TeamColor teamColor) {
ItemStack shovel = new ItemStack(Material.WOODEN_SHOVEL);
ItemMeta meta = shovel.getItemMeta();
meta.itemName(miniMessage.deserialize(String.format("<color:%s>Snow shovel</color>", teamColor.hex())));
meta.addEnchant(Enchantment.EFFICIENCY, 1, false);
shovel.setItemMeta(meta);
return shovel;
}
private static @NotNull ItemStack getDisplayItem(@NotNull TeamColor teamColor) {
ItemStack itemStack = new ItemStack(Material.IRON_SWORD); ItemStack itemStack = new ItemStack(Material.IRON_SWORD);
ItemMeta itemMeta = itemStack.getItemMeta(); ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(miniMessage.deserialize(String.format("<color:%s>Fighter</color>", teamColor.hex()))); itemMeta.displayName(miniMessage.deserialize(String.format("<color:%s>Fighter</color>", teamColor.hex())));

View File

@ -2,6 +2,7 @@ package com.alttd.ctf.game_class.creation;
import com.alttd.ctf.game_class.GameClass; import com.alttd.ctf.game_class.GameClass;
import com.alttd.ctf.game_class.implementations.Fighter; import com.alttd.ctf.game_class.implementations.Fighter;
import com.alttd.ctf.game_class.implementations.Tank;
import com.alttd.ctf.team.TeamColor; import com.alttd.ctf.team.TeamColor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
@ -9,6 +10,9 @@ import org.bukkit.Material;
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;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.util.List; import java.util.List;
@ -17,25 +21,41 @@ public class TankCreator {
private static final MiniMessage miniMessage = MiniMessage.miniMessage(); private static final MiniMessage miniMessage = MiniMessage.miniMessage();
public static GameClass createTank(TeamColor teamColor) {//TODO add ability to become temp invulnerable (with some particle effects mayb?) @Contract("_ -> new")
return new Fighter(getArmor(), getTools(teamColor), getDisplayItem(teamColor), 30, 7, 4); public static @NotNull GameClass createTank(@NotNull TeamColor teamColor) {//TODO add ability to become temp invulnerable (with some particle effects mayb?)
return new Tank(getArmor(), getTools(teamColor), getDisplayItem(teamColor),
30, 7, 4);
} }
private static List<Material> getArmor() { @Contract(value = " -> new", pure = true)
private static @Unmodifiable List<Material> getArmor() {
return (List.of(Material.CHAINMAIL_BOOTS, Material.CHAINMAIL_LEGGINGS, Material.LEATHER_CHESTPLATE, Material.CHAINMAIL_HELMET)); return (List.of(Material.CHAINMAIL_BOOTS, Material.CHAINMAIL_LEGGINGS, Material.LEATHER_CHESTPLATE, Material.CHAINMAIL_HELMET));
} }
private static List<ItemStack> getTools(TeamColor teamColor) { @Contract("_ -> new")
private static @NotNull @Unmodifiable List<ItemStack> getTools(TeamColor teamColor) {
return (List.of(getShovel(teamColor), getShield(teamColor)));
}
private static @NotNull ItemStack getShield(@NotNull TeamColor teamColor) {
ItemStack shield = new ItemStack(Material.SHIELD); ItemStack shield = new ItemStack(Material.SHIELD);
ItemMeta itemMeta = shield.getItemMeta(); ItemMeta itemMeta = shield.getItemMeta();
itemMeta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); itemMeta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE);
itemMeta.itemName(MiniMessage.miniMessage().deserialize( itemMeta.itemName(MiniMessage.miniMessage().deserialize(
String.format("<color:%s>Shield</color>", teamColor.hex()))); String.format("<color:%s>Shield</color>", teamColor.hex())));
shield.setItemMeta(itemMeta); shield.setItemMeta(itemMeta);
return (List.of(shield)); return shield;
} }
private static ItemStack getDisplayItem(TeamColor teamColor) { private static @NotNull ItemStack getShovel(@NotNull TeamColor teamColor) {
ItemStack shovel = new ItemStack(Material.WOODEN_SHOVEL);
ItemMeta meta = shovel.getItemMeta();
meta.itemName(miniMessage.deserialize(String.format("<color:%s>Snow shovel</color>", teamColor.hex())));
shovel.setItemMeta(meta);
return shovel;
}
private static @NotNull ItemStack getDisplayItem(@NotNull TeamColor teamColor) {
ItemStack itemStack = new ItemStack(Material.SHIELD); ItemStack itemStack = new ItemStack(Material.SHIELD);
ItemMeta itemMeta = itemStack.getItemMeta(); ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.displayName(miniMessage.deserialize(String.format("<color:%s>Tank</color>", teamColor.hex()))); itemMeta.displayName(miniMessage.deserialize(String.format("<color:%s>Tank</color>", teamColor.hex())));

View File

@ -0,0 +1,15 @@
package com.alttd.ctf.game_class.implementations;
import com.alttd.ctf.game_class.GameClass;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class Engineer extends GameClass {
public Engineer(@NotNull List<Material> armor, @NotNull List<ItemStack> tools, @NotNull ItemStack displayItem,
double health, int throwTickSpeed, int damage) {
super(armor, tools, displayItem, health, throwTickSpeed, damage);
}
}

View File

@ -1,16 +1,19 @@
package com.alttd.ctf.game_class.implementations; package com.alttd.ctf.game_class.implementations;
import com.alttd.ctf.game_class.GameClass; import com.alttd.ctf.game_class.GameClass;
import com.alttd.ctf.team.TeamColor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
public class Fighter extends GameClass { public class Fighter extends GameClass {
public Fighter(List<Material> armor, List<ItemStack> tools, ItemStack displayItem, double health, int tickThrowSpeed, int damage) { public Fighter(List<Material> armor, List<ItemStack> tools, ItemStack displayItem,
double health, int tickThrowSpeed, int damage) {
super(armor, tools, displayItem, health, tickThrowSpeed, damage); super(armor, tools, displayItem, health, tickThrowSpeed, damage);
} }

View File

@ -9,7 +9,8 @@ import java.util.List;
public class Tank extends GameClass { public class Tank extends GameClass {
protected Tank(@NotNull List<Material> armor, @NotNull List<ItemStack> tools, @NotNull ItemStack displayItem, double health, int throwTickSpeed, int damage) { public Tank(@NotNull List<Material> armor, @NotNull List<ItemStack> tools, @NotNull ItemStack displayItem,
double health, int throwTickSpeed, int damage) {
super(armor, tools, displayItem, health, throwTickSpeed, damage); super(armor, tools, displayItem, health, throwTickSpeed, damage);
} }
} }