diff --git a/.github/README.md b/.github/README.md
index 560338605..1d7157335 100644
--- a/.github/README.md
+++ b/.github/README.md
@@ -1,50 +1,30 @@
-![](https://images.plugily.xyz/banner/display.php?id=VillageDefense)
-
-# Village Defense [![Maven Repository](https://maven.plugily.xyz/api/badge/latest/releases/plugily/projects/villagedefense?color=40c14a&name=Maven&prefix=v)](https://maven.plugily.xyz/#/releases/plugily/projects/villagedefense) [![JavaDoc Repository](https://maven.plugily.xyz/api/badge/latest/releases/plugily/projects/villagedefense?color=40c14a&name=JavaDoc&prefix=v)](https://maven.plugily.xyz/javadoc/releases/plugily/projects/villagedefense/latest) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=Plugily-Projects_Village_Defense&metric=sqale_rating)](https://sonarcloud.io/summary/overall?id=Plugily-Projects_Village_Defense) [![Discord](https://img.shields.io/discord/345628548716822530.svg?color=7289DA&style=for-the-badge&logo=discord)](https://discord.plugily.xyz) [![Patreon]( https://img.shields.io/badge/Patreon-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://patreon.com/plugily)
-
-Village Defense is a Minecraft minigame designed for small and big servers. This minigame is unique and very
-configurable, 100% free and open source!
-
-The goal is to protect Villagers from hordes of undead Creatures. However, the game isn't that easy. There are more and
-more zombies every wave and more types of them come in higher waves. There is no wave limit so try to survive as long as
-you can!
-
-Have fun using it! Leave a good rating if you really like it.
-
-## Want to contribute in this project?
-
-[**🉑 Code Contributions**](https://github.com/Plugily-Projects/Village_Defense/blob/master/.github/CONTRIBUTING.md)
-[**💣 Issues Reporting (Discord)**](https://discordapp.com/invite/UXzUdTP)
-[**❤ Make Donation**](https://www.paypal.me/plugilyprojects)
-
-# Credits
-
-## Open Source Libraries
-
-| Library | Author | License |
-|------------------------------------------------------------------|--------------------------------------------------------|------------------------------------------------------------------------------------|
-| [MiniGamesBox](https://github.com/Plugily-Projects/MiniGamesBox) | [Plugily Projets](https://github.com/Plugily-Projects) | [GPLv3](https://github.com/Plugily-Projects/MiniGamesBox/blob/master/LICENSE.md) |
-| [ScoreboardLib](https://github.com/TigerHix/ScoreboardLib/) | [TigerHix](https://github.com/TigerHix) | [LGPLv3](https://github.com/TigerHix/ScoreboardLib/blob/master/LICENSE) |
-| [HikariCP](https://github.com/brettwooldridge/HikariCP) | [brettwooldridge](https://github.com/brettwooldridge) | [Apache License 2.0](https://github.com/brettwooldridge/HikariCP/blob/dev/LICENSE) |
-| [bStats](https://github.com/Bastian/bStats-Metrics) | [Bastian](https://github.com/Bastian) | [LGPLv3](https://github.com/Bastian/bStats-Metrics/blob/master/LICENSE) |
-| [Commons Box](https://github.com/Plajer/Commons-Box) | [Plajer](https://github.com/Plajer) | [GPLv3](https://github.com/Plajer/Commons-Box/blob/master/LICENSE.md) |
-
-## Open Source Licenses
-
-#### JetBrains
-
-
-
-Thanks to JetBrains for Open Source Program license for open source development.
-
-#### Code Whale
-
-
-
-Thanks to Code Whale for Open Source license for POEditor project.
-
-## Contributors
-
-[List of all contributors here](https://plajer.xyz/contributors/villagedefense.html)
-
-
+# Village Defense Gold
+
+A hard fork created to implement many new exciting features into Village Defense 4.0.0.
+
+Formerly known as Village Defense 5.0.0 update this hard fork now focuses on personal upgrades to the codebase with new
+gameplay stuff and other features.
+
+**No support and maintenance obligations are provided for this hard fork as it's only intended for private/limited group
+use only.**
+**Feel free to compile sources yourself and edit the plugin accordingly to your needs**
+
+Depends on [MinigamesBoxGold](https://github.com/Plajer/MinigamesBoxGold)
+
+### List of features done and planned for this version:
+
+* **Opinionated design choices and hardcoded values and options**
+* Many QoL and gameplay loop and pacing improvements
+* Drastically improved Look and Feel (sounds & effects)
+* Many fixes including ally pets targeting villagers/other pets/players
+* Kits balance changes
+* Revamped powerups
+* Revamped entity upgrades (including hidden & special upgrades)
+* Mid-wave special events (shop offer, rotten flesh trader, pinata etc.)
+* Arena personal records
+* Enemies spawn system revamp
+* New and more enjoyable enemies
+* Shop auto armor equip
+* Bosses between every game state (wave 15, wave 30, wave 50)
+* Engineer kit - replacement for Builder kit but with Turrets
+* Weekly random challenges
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index ee0f49901..30168cf46 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -33,19 +33,31 @@ repositories {
maven(uri("https://maven.plugily.xyz/snapshots"))
maven(uri("https://repo.citizensnpcs.co/"))
maven(uri("https://repo.maven.apache.org/maven2/"))
+ maven(uri("https://repo.dmulloy2.net/repository/public/"))
}
dependencies {
- implementation("plugily.projects:MiniGamesBox-Classic:1.2.0-SNAPSHOT36") { isTransitive = false }
- compileOnly("org.spigotmc:spigot-api:1.19.3-R0.1-SNAPSHOT")
+ implementation(files("lib/box-classic.jar"))
+ implementation(files("lib/box-db.jar"))
+ implementation(files("lib/box-inv.jar"))
+ implementation(files("lib/box-utils.jar"))
+ implementation("org.openjdk.nashorn:nashorn-core:15.1")
+ implementation("io.github.skytasul:glowingentities:1.3.2")
+ compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT")
compileOnly("org.jetbrains:annotations:24.0.1")
+
+ compileOnly("com.mojang:authlib:3.11.50")
+ compileOnly("com.comphenix.protocol:ProtocolLib:5.0.0")
compileOnly(files("lib/spigot/1.8.8-R0.1.jar"))
+
+ compileOnly("org.projectlombok:lombok:1.18.32")
+ annotationProcessor("org.projectlombok:lombok:1.18.32")
}
group = "plugily.projects"
-version = "4.6.1-SNAPSHOT79"
+version = "5.0.1-SNAPSHOT6"
description = "VillageDefense"
java {
withJavadocJar()
@@ -73,6 +85,12 @@ tasks {
options.encoding = "UTF-8"
}
+ compileJava {
+ options.encoding = "UTF-8"
+ targetCompatibility = JavaVersion.VERSION_17.toString()
+ sourceCompatibility = JavaVersion.VERSION_17.toString()
+ }
+
}
publishing {
diff --git a/src/main/java/plugily/projects/villagedefense/Main.java b/src/main/java/plugily/projects/villagedefense/Main.java
index 3b82dbbad..1e9281678 100644
--- a/src/main/java/plugily/projects/villagedefense/Main.java
+++ b/src/main/java/plugily/projects/villagedefense/Main.java
@@ -1,24 +1,25 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense;
-import org.bukkit.Bukkit;
+import fr.skytasul.glowingentities.GlowingEntities;
+import lombok.Getter;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPluginLoader;
@@ -27,6 +28,7 @@
import plugily.projects.minigamesbox.classic.handlers.setup.SetupInventory;
import plugily.projects.minigamesbox.classic.handlers.setup.categories.PluginSetupCategoryManager;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
+import plugily.projects.minigamesbox.classic.utils.misc.MiscUtils;
import plugily.projects.minigamesbox.classic.utils.services.metrics.Metrics;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.villagedefense.arena.Arena;
@@ -35,43 +37,32 @@
import plugily.projects.villagedefense.arena.ArenaRegistry;
import plugily.projects.villagedefense.arena.ArenaUtils;
import plugily.projects.villagedefense.arena.managers.enemy.spawner.EnemySpawnerRegistry;
-import plugily.projects.villagedefense.arena.managers.enemy.spawner.EnemySpawnerRegistryLegacy;
+import plugily.projects.villagedefense.arena.powerup.PowerupEvents;
import plugily.projects.villagedefense.boot.AdditionalValueInitializer;
import plugily.projects.villagedefense.boot.MessageInitializer;
import plugily.projects.villagedefense.boot.PlaceholderInitializer;
import plugily.projects.villagedefense.commands.arguments.ArgumentsRegistry;
import plugily.projects.villagedefense.creatures.CreatureUtils;
import plugily.projects.villagedefense.creatures.DoorBreakListener;
+import plugily.projects.villagedefense.events.EntityUpgradeListener;
import plugily.projects.villagedefense.events.PluginEvents;
-import plugily.projects.villagedefense.handlers.powerup.PowerupHandler;
+import plugily.projects.villagedefense.handlers.hologram.NewHologramManager;
import plugily.projects.villagedefense.handlers.setup.SetupCategoryManager;
-import plugily.projects.villagedefense.handlers.upgrade.EntityUpgradeMenu;
-import plugily.projects.villagedefense.handlers.upgrade.upgrades.Upgrade;
-import plugily.projects.villagedefense.handlers.upgrade.upgrades.UpgradeBuilder;
-import plugily.projects.villagedefense.kits.free.KnightKit;
-import plugily.projects.villagedefense.kits.free.LightTankKit;
-import plugily.projects.villagedefense.kits.level.ArcherKit;
-import plugily.projects.villagedefense.kits.level.GolemFriendKit;
-import plugily.projects.villagedefense.kits.level.HardcoreKit;
-import plugily.projects.villagedefense.kits.level.HealerKit;
-import plugily.projects.villagedefense.kits.level.LooterKit;
-import plugily.projects.villagedefense.kits.level.MediumTankKit;
-import plugily.projects.villagedefense.kits.level.PuncherKit;
-import plugily.projects.villagedefense.kits.level.RunnerKit;
-import plugily.projects.villagedefense.kits.level.TerminatorKit;
-import plugily.projects.villagedefense.kits.level.WorkerKit;
-import plugily.projects.villagedefense.kits.level.ZombieFinderKit;
-import plugily.projects.villagedefense.kits.premium.BlockerKit;
-import plugily.projects.villagedefense.kits.premium.CleanerKit;
-import plugily.projects.villagedefense.kits.premium.DogFriendKit;
-import plugily.projects.villagedefense.kits.premium.HeavyTankKit;
-import plugily.projects.villagedefense.kits.premium.MedicKit;
-import plugily.projects.villagedefense.kits.premium.NakedKit;
-import plugily.projects.villagedefense.kits.premium.PremiumHardcoreKit;
-import plugily.projects.villagedefense.kits.premium.ShotBowKit;
-import plugily.projects.villagedefense.kits.premium.TeleporterKit;
-import plugily.projects.villagedefense.kits.premium.TornadoKit;
-import plugily.projects.villagedefense.kits.premium.WizardKit;
+import plugily.projects.villagedefense.handlers.upgrade.EntityUpgradeHandlerEvents;
+import plugily.projects.villagedefense.handlers.upgrade.NewEntityUpgradeManager;
+import plugily.projects.villagedefense.kits.BuilderKit;
+import plugily.projects.villagedefense.kits.CleanerKit;
+import plugily.projects.villagedefense.kits.CrusaderKit;
+import plugily.projects.villagedefense.kits.KnightKit;
+import plugily.projects.villagedefense.kits.MedicKit;
+import plugily.projects.villagedefense.kits.PetsFriend;
+import plugily.projects.villagedefense.kits.ShotBowKit;
+import plugily.projects.villagedefense.kits.TerminatorKit;
+import plugily.projects.villagedefense.kits.TornadoKit;
+import plugily.projects.villagedefense.kits.WizardKit;
+import plugily.projects.villagedefense.kits.utils.KitHelper;
+import plugily.projects.villagedefense.user.VDUserManager;
+import plugily.projects.villagedefense.utils.ProtocolUtils;
import java.io.File;
import java.util.logging.Level;
@@ -82,11 +73,16 @@
*/
public class Main extends PluginMain {
- private FileConfiguration entityUpgradesConfig;
- private EnemySpawnerRegistryLegacy enemySpawnerRegistry;
+ private @Getter FileConfiguration entityUpgradesConfig;
+ private @Getter EnemySpawnerRegistry enemySpawnerRegistry;
+ private @Getter NewEntityUpgradeManager entityUpgradeManager;
+ private @Getter NewHologramManager newHologramManager;
+ private @Getter VDUserManager vdUserManager;
+ private @Getter GlowingEntities glowingEntities;
+
+ private ArgumentsRegistry argumentsRegistry;
private ArenaRegistry arenaRegistry;
private ArenaManager arenaManager;
- private ArgumentsRegistry argumentsRegistry;
@TestOnly
public Main() {
@@ -103,6 +99,9 @@ public void onEnable() {
long start = System.currentTimeMillis();
MessageInitializer messageInitializer = new MessageInitializer(this);
super.onEnable();
+ /*if(!validateStartup()) {
+ return;
+ }*/
getDebugger().debug("[System] [Plugin] Initialization start");
new PlaceholderInitializer(this);
messageInitializer.registerMessages();
@@ -113,33 +112,46 @@ public void onEnable() {
getDebugger().debug("[System] [Plugin] Initialization finished took {0}ms", System.currentTimeMillis() - start);
}
+ private boolean validateStartup() {
+ if (ServerVersion.Version.isCurrentLower(ServerVersion.Version.v1_12_R1)) {
+ MiscUtils.sendLineBreaker(this.getName());
+ getMessageUtils().thisVersionIsNotSupported();
+ MiscUtils.sendVersionInformation(this, this.getName(), this.getDescription());
+ getDebugger().sendConsoleMsg(getPluginMessagePrefix() + "&cYour server version is not supported by " + this.getDescription().getName() + "!");
+ getDebugger().sendConsoleMsg(getPluginMessagePrefix() + "&cSadly, we must shut off. Maybe you consider changing your server version?");
+ MiscUtils.sendLineBreaker(this.getName());
+ getServer().getPluginManager().disablePlugin(this);
+ return false;
+ }
+ return true;
+ }
+
public void initializePluginClasses() {
addFileName("powerups");
addFileName("creatures");
Arena.init(this);
ArenaUtils.init(this);
+ KitHelper.init(this);
+ ProtocolUtils.init(this);
new ArenaEvents(this);
+ new PowerupEvents(this);
+ vdUserManager = new VDUserManager(this);
arenaManager = new ArenaManager(this);
arenaRegistry = new ArenaRegistry(this);
arenaRegistry.registerArenas();
getSignManager().loadSigns();
getSignManager().updateSigns();
argumentsRegistry = new ArgumentsRegistry(this);
- if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_8_R3)) {
- enemySpawnerRegistry = new EnemySpawnerRegistryLegacy(this);
- } else {
- enemySpawnerRegistry = new EnemySpawnerRegistry(this);
- }
- if(getConfigPreferences().getOption("UPGRADES")) {
- entityUpgradesConfig = ConfigUtils.getConfig(this, "entity_upgrades");
- Upgrade.init(this);
- UpgradeBuilder.init(this);
- new EntityUpgradeMenu(this);
- }
+ enemySpawnerRegistry = new EnemySpawnerRegistry(this);
+ entityUpgradesConfig = ConfigUtils.getConfig(this, "entity_upgrades");
+ entityUpgradeManager = new NewEntityUpgradeManager(this);
+ newHologramManager = new NewHologramManager(this);
new DoorBreakListener(this);
CreatureUtils.init(this);
- new PowerupHandler(this);
new PluginEvents(this);
+ new EntityUpgradeListener(this);
+ new EntityUpgradeHandlerEvents(this);
+ this.glowingEntities = new GlowingEntities(this);
addPluginMetrics();
}
@@ -147,13 +159,12 @@ public void addKits() {
long start = System.currentTimeMillis();
getDebugger().debug("Adding kits...");
addFileName("kits");
- Class>[] classKitNames = new Class[]{KnightKit.class, LightTankKit.class, ZombieFinderKit.class, ArcherKit.class, PuncherKit.class, HealerKit.class, LooterKit.class, RunnerKit.class,
- MediumTankKit.class, WorkerKit.class, GolemFriendKit.class, TerminatorKit.class, HardcoreKit.class, CleanerKit.class, TeleporterKit.class, HeavyTankKit.class, ShotBowKit.class,
- DogFriendKit.class, PremiumHardcoreKit.class, TornadoKit.class, BlockerKit.class, MedicKit.class, NakedKit.class, WizardKit.class};
- for(Class> kitClass : classKitNames) {
+ Class>[] classKitNames = new Class[]{KnightKit.class, BuilderKit.class, TornadoKit.class, ShotBowKit.class, MedicKit.class,
+ CleanerKit.class, PetsFriend.class, TerminatorKit.class, CrusaderKit.class, WizardKit.class};
+ for (Class> kitClass : classKitNames) {
try {
kitClass.getDeclaredConstructor().newInstance();
- } catch(Exception e) {
+ } catch (Exception e) {
getLogger().log(Level.SEVERE, "Fatal error while registering existing game kit! Report this error to the developer!");
getLogger().log(Level.SEVERE, "Cause: " + e.getMessage() + " (kitClass " + kitClass.getName() + ")");
e.printStackTrace();
@@ -162,23 +173,16 @@ public void addKits() {
getDebugger().debug("Kit adding finished took {0}ms", System.currentTimeMillis() - start);
}
+
private void addPluginMetrics() {
getMetrics().addCustomChart(new Metrics.SimplePie("hooked_addons", () -> {
- if(getServer().getPluginManager().getPlugin("VillageDefense-Enhancements") != null) {
+ if (getServer().getPluginManager().getPlugin("VillageDefense-Enhancements") != null) {
return "Enhancements";
}
return "None";
}));
}
- public FileConfiguration getEntityUpgradesConfig() {
- return entityUpgradesConfig;
- }
-
- public EnemySpawnerRegistryLegacy getEnemySpawnerRegistry() {
- return enemySpawnerRegistry;
- }
-
@Override
public ArenaRegistry getArenaRegistry() {
return arenaRegistry;
@@ -198,4 +202,5 @@ public ArenaManager getArenaManager() {
public PluginSetupCategoryManager getSetupCategoryManager(SetupInventory setupInventory) {
return new SetupCategoryManager(setupInventory);
}
+
}
diff --git a/src/main/java/plugily/projects/villagedefense/api/event/player/VillagePlayerEntityUpgradeEvent.java b/src/main/java/plugily/projects/villagedefense/api/event/player/VillagePlayerEntityUpgradeEvent.java
index b4bde5b77..a1a976106 100644
--- a/src/main/java/plugily/projects/villagedefense/api/event/player/VillagePlayerEntityUpgradeEvent.java
+++ b/src/main/java/plugily/projects/villagedefense/api/event/player/VillagePlayerEntityUpgradeEvent.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.api.event.player;
@@ -23,7 +23,7 @@
import org.bukkit.event.HandlerList;
import plugily.projects.minigamesbox.classic.api.event.PlugilyEvent;
import plugily.projects.villagedefense.arena.Arena;
-import plugily.projects.villagedefense.handlers.upgrade.upgrades.Upgrade;
+import plugily.projects.villagedefense.handlers.upgrade.EntityUpgrade;
/**
* @author Plajer
@@ -31,15 +31,16 @@
*
* Called when player upgrades an entity.
*/
+@Deprecated
public class VillagePlayerEntityUpgradeEvent extends PlugilyEvent {
private static final HandlerList HANDLERS = new HandlerList();
private final Entity entity;
private final Player player;
- private final Upgrade appliedUpgrade;
+ private final EntityUpgrade appliedUpgrade;
private final int tier;
- public VillagePlayerEntityUpgradeEvent(Arena eventArena, Entity entity, Player player, Upgrade appliedUpgrade, int tier) {
+ public VillagePlayerEntityUpgradeEvent(Arena eventArena, Entity entity, Player player, EntityUpgrade appliedUpgrade, int tier) {
super(eventArena);
this.entity = entity;
this.player = player;
@@ -63,7 +64,7 @@ public Entity getEntity() {
/**
* @return upgrade that was applied to entity
*/
- public Upgrade getAppliedUpgrade() {
+ public EntityUpgrade getAppliedUpgrade() {
return appliedUpgrade;
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/Arena.java b/src/main/java/plugily/projects/villagedefense/arena/Arena.java
index 4c8313647..c4ae4d72e 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/Arena.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/Arena.java
@@ -1,56 +1,63 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena;
+import org.bukkit.DyeColor;
import org.bukkit.Location;
+import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.Item;
+import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
+import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import plugily.projects.minigamesbox.classic.arena.ArenaState;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
-import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
+import plugily.projects.minigamesbox.classic.utils.misc.MiscUtils;
import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.assist.AssistHandler;
import plugily.projects.villagedefense.arena.managers.CreatureTargetManager;
import plugily.projects.villagedefense.arena.managers.EnemySpawnManager;
import plugily.projects.villagedefense.arena.managers.ScoreboardManager;
import plugily.projects.villagedefense.arena.managers.ShopManager;
import plugily.projects.villagedefense.arena.managers.maprestorer.MapRestorerManager;
-import plugily.projects.villagedefense.arena.managers.maprestorer.MapRestorerManagerLegacy;
+import plugily.projects.villagedefense.arena.midwave.MidWaveEvent;
import plugily.projects.villagedefense.arena.states.EndingState;
import plugily.projects.villagedefense.arena.states.InGameState;
import plugily.projects.villagedefense.arena.states.RestartingState;
import plugily.projects.villagedefense.arena.states.StartingState;
import plugily.projects.villagedefense.creatures.CreatureUtils;
+import plugily.projects.villagedefense.creatures.v1_9_UP.CustomCreature;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -66,15 +73,18 @@ public class Arena extends PluginArena {
private final List wolves = new ArrayList<>();
private final List villagers = new ArrayList<>();
private final List ironGolems = new ArrayList<>();
+ private final List specialEntities = new ArrayList<>();
private final List droppedFleshes = new ArrayList<>();
private final List spawnedEntities = new ArrayList<>();
private MapRestorerManager mapRestorerManager;
+ private MidWaveEvent midWaveEvent;
private final Map> spawnPoints = new EnumMap<>(SpawnPoint.class);
private ShopManager shopManager;
private EnemySpawnManager enemySpawnManager;
private CreatureTargetManager creatureTargetManager;
+ private AssistHandler assistHandler;
private boolean fighting = false;
@@ -84,11 +94,8 @@ public Arena(String id) {
shopManager = new ShopManager(this);
enemySpawnManager = new EnemySpawnManager(this);
creatureTargetManager = new CreatureTargetManager(this);
- if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_16_R1)) {
- mapRestorerManager = new MapRestorerManagerLegacy(this);
- } else {
- mapRestorerManager = new MapRestorerManager(this);
- }
+ mapRestorerManager = new MapRestorerManager(this);
+ assistHandler = new AssistHandler(plugin);
setMapRestorerManager(mapRestorerManager);
setScoreboardManager(new ScoreboardManager(this));
@@ -129,6 +136,10 @@ public CreatureTargetManager getCreatureTargetManager() {
return creatureTargetManager;
}
+ public AssistHandler getAssistHandler() {
+ return assistHandler;
+ }
+
public void clearVillagers() {
for(Entity entity : plugin.getBukkitHelper().getNearbyEntities(getStartLocation(), 50)) {
if(!(entity instanceof Villager)) {
@@ -234,34 +245,58 @@ public void setWave(int wave) {
public void spawnVillager(Location location) {
Villager villager = CreatureUtils.getCreatureInitializer().spawnVillager(location);
- villager.setCustomNameVisible(getPlugin().getConfigPreferences().getOption("NAME_VISIBILITY_VILLAGER"));
- villager.setCustomName(CreatureUtils.getRandomVillagerName());
+ villager.setCustomNameVisible(true);
+ String name = CreatureUtils.getRandomVillagerName();
+ villager.setMetadata(CustomCreature.CREATURE_CUSTOM_NAME_METADATA, new FixedMetadataValue(plugin, name));
+ villager.setCustomName(CreatureUtils.getHealthNameTag(villager));
+ villager.setVillagerLevel(5);
+ villager.setVillagerType(Villager.Type.values()[ThreadLocalRandom.current().nextInt(Villager.Type.values().length)]);
+ villager.setProfession(Villager.Profession.values()[ThreadLocalRandom.current().nextInt(Villager.Profession.values().length)]);
addVillager(villager);
}
- public void spawnWolf(Location location, Player player) {
+ @Nullable
+ public Creature spawnWolf(Location location, Player player) {
if(!canSpawnMobForPlayer(player, EntityType.WOLF)) {
- return;
+ return null;
}
+ return spawnWolfForce(location, player);
+ }
+ @Nullable
+ public Creature spawnWolfForce(Location location, Player player) {
Wolf wolf = CreatureUtils.getCreatureInitializer().spawnWolf(location);
+ wolf.setMetadata("VD_OWNER_UUID", new FixedMetadataValue(getPlugin(), player.getUniqueId().toString()));
+ wolf.setMetadata("VD_ALIVE_SINCE_WAVE", new FixedMetadataValue(getPlugin(), getWave()));
wolf.setOwner(player);
- wolf.setCustomNameVisible(getPlugin().getConfigPreferences().getOption("NAME_VISIBILITY_WOLF"));
- wolf.setCustomName(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_NAME").asKey().player(player).build());
+ wolf.setCustomNameVisible(true);
+ wolf.setCollarColor(DyeColor.values()[ThreadLocalRandom.current().nextInt(DyeColor.values().length)]);
+ wolf.setCustomName(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_NAME").asKey().integer(0).player(player).build());
new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_SPAWN").asKey().player(player).sendPlayer();
addWolf(wolf);
+ return wolf;
}
- public void spawnGolem(Location location, Player player) {
+ @Nullable
+ public Creature spawnGolem(Location location, Player player) {
if(!canSpawnMobForPlayer(player, EntityType.IRON_GOLEM)) {
- return;
+ return null;
}
+ return spawnGolemForce(location, player);
+ }
+ @Nullable
+ public Creature spawnGolemForce(Location location, Player player) {
IronGolem ironGolem = CreatureUtils.getCreatureInitializer().spawnGolem(location);
- ironGolem.setCustomNameVisible(getPlugin().getConfigPreferences().getOption("NAME_VISIBILITY_GOLEM"));
- ironGolem.setCustomName(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_NAME").asKey().player(player).build());
+ ironGolem.setMetadata("VD_OWNER_UUID", new FixedMetadataValue(getPlugin(), player.getUniqueId().toString()));
+ ironGolem.setMetadata("VD_ALIVE_SINCE_WAVE", new FixedMetadataValue(getPlugin(), getWave()));
+ ironGolem.setCustomNameVisible(true);
+ ironGolem.setCustomName(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_NAME").asKey().integer(0).player(player).build());
+ ironGolem.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(150.0);
new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_SPAWN").asKey().player(player).sendPlayer();
addIronGolem(ironGolem);
+ MiscUtils.getEntityAttribute(ironGolem, Attribute.GENERIC_MOVEMENT_SPEED).ifPresent(ai -> ai.setBaseValue(0.25));
+ return ironGolem;
}
protected void addWolf(Wolf wolf) {
@@ -274,60 +309,29 @@ public boolean canSpawnMobForPlayer(Player player, EntityType type) {
return false;
}
int globalEntityLimit = 0;
- int entityLimit = 0;
- String spawnedName = "";
switch(type) {
case WOLF:
- entityLimit = plugin.getPermissionsManager().getPermissionCategoryValue("PLAYER_SPAWN_LIMIT_WOLVES", player);
- spawnedName = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_NAME").asKey().player(player).build();
globalEntityLimit = plugin.getConfig().getInt("Limit.Spawn.Wolves", 20);
break;
case IRON_GOLEM:
- entityLimit = plugin.getPermissionsManager().getPermissionCategoryValue("PLAYER_SPAWN_LIMIT_GOLEMS", player);
- spawnedName = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_NAME").asKey().player(player).build();
globalEntityLimit = plugin.getConfig().getInt("Limit.Spawn.Golems", 15);
break;
default:
break;
}
- plugin.getDebugger().debug("SpawnMobCheck for {0} and mob {1}, globalLimit {2}, playerLimit {3}", player.getName(), type, globalEntityLimit, entityLimit);
- String finalSpawnedName = spawnedName;
+ plugin.getDebugger().debug("SpawnMobCheck for {0} and mob {1}, globalLimit {2}", player.getName(), type, globalEntityLimit);
List entities = new ArrayList<>(spawnedEntities);
if(plugin.getConfigPreferences().getOption("LIMIT_ENTITY_BUY_AFTER_DEATH")) {
List entityList = entities.stream().filter(entity -> entity.getType() == type).collect(Collectors.toList());
- entityList = entityList.stream().filter(Entity::isDead).collect(Collectors.toList());
+ entityList = entityList.stream().filter(en -> !en.isDead()).collect(Collectors.toList());
long spawnedAmount = entityList.size();
if(spawnedAmount >= globalEntityLimit) {
- sendMobLimitReached(player, globalEntityLimit);
- return false;
- }
-
- long spawnedPlayerAmount = entityList.stream().filter(entity -> Objects.equals(entity.getCustomName(), finalSpawnedName)).count();
- if(spawnedPlayerAmount >= entityLimit) {
- sendMobLimitReached(player, entityLimit);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_MOB_LIMIT_REACHED").asKey().player(player).integer(globalEntityLimit).sendPlayer();
return false;
}
}
- boolean finalReturn = false;
- switch(type) {
- case WOLF:
- finalReturn = entityLimit > 0 && wolves.size() < entityLimit;
- break;
- case IRON_GOLEM:
- finalReturn = entityLimit > 0 && ironGolems.size() < entityLimit;
- break;
- default:
- break;
- }
- if(!finalReturn) {
- sendMobLimitReached(player, entityLimit);
- }
- return finalReturn;
- }
-
- private void sendMobLimitReached(Player player, int entityLimit) {
- new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_MOB_LIMIT_REACHED").asKey().player(player).integer(entityLimit).sendPlayer();
+ return true;
}
/**
@@ -360,6 +364,16 @@ public List getVillagers() {
return villagers;
}
+ /**
+ * Get special alive entities.
+ *
+ * @return alive special entities
+ */
+ @NotNull
+ public List getSpecialEntities() {
+ return specialEntities;
+ }
+
public boolean checkLevelUpRottenFlesh() {
String rottenFleshLevelOption = "ROTTEN_FLESH_LEVEL";
int rottenFleshLevel = getArenaOption(rottenFleshLevelOption);
@@ -393,6 +407,14 @@ public MapRestorerManager getMapRestorerManager() {
return mapRestorerManager;
}
+ public MidWaveEvent getMidWaveEvent() {
+ return midWaveEvent;
+ }
+
+ public void setMidWaveEvent(MidWaveEvent midWaveEvent) {
+ this.midWaveEvent = midWaveEvent;
+ }
+
@NotNull
public List getZombieSpawns() {
return spawnPoints.getOrDefault(SpawnPoint.ZOMBIE, new ArrayList<>());
@@ -411,11 +433,21 @@ protected void addIronGolem(IronGolem ironGolem) {
public void removeIronGolem(IronGolem ironGolem) {
ironGolem.remove();
ironGolems.remove(ironGolem);
+ spawnedEntities.remove(ironGolem);
}
public void removeWolf(Wolf wolf) {
wolf.remove();
wolves.remove(wolf);
+ spawnedEntities.remove(wolf);
+ }
+
+ public void addSpecialEntity(LivingEntity livingEntity) {
+ specialEntities.add(livingEntity);
+ }
+
+ public void removeSpecialEntity(LivingEntity entity) {
+ specialEntities.remove(entity);
}
public enum SpawnPoint {
diff --git a/src/main/java/plugily/projects/villagedefense/arena/ArenaEvents.java b/src/main/java/plugily/projects/villagedefense/arena/ArenaEvents.java
index ba37599f8..c42bb8f9e 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/ArenaEvents.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/ArenaEvents.java
@@ -1,27 +1,30 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Creature;
+import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.LivingEntity;
@@ -33,9 +36,12 @@
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+import org.bukkit.event.entity.EntityTeleportEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
+import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import plugily.projects.minigamesbox.classic.arena.ArenaState;
@@ -46,7 +52,14 @@
import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.minigamesbox.classic.utils.version.events.api.PlugilyEntityPickupItemEvent;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.creatures.CreatureUtils;
+import plugily.projects.villagedefense.handlers.upgrade.EntityUpgrade;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
/**
* @author Plajer
@@ -63,38 +76,145 @@ public ArenaEvents(Main plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
+ @EventHandler
+ public void onWolfTeleport(EntityTeleportEvent event) {
+ if (!(event.getEntity() instanceof Wolf wolf)) {
+ return;
+ }
+ if (!wolf.hasMetadata("VD_OWNER_UUID")) {
+ return;
+ }
+ if (wolf.hasMetadata("VD_TELEPORT_OVERRIDE_TEMP")) {
+ return;
+ }
+ //is a VD entity, cancel no matter what, unless overridden
+ event.setCancelled(true);
+ }
+
+ @EventHandler
+ public void onPlayerFocusAdjust(EntityTargetLivingEntityEvent event) {
+ if (!(event.getTarget() instanceof Player)) {
+ return;
+ }
+ Player player = (Player) event.getTarget();
+ if (!plugin.getArenaRegistry().isInArena(player)) {
+ return;
+ }
+ User user = plugin.getUserManager().getUser(player);
+ //cancel targeting of spectators or being targeted by ally pets
+ if (user.isSpectator() || event.getEntity() instanceof Wolf || event.getEntity() instanceof IronGolem) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler
+ public void onAllyFocusAdjust(EntityTargetLivingEntityEvent event) {
+ if (event.getTarget() instanceof Player) {
+ //prevent ally pets targeting players
+ if (event.getEntity() instanceof Wolf || event.getEntity() instanceof IronGolem) {
+ //cancel no matter which wolf/golem targets player, naively assume it's the same arena entity
+ if (plugin.getArenaRegistry().isInArena((Player) event.getTarget())) {
+ event.setCancelled(true);
+ }
+ }
+ } else if (event.getTarget() instanceof Wolf || event.getTarget() instanceof IronGolem) {
+ //prevent ally pets targeting ally pets
+ if (event.getEntity() instanceof Wolf || event.getEntity() instanceof IronGolem) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ List allies = new ArrayList<>();
+ allies.addAll(arena.getWolves());
+ allies.addAll(arena.getIronGolems());
+ if (allies.contains(event.getEntity()) && allies.contains(event.getTarget())) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+ } else if (event.getTarget() instanceof Villager villager) {
+ //prevent ally pets targeting villagers
+ if (event.getEntity() instanceof Wolf || event.getEntity() instanceof IronGolem) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ List allies = new ArrayList<>();
+ allies.addAll(arena.getWolves());
+ allies.addAll(arena.getIronGolems());
+ if (allies.contains(event.getEntity()) && arena.getVillagers().contains(villager)) {
+ event.setCancelled(true);
+ return;
+ }
+ }
+ }
+ }
+ }
+
//override WorldGuard build deny flag where villagers cannot be damaged
@EventHandler(priority = EventPriority.HIGHEST)
public void onVillagerDamage(EntityDamageByEntityEvent e) {
- if(e.getEntityType() != EntityType.VILLAGER || !(e.getDamager() instanceof Creature)) {
+ if (e.getEntityType() != EntityType.VILLAGER || !(e.getDamager() instanceof Creature)) {
return;
}
- for(Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
- if(arena.getVillagers().contains(e.getEntity()) && arena.getEnemies().contains(e.getDamager())) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ if (arena.getVillagers().contains(e.getEntity()) && arena.getEnemies().contains(e.getDamager())) {
e.setCancelled(false);
+ e.getEntity().setCustomName(CreatureUtils.getHealthNameTagPreDamage((Creature) e.getEntity(), e.getFinalDamage()));
+ XSound.ENTITY_VILLAGER_HURT.play(e.getEntity().getLocation(), 10.0f, 1.0f);
+
+ doApplyDamageGlowingWarning(e.getDamager(), arena);
break;
}
}
}
+ private void doApplyDamageGlowingWarning(Entity target, Arena arena) {
+ String GLOWING_TARGET_METADATA = "VD_RECENT_VILLAGER_DAMAGE_GLOW";
+ target.setMetadata(GLOWING_TARGET_METADATA, new FixedMetadataValue(plugin, true));
+ new BukkitRunnable() {
+ boolean toggle = false;
+ int tick = 0;
+
+ @Override
+ public void run() {
+ if (target.isDead() || tick >= 60) {
+ try {
+ target.removeMetadata(GLOWING_TARGET_METADATA, plugin);
+ for (Player player : arena.getPlayers()) {
+ plugin.getGlowingEntities().unsetGlowing(target, player);
+ }
+ } catch (Exception ignored) {
+ }
+ cancel();
+ return;
+ }
+ try {
+ for (Player player : arena.getPlayers()) {
+ plugin.getGlowingEntities().setGlowing(target, player, toggle ? ChatColor.YELLOW : ChatColor.RED);
+ }
+ } catch (Exception ignored) {
+ }
+ toggle = !toggle;
+ tick += 10;
+ }
+ }.runTaskTimer(plugin, 0, 10);
+ }
+
+ //todo apply kills for golem by VD_OWNER_UUID detection
@EventHandler
public void onDieEntity(EntityDamageByEntityEvent e) {
- if(!(e.getDamager() instanceof Wolf && e.getEntity() instanceof Creature)) {
+ if (!(e.getDamager() instanceof Wolf && e.getEntity() instanceof Creature)) {
return;
}
- if(e.getDamage() >= ((Creature) e.getEntity()).getHealth()) {
+ if (e.getDamage() >= ((Creature) e.getEntity()).getHealth()) {
//trick to get non player killer of zombie
- for(Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
- if(arena.getEnemies().contains(e.getEntity())) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ if (arena.getEnemies().contains(e.getEntity())) {
org.bukkit.entity.AnimalTamer owner = ((Wolf) e.getDamager()).getOwner();
- if(owner instanceof Player) { //prevent offline player cast error
+ if (owner instanceof Player) { //prevent offline player cast error
Player player = (Player) owner;
- if(plugin.getArenaRegistry().getArena(player) != null) {
+ if (plugin.getArenaRegistry().getArena(player) != null) {
plugin.getUserManager().addStat(player, plugin.getStatsStorage().getStatisticType("KILLS"));
plugin.getUserManager().addExperience(player, 2 * arena.getArenaOption("ZOMBIE_DIFFICULTY_MULTIPLIER"));
}
@@ -110,16 +230,16 @@ public void onDieEntity(EntityDamageByEntityEvent e) {
public void onItemDrop(ItemSpawnEvent e) {
org.bukkit.entity.Item item = e.getEntity();
- if(item.getItemStack().getType() != Material.ROTTEN_FLESH) {
+ if (item.getItemStack().getType() != Material.ROTTEN_FLESH) {
return;
}
Location itemLoc = item.getLocation();
- for(Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
Location start = arena.getStartLocation();
- if(itemLoc.getWorld() != start.getWorld() || itemLoc.distance(start) > 150) {
+ if (itemLoc.getWorld() != start.getWorld() || itemLoc.distance(start) > 150) {
continue;
}
@@ -129,42 +249,74 @@ public void onItemDrop(ItemSpawnEvent e) {
@EventHandler
public void onEntityDamage(EntityDamageEvent event) {
- if(event.getEntityType() != EntityType.IRON_GOLEM && event.getEntityType() != EntityType.WOLF)
+ if (event.getEntityType() != EntityType.IRON_GOLEM && event.getEntityType() != EntityType.WOLF)
return;
- for(Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
- switch(event.getEntityType()) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ switch (event.getEntityType()) {
case IRON_GOLEM:
- if(!arena.getIronGolems().contains(event.getEntity())) {
+ if (!arena.getIronGolems().contains(event.getEntity())) {
continue;
}
-
IronGolem ironGolem = (IronGolem) event.getEntity();
-
- if(ironGolem.getHealth() <= event.getDamage()) {
+ if (ironGolem.getHealth() <= event.getDamage()) {
event.setCancelled(true);
event.setDamage(0);
+
+ int totalLevel = 0;
+ for (EntityUpgrade entityUpgrade : plugin.getEntityUpgradeManager().getRegisteredUpgrades()) {
+ if (entityUpgrade.getApplicableEntity() == ironGolem.getType() && ironGolem.hasMetadata(entityUpgrade.getMetadataKey())) {
+ totalLevel++;
+ }
+ }
+ UUID ownerUUID = null;
+ if (ironGolem.hasMetadata("VD_OWNER_UUID")) {
+ ownerUUID = UUID.fromString(ironGolem.getMetadata("VD_OWNER_UUID").get(0).asString());
+ }
+
+ if (ownerUUID != null) {
+ Player playerOwner = plugin.getServer().getPlayer(ownerUUID);
+
+ int totalKills = 0;
+ if (ironGolem.hasMetadata("VD_ENTITY_KILLS")) {
+ totalKills = ironGolem.getMetadata("VD_ENTITY_KILLS").get(0).asInt();
+ }
+ if (playerOwner != null)
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_DEATH").asKey().integer(totalLevel).value(String.valueOf(totalKills)).player(playerOwner).sendPlayer();
+ }
+
arena.removeIronGolem(ironGolem);
}
return;
case WOLF:
- if(!arena.getWolves().contains(event.getEntity())) {
+ if (!arena.getWolves().contains(event.getEntity())) {
continue;
}
-
Wolf wolf = (Wolf) event.getEntity();
-
- if(wolf.getHealth() <= event.getDamage()) {
+ if (wolf.getHealth() <= event.getDamage()) {
event.setCancelled(true);
event.setDamage(0);
- java.util.UUID ownerUUID = (wolf.getOwner() != null) ? wolf.getOwner().getUniqueId() : null;
+ int totalLevel = 0;
+ for (EntityUpgrade entityUpgrade : plugin.getEntityUpgradeManager().getRegisteredUpgrades()) {
+ if (entityUpgrade.getApplicableEntity() == wolf.getType() && wolf.hasMetadata(entityUpgrade.getMetadataKey())) {
+ totalLevel++;
+ }
+ }
+ UUID ownerUUID = (wolf.getOwner() != null) ? wolf.getOwner().getUniqueId() : null;
+ if (ownerUUID == null && wolf.hasMetadata("VD_OWNER_UUID")) {
+ ownerUUID = UUID.fromString(wolf.getMetadata("VD_OWNER_UUID").get(0).asString());
+ }
- if(ownerUUID != null) {
+ if (ownerUUID != null) {
Player playerOwner = plugin.getServer().getPlayer(ownerUUID);
+ int totalKills = 0;
+ if (wolf.hasMetadata("VD_ENTITY_KILLS")) {
+ totalKills = wolf.getMetadata("VD_ENTITY_KILLS").get(0).asInt();
+ }
- if(playerOwner != null)
- new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_DEATH").asKey().player(playerOwner).sendPlayer();
+ if (playerOwner != null)
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_DEATH").asKey().integer(totalLevel).value(String.valueOf(totalKills)).player(playerOwner).sendPlayer();
}
arena.removeWolf(wolf);
@@ -177,14 +329,14 @@ public void onEntityDamage(EntityDamageEvent event) {
}
@EventHandler
- public void onDieEntity(EntityDeathEvent event) {
+ public void onVillagerDeath(EntityDeathEvent event) {
LivingEntity entity = event.getEntity();
- if(!(entity instanceof Creature)) {
+ if (!(entity instanceof Creature)) {
return;
}
- for(Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
- if(event.getEntityType() == EntityType.VILLAGER) {
- if(!arena.getVillagers().contains(entity)) {
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ if (event.getEntityType() == EntityType.VILLAGER) {
+ if (!arena.getVillagers().contains(entity)) {
continue;
}
arena.getStartLocation().getWorld().strikeLightningEffect(entity.getLocation());
@@ -192,37 +344,20 @@ public void onDieEntity(EntityDeathEvent event) {
plugin.getRewardsHandler().performReward(null, arena, plugin.getRewardsHandler().getRewardType("VILLAGER_DEATH"));
plugin.getHolidayManager().applyHolidayDeathEffects(entity);
new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_DIED").asKey().arena(arena).sendArena();
- } else {
- if(!arena.getEnemies().contains(entity)) {
- continue;
- }
- arena.removeEnemy((Creature) entity);
- arena.changeArenaOptionBy("TOTAL_KILLED_ZOMBIES", 1);
-
- Player killer = entity.getKiller();
- Arena killerArena = plugin.getArenaRegistry().getArena(killer);
-
- if(killerArena != null) {
- plugin.getUserManager().addStat(killer, plugin.getStatsStorage().getStatisticType("KILLS"));
- plugin.getUserManager().addExperience(killer, 2 * arena.getArenaOption("ZOMBIE_DIFFICULTY_MULTIPLIER"));
- plugin.getRewardsHandler().performReward(killer, plugin.getRewardsHandler().getRewardType("ZOMBIE_KILL"));
- plugin.getPowerupRegistry().spawnPowerup(entity.getLocation(), killerArena);
- }
}
- break;
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerDie(PlayerDeathEvent e) {
Arena arena = plugin.getArenaRegistry().getArena(e.getEntity());
- if(arena == null) {
+ if (arena == null) {
return;
}
final Player player = e.getEntity();
- if(player.isDead()) {
+ if (player.isDead()) {
player.setHealth(VersionUtils.getMaxHealth(player));
}
plugin.getRewardsHandler().performReward(player, arena, plugin.getRewardsHandler().getRewardType("PLAYER_DEATH"));
@@ -230,14 +365,14 @@ public void onPlayerDie(PlayerDeathEvent e) {
e.getDrops().clear();
e.setDroppedExp(0);
plugin.getHolidayManager().applyHolidayDeathEffects(player);
- player.spigot().respawn();
+ Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> player.spigot().respawn(), 1);
plugin.getServer().getScheduler().runTask(plugin, () -> {
- if(arena.getArenaState() == ArenaState.STARTING) {
+ if (arena.getArenaState() == ArenaState.STARTING) {
VersionUtils.teleport(player, arena.getStartLocation());
return;
}
- if(arena.getArenaState() == ArenaState.ENDING || arena.getArenaState() == ArenaState.RESTARTING) {
+ if (arena.getArenaState() == ArenaState.ENDING || arena.getArenaState() == ArenaState.RESTARTING) {
player.getInventory().clear();
player.setFlying(false);
player.setAllowFlight(false);
@@ -273,12 +408,12 @@ private void sendSpectatorActionBar(User user, Arena arena) {
new BukkitRunnable() {
@Override
public void run() {
- if(arena.getArenaState() == ArenaState.ENDING || !user.isSpectator()) {
+ if (arena.getArenaState() == ArenaState.ENDING || !user.isSpectator()) {
cancel();
return;
}
Player player = user.getPlayer();
- if(player == null) {
+ if (player == null) {
cancel();
} else {
VersionUtils.sendActionBar(player, new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_RESPAWN_ON_NEXT").asKey().player(player).arena(arena).build());
@@ -291,14 +426,14 @@ public void run() {
@EventHandler(priority = EventPriority.HIGHEST)
public void onRespawn(PlayerRespawnEvent e) {
Arena arena = plugin.getArenaRegistry().getArena(e.getPlayer());
- if(arena == null) {
+ if (arena == null) {
return;
}
Player player = e.getPlayer();
player.setAllowFlight(true);
player.setFlying(true);
User user = plugin.getUserManager().getUser(player);
- if(!user.isSpectator()) {
+ if (!user.isSpectator()) {
user.setSpectator(true);
player.setGameMode(GameMode.SURVIVAL);
player.removePotionEffect(PotionEffectType.NIGHT_VISION);
@@ -312,7 +447,7 @@ public void onRespawn(PlayerRespawnEvent e) {
private void modifyUserOrbs(User user) {
int deathValue = plugin.getConfig().getInt("Orbs.Death.Value", 50);
int current = user.getStatistic("ORBS");
- switch(getOrbDeathType()) {
+ switch (getOrbDeathType()) {
case KEEP:
return;
case AMOUNT:
@@ -339,15 +474,15 @@ private enum OrbDeathType {
@EventHandler
public void onPickup(PlugilyEntityPickupItemEvent e) {
- if(e.getEntity().getType() != EntityType.PLAYER || e.getItem().getItemStack().getType() != Material.ROTTEN_FLESH) {
+ if (e.getEntity().getType() != EntityType.PLAYER || e.getItem().getItemStack().getType() != Material.ROTTEN_FLESH) {
return;
}
Player player = (Player) e.getEntity();
Arena arena = plugin.getArenaRegistry().getArena(player);
- if(arena == null) {
+ if (arena == null) {
return;
}
- if(plugin.getUserManager().getUser(player).isSpectator()) {
+ if (plugin.getUserManager().getUser(player).isSpectator()) {
e.setCancelled(true);
}
arena.removeDroppedFlesh(e.getItem());
diff --git a/src/main/java/plugily/projects/villagedefense/arena/ArenaManager.java b/src/main/java/plugily/projects/villagedefense/arena/ArenaManager.java
index afd40fff2..075e86b1a 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/ArenaManager.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/ArenaManager.java
@@ -1,26 +1,33 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena;
import org.bukkit.Bukkit;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.Creature;
import org.bukkit.entity.IronGolem;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Mob;
import org.bukkit.entity.Player;
+import org.bukkit.entity.Villager;
+import org.bukkit.entity.Wolf;
+import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.PluginArenaManager;
@@ -28,10 +35,24 @@
import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
import plugily.projects.minigamesbox.classic.user.User;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.villagedefense.Main;
import plugily.projects.villagedefense.api.event.wave.VillageWaveEndEvent;
import plugily.projects.villagedefense.api.event.wave.VillageWaveStartEvent;
-import plugily.projects.villagedefense.kits.level.GolemFriendKit;
+import plugily.projects.villagedefense.arena.assist.AssistHandler;
+import plugily.projects.villagedefense.arena.midwave.MidWaveEvent;
+import plugily.projects.villagedefense.arena.midwave.PinataZombieEvent;
+import plugily.projects.villagedefense.arena.midwave.RottenOfferEvent;
+import plugily.projects.villagedefense.arena.midwave.ShopOfferEvent;
+import plugily.projects.villagedefense.arena.record.RecordsManager;
+import plugily.projects.villagedefense.creatures.CreatureUtils;
+import plugily.projects.villagedefense.handlers.upgrade.EntityUpgrade;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
/**
* @author Plajer
@@ -40,11 +61,20 @@
*/
public class ArenaManager extends PluginArenaManager {
+ public static final int DEFAULT_VILLAGER_HEAL_POWER = 2;
+ public static final int DEFAULT_PET_HEAL_POWER = 3;
+
private final Main plugin;
+ private final List midWaveEvents = new ArrayList<>();
+ private final RecordsManager recordsManager;
public ArenaManager(Main plugin) {
super(plugin);
this.plugin = plugin;
+ this.midWaveEvents.add(new ShopOfferEvent(plugin));
+ this.midWaveEvents.add(new RottenOfferEvent(plugin));
+ this.midWaveEvents.add(new PinataZombieEvent(plugin));
+ this.recordsManager = new RecordsManager(plugin);
}
@Override
@@ -57,10 +87,23 @@ public void additionalSpectatorSettings(Player player, PluginArena arena) {
@Override
public void leaveAttempt(@NotNull Player player, @NotNull PluginArena arena) {
- if(plugin.getUserManager().getUser(player).getKit() instanceof GolemFriendKit) {
- ((Arena) arena).getIronGolems().stream().filter(ironGolem -> ironGolem.getCustomName().contains(player.getName()))
- .forEach(IronGolem::remove);
- }
+ player.removeMetadata(AssistHandler.ASSIST_CONTAINER_METADATA, plugin);
+ Arena gameArena = (Arena) arena;
+ List pets = new ArrayList<>();
+ pets.addAll(gameArena.getIronGolems());
+ pets.addAll(gameArena.getWolves());
+ pets
+ .stream()
+ .filter(Objects::nonNull)
+ .filter(pet -> pet.hasMetadata("VD_OWNER_UUID"))
+ .filter(pet -> UUID.fromString(pet.getMetadata("VD_OWNER_UUID").get(0).asString()).equals(player.getUniqueId()))
+ .forEach(pet -> {
+ if(pet instanceof IronGolem) {
+ gameArena.removeIronGolem((IronGolem) pet);
+ } else {
+ gameArena.removeWolf((Wolf) pet);
+ }
+ });
super.leaveAttempt(player, arena);
}
@@ -76,14 +119,30 @@ public void stopGame(boolean quickStop, @NotNull PluginArena arena) {
}
user.setStatistic("HIGHEST_WAVE", wave);
}
- if(plugin.getConfigPreferences().getOption("LIMIT_WAVE_UNLIMITED") && wave >= plugin.getConfig().getInt("Limit.Wave.Game-End", 25)) {
+ recordsManager.registerAndAnnounceRecord(player, (Arena) arena);
+ if (wave == 50) {
plugin.getUserManager().addStat(user, plugin.getStatsStorage().getStatisticType("WINS"));
+ XSound.UI_TOAST_CHALLENGE_COMPLETE.play(player, 1, 1.5f);
+ for (int i = 0; i < 5; i++) {
+ Bukkit.getScheduler().runTaskLater(plugin, () -> XSound.ENTITY_VILLAGER_YES.play(player), 10 * (i * 2));
+ }
+ XSound.ENTITY_VILLAGER_YES.play(player);
} else {
plugin.getUserManager().addStat(user, plugin.getStatsStorage().getStatisticType("LOSES"));
+ XSound.ENTITY_VILLAGER_NO.play(player);
}
plugin.getUserManager().addExperience(player, wave);
}
}
+ List allEntities = new ArrayList<>();
+ Arena gameArena = ((Arena) arena);
+ allEntities.addAll(gameArena.getEnemies());
+ allEntities.addAll(gameArena.getIronGolems());
+ allEntities.addAll(gameArena.getWolves());
+ allEntities.addAll(gameArena.getVillagers());
+ for(LivingEntity entity : allEntities) {
+ entity.setAI(false);
+ }
super.stopGame(quickStop, arena);
}
@@ -108,7 +167,9 @@ public void endWave(@NotNull Arena arena) {
if(!user.isSpectator() && !user.isPermanentSpectator()) {
Player player = user.getPlayer();
plugin.getRewardsHandler().performReward(player, arena, plugin.getRewardsHandler().getRewardType("END_WAVE"));
+ user.getKit().reStock(player);
}
+ XSound.ENTITY_VILLAGER_YES.play(user.getPlayer());
}
arena.setTimer(plugin.getConfig().getInt("Time-Manager.Cooldown-Before-Next-Wave", 25));
@@ -118,6 +179,8 @@ public void endWave(@NotNull Arena arena) {
Bukkit.getPluginManager().callEvent(new VillageWaveEndEvent(arena, arena.getWave()));
refreshAllPlayers(arena);
+ refreshAllies(arena);
+ removeAllAssists(arena);
if(plugin.getConfigPreferences().getOption("RESPAWN_AFTER_WAVE")) {
ArenaUtils.bringDeathPlayersBack(arena);
@@ -126,23 +189,129 @@ public void endWave(@NotNull Arena arena) {
for(Player player : arena.getPlayersLeft()) {
plugin.getUserManager().addExperience(player, 5);
}
+
+ doCheckNewShopOffers(arena);
+ doApplySecretUpgrades(arena);
+ prepareMidWaveEvent(arena);
+ doRetreatPets(arena);
+ }
+
+ private void doCheckNewShopOffers(Arena arena) {
+ if (!arena.getShopManager().getNewOffersAtWaves().contains(arena.getWave())) {
+ return;
+ }
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_NEW_OFFERS_AVAILABLE").asKey().arena(arena).sendArena();
+ }
+
+ private void prepareMidWaveEvent(Arena arena) {
+ for (MidWaveEvent event : midWaveEvents) {
+ //70% chance to attempt to trigger
+ if (ThreadLocalRandom.current().nextInt(0, 100) >= 30) {
+ if (!event.canTrigger(arena)) {
+ continue;
+ }
+ event.initiate(arena);
+ arena.setMidWaveEvent(event);
+ return;
+ }
+ }
+ }
+
+ private void doRetreatPets(Arena arena) {
+ List toMove = arena.getIronGolems();
+ //repeated calls so mobs don't lose focus randomly
+ for (int i = 0; i < 5; i++) {
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ for (Mob mob : toMove) {
+ mob.getPathfinder().moveTo(arena.getStartLocation(), 1.25);
+ }
+ }, i * 20);
+ }
+ for (Wolf wolf : arena.getWolves()) {
+ wolf.setMetadata("VD_TELEPORT_OVERRIDE_TEMP", new FixedMetadataValue(plugin, true));
+ wolf.teleport(arena.getStartLocation());
+ wolf.removeMetadata("VD_TELEPORT_OVERRIDE_TEMP", plugin);
+ }
+ }
+
+ private void doApplySecretUpgrades(Arena arena) {
+ List toUpgrade = new ArrayList<>();
+ toUpgrade.addAll(arena.getWolves());
+ toUpgrade.addAll(arena.getIronGolems());
+ for (LivingEntity livingEntity : toUpgrade) {
+ if (!livingEntity.hasMetadata("VD_ALIVE_SINCE_WAVE")) {
+ continue;
+ }
+ int wave = livingEntity.getMetadata("VD_ALIVE_SINCE_WAVE").get(0).asInt();
+ for (EntityUpgrade upgrade : plugin.getEntityUpgradeManager().getRegisteredUpgrades()) {
+ if (upgrade.isHidden() && upgrade.getSurviveWaves() >= arena.getWave() - wave) {
+ if (livingEntity.hasMetadata(upgrade.getMetadataKey())) {
+ break;
+ }
+ Player player = Bukkit.getPlayer(UUID.fromString(livingEntity.getMetadata("VD_OWNER_UUID").get(0).asString()));
+ plugin.getEntityUpgradeManager().applyUpgradeWithVisuals(livingEntity, player, upgrade);
+ }
+ }
+ }
}
private void refreshAllPlayers(Arena arena) {
int waveStat = arena.getWave() * 10;
- String feelRefreshed = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_FEEL_REFRESHED").asKey().build();
- String formatted = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_NEXT_IN").asKey().arena(arena).integer(arena.getTimer()).build();
-
+ String nextWave = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_NEXT_IN").asKey().arena(arena).integer(arena.getTimer()).build();
for(Player player : arena.getPlayers()) {
- player.sendMessage(formatted);
- player.sendMessage(feelRefreshed);
- player.setHealth(VersionUtils.getMaxHealth(player));
+ int healPower = (int) Math.ceil(VersionUtils.getMaxHealth(player) * 0.25); //25% of max health rounded up
+ player.sendMessage(nextWave);
+ player.setHealth(Math.min(player.getHealth() + healPower, VersionUtils.getMaxHealth(player)));
plugin.getUserManager().getUser(player).adjustStatistic(plugin.getStatsStorage().getStatisticType("ORBS"), waveStat);
}
}
+ private void refreshAllies(Arena arena) {
+ int healPower = DEFAULT_VILLAGER_HEAL_POWER; //1 heart
+ for(Villager villager : arena.getVillagers()) {
+ villager.setHealth(Math.min(villager.getHealth() + healPower, VersionUtils.getMaxHealth(villager)));
+ villager.setCustomName(CreatureUtils.getHealthNameTag(villager));
+ }
+ healPower = DEFAULT_PET_HEAL_POWER; //1.5 hearts
+ List pets = new ArrayList<>();
+ pets.addAll(arena.getWolves());
+ pets.addAll(arena.getIronGolems());
+ for(LivingEntity pet : pets) {
+ //double heal for golems
+ double multiplier = getRefreshBonus(pet);
+ pet.setHealth(Math.min(pet.getHealth() + (healPower * multiplier), VersionUtils.getMaxHealth(pet)));
+ }
+ }
+
+ private double getRefreshBonus(LivingEntity livingEntity) {
+ double defaultHeal = livingEntity instanceof IronGolem ? 2.0 : 1.0;
+ String prefix = livingEntity instanceof IronGolem ? "GOLEM_" : "WOLF_";
+ for (int i = 3; i > 0; i--) {
+ EntityUpgrade heal = plugin.getEntityUpgradeManager().getUpgrade(prefix + "HEALTH_AND_REGEN_" + i);
+ if (livingEntity.hasMetadata(heal.getMetadataKey())) {
+ defaultHeal += heal.getUpgradeData().getOrDefault("regen", 0.0);
+ break;
+ }
+ }
+ EntityUpgrade willToSurvive = plugin.getEntityUpgradeManager().getUpgrade("GOLEM_SURVIVOR");
+ if (livingEntity.hasMetadata(willToSurvive.getMetadataKey())) {
+ defaultHeal += livingEntity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue() * 0.1;
+ }
+ return defaultHeal;
+ }
+
+ private void removeAllAssists(Arena arena) {
+ List allEntities = new ArrayList<>();
+ allEntities.addAll(arena.getPlayers());
+ allEntities.addAll(arena.getWolves());
+ allEntities.addAll(arena.getIronGolems());
+ for(LivingEntity livingEntity : allEntities) {
+ livingEntity.removeMetadata(AssistHandler.ASSIST_CONTAINER_METADATA, plugin);
+ }
+ }
+
/**
* Starts wave in game.
* Calls VillageWaveStartEvent event
@@ -169,7 +338,7 @@ public void startWave(@NotNull Arena arena) {
arena.setArenaOption("ZOMBIE_DIFFICULTY_MULTIPLIER", multiplier);
plugin.getDebugger().debug("[{0}] Detected abnormal wave ({1})! Applying zombie limit and difficulty multiplier to {2} | ZombiesAmount: {3} | MaxZombies: {4}",
- arena.getId(), wave, arena.getArenaOption("ZOMBIE_DIFFICULTY_MULTIPLIER"), zombiesAmount, maxzombies);
+ arena.getId(), wave, arena.getArenaOption("ZOMBIE_DIFFICULTY_MULTIPLIER"), zombiesAmount, maxzombies);
zombiesAmount = maxzombies;
}
@@ -191,13 +360,14 @@ public void startWave(@NotNull Arena arena) {
for(User user : plugin.getUserManager().getUsers(arena)) {
Player player = user.getPlayer();
- if(!user.isSpectator()) {
- user.getKit().reStock(player);
- }
plugin.getRewardsHandler().performReward(player, arena, plugin.getRewardsHandler().getRewardType("START_WAVE"));
new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_STARTED").asKey().arena(arena).integer(wave).player(player).sendPlayer();
}
+ if (arena.getMidWaveEvent() != null) {
+ arena.getMidWaveEvent().cleanup(arena);
+ arena.setMidWaveEvent(null);
+ }
plugin.getDebugger().debug("[{0}] Wave start event finished took {1}ms", arena.getId(), System.currentTimeMillis() - start);
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/ArenaRegistry.java b/src/main/java/plugily/projects/villagedefense/arena/ArenaRegistry.java
index 09b053663..c6849e924 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/ArenaRegistry.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/ArenaRegistry.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena;
@@ -80,18 +80,15 @@ public boolean additionalValidatorChecks(ConfigurationSection section, PluginAre
}
}
- ConfigurationSection doorSection = section.getConfigurationSection(id + ".doors");
- if(doorSection != null) {
- for(String string : doorSection.getKeys(false)) {
- ((Arena) arena).getMapRestorerManager().addDoor(LocationSerializer.getLocation(doorSection.getString(string + ".location")),
- (byte) doorSection.getInt(string + ".byte"));
- }
+ List doorSection = section.getStringList(id + ".doors");
+ for(String location : doorSection) {
+ ((Arena) arena).getMapRestorerManager().addDoor(LocationSerializer.getLocation(location));
}
if(arena.getStartLocation().getWorld().getDifficulty() == Difficulty.PEACEFUL) {
plugin.getDebugger().sendConsoleMsg(new MessageBuilder("VALIDATOR_INVALID_ARENA_CONFIGURATION").asKey().value("THERE IS A WRONG " +
- "DIFFICULTY -> SET IT TO ANOTHER ONE THAN PEACEFUL - WE SET IT TO EASY").arena(arena).build());
+ "DIFFICULTY -> SET IT TO ANOTHER ONE THAN PEACEFUL - WE SET IT TO EASY").arena(arena).build());
arena.getStartLocation().getWorld().setDifficulty(Difficulty.EASY);
}
return true;
@@ -124,4 +121,5 @@ public boolean additionalValidatorChecks(ConfigurationSection section, PluginAre
}
return arenas;
}
+
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/assist/AssistContainer.java b/src/main/java/plugily/projects/villagedefense/arena/assist/AssistContainer.java
new file mode 100644
index 000000000..b461116e5
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/assist/AssistContainer.java
@@ -0,0 +1,173 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.assist;
+
+import org.bukkit.entity.LivingEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.StringJoiner;
+import java.util.UUID;
+
+/**
+ * Metadata container that includes every player
+ * that assisted in killing an enemy and their
+ * kill participation (damage/buffing the killer/other)
+ *
+ * While assists for enemies are always counted,
+ * assists for players are only counted if time_millis parameter
+ * is no more than 10 seconds from actual time.
+ *
+ * Data is stored in the following way:
+ * uuid,assist_type,value,time_millis|uuid,assist_type,value,time_millis
+ *
+ * @author Plajer
+ *
+ * Created at 29.08.2023
+ */
+public class AssistContainer {
+
+ private final List data;
+
+ public AssistContainer() {
+ this.data = new ArrayList<>();
+ }
+
+ public AssistContainer(List data) {
+ this.data = data;
+ }
+
+ public static AssistContainer deserialize(String text) {
+ if(text.isBlank()) {
+ return new AssistContainer(new ArrayList<>());
+ }
+ List assistData = new ArrayList<>();
+ String[] serialized = text.split("\\|");
+ for(String assistSerialized : serialized) {
+ String[] values = assistSerialized.split(",");
+ assistData.add(new AssistData(UUID.fromString(values[0]), AssistData.AssistType.valueOf(values[1].toUpperCase()),
+ Double.parseDouble(values[2]), Long.parseLong(values[3])));
+ }
+ return new AssistContainer(assistData);
+ }
+
+ public List getData() {
+ return data;
+ }
+
+ public void updateAssist(LivingEntity entity, AssistData.AssistType type) {
+ updateAssist(entity, type, 0);
+ }
+
+ public void updateAssist(LivingEntity entity, AssistData.AssistType type, double value) {
+ Optional optional = data.stream().filter(a -> a.getUuid().equals(entity.getUniqueId())).findFirst();
+ if(optional.isEmpty()) {
+ data.add(new AssistData(entity.getUniqueId(), type, value, System.currentTimeMillis()));
+ return;
+ }
+ AssistData assistData = optional.get();
+ //damage has the highest assist reward, override if any damage is given
+ if(assistData.getType() != type && type == AssistData.AssistType.DAMAGE) {
+ assistData.setType(type);
+ assistData.setValue(value);
+ assistData.setTimeMillis(System.currentTimeMillis());
+ return;
+ }
+ //on damage, increase total value of assist
+ if(type == AssistData.AssistType.DAMAGE) {
+ assistData.setValue(assistData.getValue() + value);
+ }
+ //update time for any type of assist be it buff or damage
+ assistData.setTimeMillis(System.currentTimeMillis());
+ }
+
+ public String serialize() {
+ StringJoiner joiner = new StringJoiner("|");
+ for(AssistData assistData : data) {
+ joiner.add(assistData.toString());
+ }
+ return joiner.toString();
+ }
+
+ public static class AssistData {
+
+ private final UUID uuid;
+ private AssistType type;
+ private double value;
+ private long timeMillis;
+
+ public AssistData(UUID uuid, AssistType type, double value, long timeMillis) {
+ this.uuid = uuid;
+ this.type = type;
+ this.value = value;
+ this.timeMillis = timeMillis;
+ }
+
+ public UUID getUuid() {
+ return uuid;
+ }
+
+ public AssistType getType() {
+ return type;
+ }
+
+ public void setType(AssistType type) {
+ this.type = type;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public void setValue(double value) {
+ this.value = value;
+ }
+
+ public long getTimeMillis() {
+ return timeMillis;
+ }
+
+ public void setTimeMillis(long timeMillis) {
+ this.timeMillis = timeMillis;
+ }
+
+ @Override
+ public String toString() {
+ return uuid.toString() + "," + type.name() + "," + value + "," + timeMillis;
+ }
+
+ public enum AssistType {
+ /**
+ * Assisting ally did damage to killed enemy
+ */
+ DAMAGE,
+ /**
+ * Assisting ally did buff ally that killed the enemy
+ */
+ BUFF,
+ /**
+ * Assisting ally did debuff enemy that was killed by ally
+ */
+ DEBUFF
+ }
+
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/assist/AssistHandler.java b/src/main/java/plugily/projects/villagedefense/arena/assist/AssistHandler.java
new file mode 100644
index 000000000..41aba3a8b
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/assist/AssistHandler.java
@@ -0,0 +1,211 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.assist;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Creature;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.IronGolem;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Wolf;
+import org.bukkit.metadata.FixedMetadataValue;
+import plugily.projects.villagedefense.Main;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Class dedicated to handle metadata for players who buff
+ * or help their allies in any other way.
+ * This class is a middleman between sharing orbs on enemy death
+ * both for the killer and all assisting players (including
+ * allies that buffed the killer)
+ *
+ * @author Plajer
+ *
+ * Created at 29.08.2023
+ */
+public class AssistHandler {
+
+ public static final String ASSIST_CONTAINER_METADATA = "VD_ASSIST_CONTAINER";
+ private Main plugin;
+
+ public AssistHandler(Main plugin) {
+ this.plugin = plugin;
+ }
+
+ public void doRegisterDamageOnEnemy(LivingEntity source, Creature target, double damage) {
+ AssistContainer container = new AssistContainer();
+ if(target.hasMetadata(ASSIST_CONTAINER_METADATA)) {
+ container = AssistContainer.deserialize(target.getMetadata(ASSIST_CONTAINER_METADATA).get(0).asString());
+ }
+ container.updateAssist(source, AssistContainer.AssistData.AssistType.DAMAGE, damage);
+ target.setMetadata(ASSIST_CONTAINER_METADATA, new FixedMetadataValue(plugin, container.serialize()));
+ }
+
+ public void doRegisterDebuffOnEnemy(LivingEntity source, Creature target) {
+ AssistContainer container = new AssistContainer();
+ if(target.hasMetadata(ASSIST_CONTAINER_METADATA)) {
+ container = AssistContainer.deserialize(target.getMetadata(ASSIST_CONTAINER_METADATA).get(0).asString());
+ }
+ container.updateAssist(source, AssistContainer.AssistData.AssistType.DEBUFF);
+ target.setMetadata(ASSIST_CONTAINER_METADATA, new FixedMetadataValue(plugin, container.serialize()));
+ }
+
+ public void doRegisterBuffOnAlly(LivingEntity source, LivingEntity target) {
+ AssistContainer container = new AssistContainer();
+ if(target.hasMetadata(ASSIST_CONTAINER_METADATA)) {
+ container = AssistContainer.deserialize(target.getMetadata(ASSIST_CONTAINER_METADATA).get(0).asString());
+ }
+ container.updateAssist(source, AssistContainer.AssistData.AssistType.BUFF);
+ target.setMetadata(ASSIST_CONTAINER_METADATA, new FixedMetadataValue(plugin, container.serialize()));
+ }
+
+ /**
+ * Distribute orb from killed enemy to all people that assisted the killer.
+ * Distribution map is a map of player and their percentage contribution.
+ *
+ * If killer is a pet, owner will receive 100% of kill participation
+ * unless the pet was assisted by any other ally.
+ *
+ * If killer is a player, player will receive 100% of kill participation
+ * unless they were assisted by any other ally.
+ *
+ * Moreover, deadEnemy is checked for any debuffs it received as well
+ * so assist is split between people that applied debuffs as well.
+ *
+ * @param killer the entity that killed deadEnemy
+ * @param deadEnemy enemy that died in the event
+ * @return map of percentage distribution of orbs given by deadEnemy
+ */
+ public Map doDistributeAssistRewards(LivingEntity killer, Creature deadEnemy) {
+ Player killerOwner = getRealKiller(killer);
+ if(killerOwner == null) {
+ plugin.getDebugger().debug("No owner of " + killer.getType() + " found, cannot distribute orb assists.");
+ return new HashMap<>();
+ }
+ Map damageDone = new LinkedHashMap<>();
+ List otherAssists = new ArrayList<>();
+ //enemy was debuffed or attacked by someone, check it
+ if(deadEnemy.hasMetadata(ASSIST_CONTAINER_METADATA)) {
+ AssistContainer debuffers = AssistContainer.deserialize(deadEnemy.getMetadata(ASSIST_CONTAINER_METADATA).get(0).asString());
+ List assistData = debuffers.getData();
+ for(AssistContainer.AssistData data : assistData) {
+ Player assister = getAssisterByUuid(data.getUuid());
+ if(assister == null || assister.equals(killerOwner)) {
+ continue;
+ }
+ //only count indirect (debuffs) or damage to the enemy
+ switch(data.getType()) {
+ case DAMAGE:
+ Entity entity = Bukkit.getEntity(data.getUuid());
+ damageDone.put(assister, data.getValue());
+ break;
+ case DEBUFF:
+ otherAssists.add(assister);
+ break;
+ }
+ }
+ }
+ //check if killer (either pet or player) has any assist buffs
+ if(killer.hasMetadata(ASSIST_CONTAINER_METADATA)) {
+ AssistContainer assisters = AssistContainer.deserialize(killer.getMetadata(ASSIST_CONTAINER_METADATA).get(0).asString());
+ List assistData = assisters.getData();
+ for(AssistContainer.AssistData data : assistData) {
+ Player assister = getAssisterByUuid(data.getUuid());
+ if(assister == null || data.getType() != AssistContainer.AssistData.AssistType.BUFF) {
+ continue;
+ }
+ //only count buffs (within 10 seconds) to the killer
+ if(System.currentTimeMillis() - data.getTimeMillis() <= 10000) {
+ otherAssists.add(assister);
+ }
+ }
+ }
+ return doDistributeMap(killerOwner, damageDone, otherAssists);
+ }
+
+ //aims to get owner of the wolf/golem or player if applicable
+ private Player getRealKiller(LivingEntity killer) {
+ Player realKiller = null;
+ if(killer instanceof Player) {
+ realKiller = (Player) killer;
+ } else if(killer instanceof Wolf || killer instanceof IronGolem && killer.hasMetadata("VD_OWNER_UUID")) {
+ realKiller = Bukkit.getPlayer(UUID.fromString(killer.getMetadata("VD_OWNER_UUID").get(0).asString()));
+ }
+ return realKiller;
+ }
+
+ //aims to get the owner of the assisting wolf/golem or player if applicable
+ private Player getAssisterByUuid(UUID uuid) {
+ Entity entity = Bukkit.getEntity(uuid);
+ if(entity == null) {
+ return null;
+ }
+ if(entity instanceof Player) {
+ return (Player) entity;
+ }
+ if(!entity.hasMetadata("VD_OWNER_UUID")) {
+ return null;
+ }
+ return Bukkit.getPlayer(UUID.fromString(entity.getMetadata("VD_OWNER_UUID").get(0).asString()));
+ }
+
+ //50% / 50% split between killer and assisters
+ //and 50% split based on damage contribution (weighted)
+ //and 50% split based on other assists (split evenly)
+ private Map doDistributeMap(Player killer, Map damage, List otherAssists) {
+ double total = 100.0;
+ Map shares = new HashMap<>();
+ double killerShare = 50.0;
+ if(damage.isEmpty() && otherAssists.isEmpty()) {
+ killerShare = 100.0;
+ }
+ shares.put(killer, killerShare);
+ double totalDamageShare = 0.0;
+ for(Map.Entry entry : damage.entrySet()) {
+ double damageDealt = 1.0;
+ if(entry.getValue() > 0) {
+ damageDealt = entry.getValue();
+ }
+ totalDamageShare += damageDealt;
+ }
+ double assistSplit = 0.5;
+ //if either is empty then assist should be shared 50/50 not 50/(25/25)
+ if(damage.isEmpty() || otherAssists.isEmpty()) {
+ assistSplit = 1.0;
+ }
+ for(Map.Entry entry : damage.entrySet()) {
+ double damageShare = (entry.getValue() / totalDamageShare) * assistSplit * (total - killerShare);
+ shares.put(entry.getKey(), damageShare);
+ }
+
+ double otherAssistsShare = assistSplit * (total - killerShare);
+ for(Player player : otherAssists) {
+ shares.put(player, otherAssistsShare / otherAssists.size());
+ }
+ return shares;
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/CreatureTargetManager.java b/src/main/java/plugily/projects/villagedefense/arena/managers/CreatureTargetManager.java
index 892bb95d3..a88c65c3b 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/CreatureTargetManager.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/CreatureTargetManager.java
@@ -1,20 +1,20 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers;
@@ -33,7 +33,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
-import java.util.Random;
/**
* @author Tigerpanzer_02
@@ -95,7 +94,7 @@ public void unTargetCreature(Creature creature) {
}
public CustomCreature getCustomCreatureFromCreature(Creature creature) {
- List metadataValueList = creature.getMetadata("PlugilyProjects-VillageDefense-Name");
+ List metadataValueList = creature.getMetadata(CustomCreature.CREATURE_ID_METADATA);
if(metadataValueList.isEmpty()) {
plugin.getDebugger().debug("Arena {0} Couldn't find creature meta data", arena.getId());
return null;
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/EnemySpawnManager.java b/src/main/java/plugily/projects/villagedefense/arena/managers/EnemySpawnManager.java
index 7442e710c..ff9ef537f 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/EnemySpawnManager.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/EnemySpawnManager.java
@@ -1,35 +1,35 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
import org.bukkit.Location;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Villager;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
import plugily.projects.villagedefense.arena.Arena;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
/**
* @author Plajer
*
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/ShopManager.java b/src/main/java/plugily/projects/villagedefense/arena/managers/ShopManager.java
index b1e754063..1a2de6093 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/ShopManager.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/ShopManager.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers;
@@ -25,20 +25,24 @@
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
+import org.bukkit.entity.Villager;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
-import org.jetbrains.annotations.NotNull;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.user.User;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
import plugily.projects.minigamesbox.classic.utils.helper.ItemUtils;
import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
import plugily.projects.minigamesbox.classic.utils.serialization.LocationSerializer;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
import plugily.projects.minigamesbox.inventory.normal.NormalFastInv;
import plugily.projects.villagedefense.Main;
import plugily.projects.villagedefense.arena.Arena;
-import java.util.function.Consumer;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
@@ -47,48 +51,38 @@
*/
public class ShopManager {
+ public static final String SHOP_OFFER_METADATA = "VD_SHOP_SPECIAL_OFFER";
+
+ private final String defaultOrbsName;
+ private final String defaultWaveLockName = "wave_lock";
private final String defaultGolemItemName;
private final String defaultWolfItemName;
+ private final String itemLockedMessage;
+ private final String specialOfferMessage;
+ private final Set newOffersAtWaves = new HashSet<>();
private final Main plugin;
private final FileConfiguration config;
private final Arena arena;
- private NormalFastInv gui;
- private Consumer openMenuConsumer;
+ private boolean shopValidated = false;
public ShopManager(Arena arena) {
plugin = arena.getPlugin();
config = ConfigUtils.getConfig(plugin, "arenas");
this.arena = arena;
+ defaultOrbsName = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_CURRENCY").asKey().build();
defaultGolemItemName = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_GOLEM_ITEM", false).asKey().build();
defaultWolfItemName = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_WOLF_ITEM", false).asKey().build();
+ itemLockedMessage = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_ITEM_LOCKED").asKey().build();
+ specialOfferMessage = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_SPECIAL_OFFER").asKey().build();
if(config.isSet("instances." + arena.getId() + ".shop")) {
- registerShop();
- }
- openMenuConsumer = player -> {
- if(plugin.getArenaRegistry().getArena(player) == null) {
- return;
+ validateShop();
+ if (shopValidated) {
+ loadShopChestWaveAnnouncements();
}
- if(gui == null) {
- new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_NOT_DEFINED").asKey().player(player).sendPlayer();
- return;
- }
- gui.open(player);
- };
- }
-
- public NormalFastInv getShop() {
- return gui;
- }
-
- public void setShop(NormalFastInv gui) {
- this.gui = gui;
- }
-
- public void setOpenMenuConsumer(@NotNull Consumer openMenuConsumer) {
- this.openMenuConsumer = openMenuConsumer;
+ }
}
/**
@@ -109,119 +103,224 @@ public String getDefaultWolfItemName() {
return defaultWolfItemName;
}
- public void openShop(Player player) {
- if(openMenuConsumer != null) {
- openMenuConsumer.accept(player);
+ public Set getNewOffersAtWaves() {
+ return newOffersAtWaves;
+ }
+
+ private void loadShopChestWaveAnnouncements() {
+ ItemStack[] contents = ((Chest) LocationSerializer.getLocation(config.getString("instances." + arena.getId() + ".shop"))
+ .getBlock().getState()).getInventory().getContents();
+ for (ItemStack itemStack : contents) {
+ if (itemStack == null || itemStack.getType() == Material.REDSTONE_BLOCK) {
+ continue;
+ }
+ ItemMeta meta = itemStack.getItemMeta();
+ //seek for wave limit
+ if (meta != null && meta.hasLore()) {
+ for (String line : ComplementAccessor.getComplement().getLore(meta)) {
+ if (line.contains(defaultWaveLockName)) {
+ newOffersAtWaves.add(parseNumberSafely(line));
+ }
+ }
+ }
}
}
- private void registerShop() {
- if(!validateShop()) {
+ public void openShop(Player player, Villager source) {
+ User user = plugin.getUserManager().getUser(player);
+ if (user == null || user.getArena() == null) {
+ return;
+ }
+ if (!shopValidated) {
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_NOT_DEFINED").asKey().player(player).sendPlayer();
return;
}
+ boolean hasSpecialOffer = source.hasMetadata(SHOP_OFFER_METADATA);
+ NormalFastInv gui = doGenerateShop(user, hasSpecialOffer);
+ gui.open(player);
+ }
+
+ private NormalFastInv doGenerateShop(User user, boolean hasSpecialOffer) {
ItemStack[] contents = ((Chest) LocationSerializer.getLocation(config.getString("instances." + arena.getId() + ".shop"))
- .getBlock().getState()).getInventory().getContents();
- gui = new NormalFastInv(plugin.getBukkitHelper().serializeInt(contents.length), new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_GUI").asKey().build());
+ .getBlock().getState()).getInventory().getContents();
+ NormalFastInv gui = new NormalFastInv(plugin.getBukkitHelper().serializeInt(contents.length), new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_GUI").asKey().build());
+ gui.getInventory().setMaxStackSize(plugin.getConfig().getInt("Limit.Wave.Game-End", 127));
gui.addClickHandler(inventoryClickEvent -> inventoryClickEvent.setCancelled(true));
for(int slot = 0; slot < contents.length; slot++) {
ItemStack itemStack = contents[slot];
if(itemStack == null || itemStack.getType() == Material.REDSTONE_BLOCK) {
continue;
}
+ //we do not want to override our real chest contents
+ itemStack = itemStack.clone();
+
+ int orbsRequired = 0;
+ int waveRequired = 0;
- String costString = "";
ItemMeta meta = itemStack.getItemMeta();
- //seek for item price
+ //seek for price or wave limit
if(meta != null && meta.hasLore()) {
- for(String s : ComplementAccessor.getComplement().getLore(meta)) {
- if(s.contains(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_CURRENCY").asKey().build()) || s.contains("orbs")) {
- costString = ChatColor.stripColor(s).replaceAll("&[0-9a-zA-Z]", "").replaceAll("[^0-9]", "");
- break;
+ for (String line : ComplementAccessor.getComplement().getLore(meta)) {
+ if (line.contains(defaultOrbsName) || line.contains("orbs")) {
+ orbsRequired = parseNumberSafely(line);
+ } else if (line.contains(defaultWaveLockName)) {
+ waveRequired = parseNumberSafely(line);
}
}
}
-
- int cost;
- try {
- cost = Integer.parseInt(costString);
- } catch(NumberFormatException e) {
- plugin.getDebugger().debug(Level.WARNING, "No price set for shop item in arena {0} skipping item!", arena.getId());
+ if (orbsRequired == -1 || waveRequired == -1) {
+ plugin.getDebugger().debug(Level.WARNING, "Invalid or no price/wave unlock value set for shop item in arena {0} skipping item!", arena.getId());
continue;
}
+ int currentWave = ((Arena) user.getArena()).getWave();
+ if (hasSpecialOffer) {
+ orbsRequired = (int) (orbsRequired - (orbsRequired * 0.1));
+ }
+ final int finalOrbs = orbsRequired;
+ final int finalWaveLimit = waveRequired;
+ if (meta != null && meta.hasLore()) {
+ List newLore = meta.getLore()
+ .stream()
+ .map(lore -> {
+ if (lore.contains(defaultWaveLockName)) {
+ lore = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_WAVE_LOCK").asKey().integer(finalWaveLimit).build();
+ }
+ if (lore.contains(defaultOrbsName) || lore.contains("orbs")) {
+ lore = ChatColor.GOLD + "" + finalOrbs + " " + defaultOrbsName;
+ }
+ return lore;
+ })
+ .collect(Collectors.toList());
+ if (hasSpecialOffer) {
+ newLore.add(specialOfferMessage);
+ }
+ ComplementAccessor.getComplement().setLore(meta, newLore);
+ if (currentWave < waveRequired) {
+ itemStack.setType(XMaterial.BARRIER.parseMaterial());
+ itemStack.setAmount(finalWaveLimit);
+ meta.setDisplayName(itemLockedMessage);
+ }
+ itemStack.setItemMeta(meta);
+ }
+ final ItemStack finalStack = itemStack;
gui.setItem(slot, itemStack, event -> {
- Player player = (Player) event.getWhoClicked();
-
- if(!arena.getPlayers().contains(player)) {
+ Player player = user.getPlayer();
+ int orbs = user.getStatistic("ORBS");
+ if (currentWave < finalWaveLimit) {
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_WAVE_STILL_LOCKED").asKey().integer(finalWaveLimit).player(player).sendPlayer();
+ XSound.ENTITY_VILLAGER_NO.play(player);
return;
}
-
- User user = plugin.getUserManager().getUser(player);
- int orbs = user.getStatistic("ORBS");
-
- if(cost > orbs) {
+ if (orbs < finalOrbs) {
new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_NOT_ENOUGH_CURRENCY").asKey().player(player).sendPlayer();
+ XSound.ENTITY_VILLAGER_NO.play(player);
return;
}
-
- if(ItemUtils.isItemStackNamed(itemStack)) {
- String name = ComplementAccessor.getComplement().getDisplayName(itemStack.getItemMeta());
+ if (ItemUtils.isItemStackNamed(finalStack)) {
+ String name = ComplementAccessor.getComplement().getDisplayName(finalStack.getItemMeta());
if(name.contains(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_GOLEM_ITEM", false).asKey().build())
- || name.contains(defaultGolemItemName)) {
+ || name.contains(defaultGolemItemName)) {
if(!arena.canSpawnMobForPlayer(player, EntityType.IRON_GOLEM)) {
+ XSound.ENTITY_VILLAGER_NO.play(player);
return;
}
arena.spawnGolem(arena.getStartLocation(), player);
- adjustOrbs(user, cost);
+ adjustOrbs(user, finalOrbs);
return;
}
if(name.contains(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_WOLF_ITEM", false).asKey().build())
- || name.contains(defaultWolfItemName)) {
+ || name.contains(defaultWolfItemName)) {
if(!arena.canSpawnMobForPlayer(player, EntityType.WOLF)) {
+ XSound.ENTITY_VILLAGER_NO.play(player);
return;
}
arena.spawnWolf(arena.getStartLocation(), player);
- adjustOrbs(user, cost);
+ adjustOrbs(user, finalOrbs);
return;
}
}
- ItemStack stack = itemStack.clone();
+ ItemStack stack = finalStack.clone();
ItemMeta itemMeta = stack.getItemMeta();
- if(itemMeta != null) {
- if(itemMeta.hasLore()) {
- ComplementAccessor.getComplement().setLore(itemMeta, ComplementAccessor.getComplement().getLore(itemMeta).stream().filter(lore ->
- !lore.contains(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_CURRENCY").asKey().build()))
- .collect(Collectors.toList()));
- }
-
+ if (itemMeta != null && itemMeta.hasLore()) {
+ List updatedLore = ComplementAccessor.getComplement()
+ .getLore(itemMeta)
+ .stream()
+ .filter(lore -> !lore.contains(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_CURRENCY").asKey().build()))
+ .filter(lore -> !lore.contains(new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_WAVE_LOCK").asKey().integer(finalWaveLimit).build()))
+ .filter(lore -> !lore.contains(specialOfferMessage))
+ .collect(Collectors.toList());
+ ComplementAccessor.getComplement().setLore(itemMeta, updatedLore);
stack.setItemMeta(itemMeta);
}
- player.getInventory().addItem(stack);
- adjustOrbs(user, cost);
+ applyOrGiveItem(player, stack);
+ adjustOrbs(user, finalOrbs);
});
}
+ return gui;
+ }
+
+ private int parseNumberSafely(String text) {
+ String stripped = ChatColor.stripColor(text).replaceAll("&[0-9a-zA-Z]", "").replaceAll("[^0-9]", "");
+ try {
+ return Integer.parseInt(stripped);
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+
+ private void applyOrGiveItem(Player player, ItemStack itemStack) {
+ Material type = itemStack.getType();
+ if (type == Material.LEATHER_HELMET || type == Material.CHAINMAIL_HELMET || type == Material.IRON_HELMET || type == Material.GOLDEN_HELMET
+ || type == Material.DIAMOND_HELMET || type == Material.NETHERITE_HELMET || type == Material.TURTLE_HELMET) {
+ player.getInventory().setHelmet(itemStack);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_AUTO_ARMOR_EQUIPPED").asKey().player(player).sendPlayer();
+ return;
+ }
+ if (type == Material.LEATHER_CHESTPLATE || type == Material.CHAINMAIL_CHESTPLATE || type == Material.IRON_CHESTPLATE || type == Material.GOLDEN_CHESTPLATE
+ || type == Material.DIAMOND_CHESTPLATE || type == Material.NETHERITE_CHESTPLATE) {
+ player.getInventory().setChestplate(itemStack);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_AUTO_ARMOR_EQUIPPED").asKey().player(player).sendPlayer();
+ return;
+ }
+ if (type == Material.LEATHER_LEGGINGS || type == Material.CHAINMAIL_LEGGINGS || type == Material.IRON_LEGGINGS || type == Material.GOLDEN_LEGGINGS
+ || type == Material.DIAMOND_LEGGINGS || type == Material.NETHERITE_LEGGINGS) {
+ player.getInventory().setLeggings(itemStack);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_AUTO_ARMOR_EQUIPPED").asKey().player(player).sendPlayer();
+ return;
+ }
+ if (type == Material.LEATHER_BOOTS || type == Material.CHAINMAIL_BOOTS || type == Material.IRON_BOOTS || type == Material.GOLDEN_BOOTS
+ || type == Material.DIAMOND_BOOTS || type == Material.NETHERITE_BOOTS) {
+ player.getInventory().setBoots(itemStack);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_SHOP_AUTO_ARMOR_EQUIPPED").asKey().player(player).sendPlayer();
+ return;
+ }
+ player.getInventory().addItem(itemStack);
}
private void adjustOrbs(User user, int cost) {
user.adjustStatistic("ORBS", -cost);
arena.changeArenaOptionBy("TOTAL_ORBS_SPENT", cost);
+ XSound.ENTITY_VILLAGER_YES.play(user.getPlayer());
}
- private boolean validateShop() {
+ private void validateShop() {
String shop = config.getString("instances." + arena.getId() + ".shop", "");
if(!shop.contains(",")) {
plugin.getDebugger().debug(Level.WARNING, "There is no shop for arena {0}! Aborting registering shop!", arena.getId());
- return false;
+ this.shopValidated = false;
+ return;
}
Location location = LocationSerializer.getLocation(shop);
if(location.getWorld() == null || !(location.getBlock().getState() instanceof Chest)) {
plugin.getDebugger().debug(Level.WARNING, "Shop failed to load, invalid location for location {0}", LocationSerializer.locationToString(location));
- return false;
+ this.shopValidated = false;
+ return;
}
- return true;
+ this.shopValidated = true;
}
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistry.java b/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistry.java
index b4462a273..79f85cc1f 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistry.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistry.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers.enemy.spawner;
@@ -23,18 +23,26 @@
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import plugily.projects.minigamesbox.classic.utils.configuration.ConfigUtils;
-import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.arena.managers.spawner.EnemySpawner;
import plugily.projects.villagedefense.creatures.v1_9_UP.CustomCreature;
import plugily.projects.villagedefense.creatures.v1_9_UP.CustomCreatureEvents;
import plugily.projects.villagedefense.creatures.v1_9_UP.CustomRideableCreature;
import plugily.projects.villagedefense.creatures.v1_9_UP.Equipment;
import plugily.projects.villagedefense.creatures.v1_9_UP.Rate;
+import plugily.projects.villagedefense.creatures.v1_9_UP.RideableCreatureEvents;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.EnumMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
+import java.util.Random;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.logging.Level;
/**
@@ -42,18 +50,20 @@
*
* Created at 01.05.2022
*/
-public class EnemySpawnerRegistry extends EnemySpawnerRegistryLegacy {
+public class EnemySpawnerRegistry {
+
private static final String CREATURES_MISSING_SECTION = "Creatures section {0} is missing! Was it manually removed?";
+ private final Set enemySpawnerSet = new TreeSet<>(Collections.reverseOrder());
+ private final Set rideableCreatures = new HashSet<>();
+ private final Main plugin;
public EnemySpawnerRegistry(Main plugin) {
- super(plugin);
+ this.plugin = plugin;
+ registerCreatures();
+ registerRideableCreatures();
}
- @Override
public void registerRideableCreatures() {
- if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_8_R3)) {
- return;
- }
FileConfiguration config = ConfigUtils.getConfig(plugin, "creatures");
ConfigurationSection village = config.getConfigurationSection("Creatures.Village");
if(village == null) {
@@ -87,9 +97,9 @@ public void registerRideableCreatures() {
}
}
- @Override
public void registerCreatures() {
new CustomCreatureEvents(plugin);
+ new RideableCreatureEvents(plugin);
FileConfiguration config = ConfigUtils.getConfig(plugin, "creatures");
ConfigurationSection content = config.getConfigurationSection("Creatures.Content");
@@ -110,10 +120,12 @@ public void registerCreatures() {
boolean explodeTarget = content.getBoolean(creature + ".explosive_hit", false);
+ String name = content.getString(creature + ".name", "Zombie");
String key = creature.toUpperCase();
EntityType entityType = EntityType.valueOf(content.getString(creature + ".entity_type", "ZOMBIE").toUpperCase());
+ boolean doorBulldozing = content.getBoolean(creature + ".door_bulldozing", false);
boolean baby = content.getBoolean(creature + ".baby", false);
boolean breed = content.getBoolean(creature + ".breed", false);
int age = content.getInt(creature + ".age", 0);
@@ -176,9 +188,71 @@ public void registerCreatures() {
dropItem = XMaterial.matchXMaterial(item).orElse(XMaterial.BEDROCK).parseItem();
}
plugin.getDebugger().debug("Registered CustomCreature named {0}", key);
- enemySpawnerSet.add(new CustomCreature(plugin, waveMin, waveMax, priorityTarget, explodeTarget, key, entityType, baby, breed, age, ageLook, expDrop, holidayEffects, rates, attributes, equipments, dropItem));
+ enemySpawnerSet.add(new CustomCreature(plugin, name, waveMin, waveMax, priorityTarget, explodeTarget, key, entityType, doorBulldozing, baby, breed, age, ageLook, expDrop, holidayEffects, rates, attributes, equipments, dropItem));
+ }
+ }
+
+ /**
+ * Spawn the enemies at the arena
+ *
+ * @param random the random instance
+ * @param arena the arena
+ */
+ public void spawnEnemies(Random random, Arena arena) {
+ int spawn = arena.getWave();
+ int zombiesLimit = plugin.getConfig().getInt("Limit.Spawn.Creatures", 75);
+ if(zombiesLimit < spawn) {
+ spawn = (int) Math.ceil(zombiesLimit / 2.0);
+ }
+ String zombieSpawnCounterOption = "ZOMBIE_SPAWN_COUNTER";
+ arena.changeArenaOptionBy(zombieSpawnCounterOption, 1);
+ if(arena.getArenaOption(zombieSpawnCounterOption) == 20) {
+ arena.setArenaOption(zombieSpawnCounterOption, 0);
+ }
+
+ List enemySpawners = new ArrayList<>(enemySpawnerSet);
+ Collections.shuffle(enemySpawners);
+ for(EnemySpawner enemySpawner : enemySpawners) {
+ plugin.getDebugger().debug("Trying enemy spawn for " + enemySpawner.getName());
+ enemySpawner.spawn(random, arena, spawn);
}
+ }
+
+ /**
+ * Get the set of enemy spawners
+ *
+ * @return the set of enemy spawners
+ */
+ public Set getEnemySpawnerSet() {
+ return enemySpawnerSet;
+ }
+
+ public Set getRideableCreatures() {
+ return rideableCreatures;
+ }
+
+ /**
+ * Get the rideable creature by its type
+ *
+ * @param type the tyoe
+ * @return the rideable creature
+ */
+ public Optional getRideableCreatureByName(CustomRideableCreature.RideableType type) {
+ return rideableCreatures.stream()
+ .filter(creature -> creature.getRideableType().equals(type))
+ .findFirst();
+ }
+ /**
+ * Get the enemy spawner by its name
+ *
+ * @param name the name
+ * @return the enemy spawner
+ */
+ public Optional getSpawnerByName(String name) {
+ return enemySpawnerSet.stream()
+ .filter(enemySpawner -> enemySpawner.getName().equals(name))
+ .findFirst();
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistryLegacy.java b/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistryLegacy.java
deleted file mode 100644
index 5da57293d..000000000
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/enemy/spawner/EnemySpawnerRegistryLegacy.java
+++ /dev/null
@@ -1,145 +0,0 @@
-
-/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package plugily.projects.villagedefense.arena.managers.enemy.spawner;
-
-import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
-import plugily.projects.villagedefense.Main;
-import plugily.projects.villagedefense.arena.Arena;
-import plugily.projects.villagedefense.arena.managers.spawner.EnemySpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.BabyZombieSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.FastZombieSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.GolemBusterSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.HalfInvisibleZombieSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.HardZombieSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.KnockbackResistantZombieSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.PlayerBusterSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.SoftHardZombieSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.VillagerBusterSpawner;
-import plugily.projects.villagedefense.creatures.v1_8_R3.spawner.VillagerSlayerSpawner;
-import plugily.projects.villagedefense.creatures.v1_9_UP.CustomRideableCreature;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Random;
-import java.util.Set;
-import java.util.TreeSet;
-
-/**
- * The registry for all {@link EnemySpawner}
- */
-public class EnemySpawnerRegistryLegacy {
- final Set enemySpawnerSet = new TreeSet<>(Collections.reverseOrder());
- final Set rideableCreatures = new HashSet<>();
- final Main plugin;
-
- public EnemySpawnerRegistryLegacy(Main plugin) {
- this.plugin = plugin;
- registerCreatures();
- registerRideableCreatures();
- }
-
- public void registerRideableCreatures() {
- if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_8_R3)) {
- return;
- }
- }
-
- public void registerCreatures() {
- if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_8_R3)) {
- enemySpawnerSet.add(new BabyZombieSpawner());
- enemySpawnerSet.add(new FastZombieSpawner());
- enemySpawnerSet.add(new GolemBusterSpawner());
- enemySpawnerSet.add(new HalfInvisibleZombieSpawner());
- enemySpawnerSet.add(new HardZombieSpawner());
- enemySpawnerSet.add(new KnockbackResistantZombieSpawner());
- enemySpawnerSet.add(new PlayerBusterSpawner());
- enemySpawnerSet.add(new SoftHardZombieSpawner());
- enemySpawnerSet.add(new VillagerBusterSpawner());
- enemySpawnerSet.add(new VillagerSlayerSpawner());
- return;
- }
- }
-
- /**
- * Spawn the enemies at the arena
- *
- * @param random the random instance
- * @param arena the arena
- */
- public void spawnEnemies(Random random, Arena arena) {
- int spawn = arena.getWave();
- int zombiesLimit = plugin.getConfig().getInt("Limit.Spawn.Creatures", 75);
- if(zombiesLimit < spawn) {
- spawn = (int) Math.ceil(zombiesLimit / 2.0);
- }
- String zombieSpawnCounterOption = "ZOMBIE_SPAWN_COUNTER";
- arena.changeArenaOptionBy(zombieSpawnCounterOption, 1);
- if(arena.getArenaOption(zombieSpawnCounterOption) == 20) {
- arena.setArenaOption(zombieSpawnCounterOption, 0);
- }
-
- List enemySpawners = new ArrayList<>(enemySpawnerSet);
- Collections.shuffle(enemySpawners);
- for(EnemySpawner enemySpawner : enemySpawners) {
- plugin.getDebugger().debug("Trying enemy spawn for " + enemySpawner.getName());
- enemySpawner.spawn(random, arena, spawn);
- }
- }
-
- /**
- * Get the set of enemy spawners
- *
- * @return the set of enemy spawners
- */
- public Set getEnemySpawnerSet() {
- return enemySpawnerSet;
- }
-
- public Set getRideableCreatures() {
- return rideableCreatures;
- }
-
- /**
- * Get the rideable creature by its type
- *
- * @param type the tyoe
- * @return the rideable creature
- */
- public Optional getRideableCreatureByName(CustomRideableCreature.RideableType type) {
- return rideableCreatures.stream()
- .filter(creature -> creature.getRideableType().equals(type))
- .findFirst();
- }
-
- /**
- * Get the enemy spawner by its name
- *
- * @param name the name
- * @return the enemy spawner
- */
- public Optional getSpawnerByName(String name) {
- return enemySpawnerSet.stream()
- .filter(enemySpawner -> enemySpawner.getName().equals(name))
- .findFirst();
- }
-}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManager.java b/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManager.java
index 889733911..a9a2c1fb3 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManager.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManager.java
@@ -1,26 +1,28 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers.maprestorer;
import org.bukkit.Location;
+import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -28,33 +30,34 @@
import plugily.projects.minigamesbox.classic.arena.managers.PluginMapRestorerManager;
import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.creatures.DoorBreakListener;
import plugily.projects.villagedefense.utils.Utils;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
import java.util.logging.Level;
/**
- * @author Plajer
+ * @author Tigerpanzer_02
*
- * Created at 14.02.2019
+ * Created at 13.01.2021
*/
@SuppressWarnings("deprecation")
public class MapRestorerManager extends PluginMapRestorerManager {
- protected final Map doorBlocks = new LinkedHashMap<>();
- public final Arena arena;
+ private final List doorBlocks = new ArrayList<>();
+ private final Arena arena;
public MapRestorerManager(Arena arena) {
super(arena);
this.arena = arena;
}
- public final void addDoor(Location location, byte data) {
- doorBlocks.put(location, data);
+ public final void addDoor(Location location) {
+ doorBlocks.add(location);
}
- public final Map getGameDoorLocations() {
+ public final List getGameDoorLocations() {
return doorBlocks;
}
@@ -101,21 +104,22 @@ public final void clearWolvesFromArena() {
public void restoreDoors() {
int i = 0;
- for(Map.Entry entry : doorBlocks.entrySet()) {
- Block block = entry.getKey().getBlock();
- Byte doorData = entry.getValue();
+ for(Location location : doorBlocks) {
+ Block block = location.getBlock();
try {
if(block.getType() != XMaterial.AIR.parseMaterial()) {
i++;
continue;
}
- if(doorData == (byte) 8) {
- restoreTopHalfDoorPart(block);
- i++;
- continue;
+ Block relative = block.getRelative(BlockFace.DOWN).getLocation().getBlock();
+ boolean isAirBelow = relative.getType().equals(XMaterial.AIR.parseMaterial());
+ boolean relativeTopHalf = false;
+ if(!isAirBelow) {
+ relative = block.getRelative(BlockFace.UP).getLocation().getBlock();
+ relativeTopHalf = true;
}
- restoreBottomHalfDoorPart(block, doorData);
- i++;
+ restoreDoorPart(block, !relativeTopHalf);
+ restoreDoorPart(relative, relativeTopHalf);
} catch(Exception ex) {
arena.getPlugin().getDebugger().debug(Level.WARNING, "Door has failed to load for arena {0} message {1} type {2} skipping!", arena.getId(), ex.getMessage(), ex.getCause());
}
@@ -125,32 +129,36 @@ public void restoreDoors() {
}
}
- public void restoreTopHalfDoorPart(Block block) {
- block.setType(Utils.getCachedDoor(block));
- BlockState doorBlockState = block.getState();
- Door doorBlockData = new Door(TreeSpecies.GENERIC, arena.getPlugin().getBukkitHelper().getFacingByByte((byte) 8));
-
- doorBlockData.setTopHalf(true);
- doorBlockData.setFacingDirection(doorBlockData.getFacing());
-
- doorBlockState.setType(doorBlockData.getItemType());
- doorBlockState.setData(doorBlockData);
-
- doorBlockState.update(true);
- }
+ public void restoreDoorPart(Block block, boolean topHalf) {
+ byte doorByte;
+ if(topHalf) {
+ doorByte = 8;
+ } else {
+ doorByte = 1;
+ }
- public void restoreBottomHalfDoorPart(Block block, byte doorData) {
block.setType(Utils.getCachedDoor(block));
- BlockState doorBlockState = block.getState();
- Door doorBlockData = new Door(TreeSpecies.GENERIC, arena.getPlugin().getBukkitHelper().getFacingByByte(doorData));
-
- doorBlockData.setTopHalf(false);
- doorBlockData.setFacingDirection(doorBlockData.getFacing());
-
- doorBlockState.setType(doorBlockData.getItemType());
- doorBlockState.setData(doorBlockData);
-
- doorBlockState.update(true);
+ Door doorData = null;
+ try {
+ doorData = new Door(TreeSpecies.GENERIC, arena.getPlugin().getBukkitHelper().getFacingByByte(doorByte));
+ } catch(NoSuchMethodError e) {
+ try {
+ doorData = Door.class.getDeclaredConstructor(Material.class, byte.class).newInstance(XMaterial.OAK_DOOR.parseMaterial(), doorByte);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ if(doorData == null) {
+ return;
+ }
+ BlockState state = block.getState();
+ doorData.setTopHalf(topHalf);
+ doorData.setFacingDirection(doorData.getFacing());
+ state.setType(doorData.getItemType());
+ state.setData(doorData);
+ state.update(true);
+
+ block.removeMetadata(DoorBreakListener.CREATURE_DOOR_BULLDOZER_METADATA, arena.getPlugin());
}
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManagerLegacy.java b/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManagerLegacy.java
deleted file mode 100644
index f5ab3be34..000000000
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/maprestorer/MapRestorerManagerLegacy.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package plugily.projects.villagedefense.arena.managers.maprestorer;
-
-import java.util.Map;
-import java.util.logging.Level;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.TreeSpecies;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockState;
-import org.bukkit.material.Door;
-import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
-import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
-import plugily.projects.villagedefense.arena.Arena;
-import plugily.projects.villagedefense.utils.Utils;
-
-/**
- * @author Tigerpanzer_02
- *
- * Created at 13.01.2021
- */
-@SuppressWarnings("deprecation")
-public class MapRestorerManagerLegacy extends MapRestorerManager {
-
- public MapRestorerManagerLegacy(Arena arena) {
- super(arena);
- }
-
- @Override
- public void restoreDoors() {
- int i = 0;
- for(Map.Entry entry : doorBlocks.entrySet()) {
- Block block = entry.getKey().getBlock();
- Byte doorData = entry.getValue();
- if(ServerVersion.Version.isCurrentEqualOrLower(ServerVersion.Version.v1_11_R1) && block.getType() != org.bukkit.Material.AIR) {
- Material mat = Utils.getCachedDoor(block);
- try {
- int id = (int) mat.getClass().getDeclaredMethod("getId").invoke(mat);
- block.getClass().getDeclaredMethod("setTypeIdAndData", int.class, byte.class, boolean.class)
- .invoke(block, id, doorData, false);
- } catch(Exception e) {
- e.printStackTrace();
- }
- i++;
- } else {
- try {
- if(block.getType() != XMaterial.AIR.parseMaterial()) {
- i++;
- continue;
- }
- if(doorData == (byte) 8) {
- restoreTopHalfDoorPart(block);
- i++;
- continue;
- }
- restoreBottomHalfDoorPart(block, doorData);
- i++;
- } catch(Exception ex) {
- arena.getPlugin().getDebugger().debug(Level.WARNING, "Door has failed to load for arena {0} message {1} type {2} skipping!", arena.getId(), ex.getMessage(), ex.getCause());
- }
- }
- }
- if(i != doorBlocks.size()) {
- arena.getPlugin().getDebugger().debug(Level.WARNING, "Failed to load doors for {0}! Expected {1} got {2}", arena.getId(), doorBlocks.size(), i);
- }
- }
-
- @Override
- public void restoreTopHalfDoorPart(Block block) {
- block.setType(Utils.getCachedDoor(block));
-
- Door doorBlockData = null;
- try {
- doorBlockData = new Door(TreeSpecies.GENERIC, arena.getPlugin().getBukkitHelper().getFacingByByte((byte) 8));
- } catch (NoSuchMethodError e) {
- try {
- doorBlockData = Door.class.getDeclaredConstructor(Material.class, byte.class)
- .newInstance(XMaterial.OAK_DOOR, arena.getPlugin().getBukkitHelper().getFacingByByte((byte) 8));
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
- if (doorBlockData == null)
- return;
-
- BlockState doorBlockState = block.getState();
-
- doorBlockData.setTopHalf(true);
- doorBlockData.setFacingDirection(doorBlockData.getFacing());
- doorBlockState.setType(doorBlockData.getItemType());
- doorBlockState.setData(doorBlockData);
- doorBlockState.update(true);
- }
-
- @Override
- public void restoreBottomHalfDoorPart(Block block, byte doorData) {
- block.setType(Utils.getCachedDoor(block));
-
- Door doorBlockData = null;
- try {
- doorBlockData = new Door(TreeSpecies.GENERIC, arena.getPlugin().getBukkitHelper().getFacingByByte(doorData));
- } catch (NoSuchMethodError e) {
- try {
- doorBlockData = Door.class.getDeclaredConstructor(Material.class, byte.class)
- .newInstance(XMaterial.OAK_DOOR.parseMaterial(), arena.getPlugin().getBukkitHelper().getFacingByByte(doorData));
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
- if (doorBlockData == null)
- return;
-
- BlockState doorBlockState = block.getState();
-
- doorBlockData.setTopHalf(false);
- doorBlockData.setFacingDirection(doorBlockData.getFacing());
- doorBlockState.setType(doorBlockData.getItemType());
- doorBlockState.setData(doorBlockData);
- doorBlockState.update(true);
- }
-
-}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/EnemySpawner.java b/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/EnemySpawner.java
index 18a2c9abd..c80551f56 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/EnemySpawner.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/EnemySpawner.java
@@ -1,29 +1,29 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers.spawner;
-import java.util.Random;
-
import org.bukkit.inventory.ItemStack;
import plugily.projects.villagedefense.arena.Arena;
+import java.util.Random;
+
/**
* The interface for enemy spawner
*/
@@ -53,8 +53,8 @@ default int getPriority() {
/**
* Get the defined itemstack for drop reasons
- * does NOT work on 1.8.8 or lower
- * @return ItemStack that gets dropped on enemey death
+ *
+ * @return ItemStack that gets dropped on enemy death
*/
ItemStack getDropItem();
diff --git a/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/SimpleEnemySpawner.java b/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/SimpleEnemySpawner.java
index 34e60807d..604ea9138 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/SimpleEnemySpawner.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/managers/spawner/SimpleEnemySpawner.java
@@ -1,20 +1,20 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.managers.spawner;
@@ -134,6 +134,9 @@ default void spawn(Location location, Arena arena) {
if(creature == null) {
return;
}
+ //2 seconds of invulnerability to avoid suffocation problem
+ creature.setMaximumNoDamageTicks(45);
+ creature.setNoDamageTicks(40);
if(canApplyAttributes()) {
CreatureUtils.applyAttributes(creature, arena);
}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/midwave/MidWaveEvent.java b/src/main/java/plugily/projects/villagedefense/arena/midwave/MidWaveEvent.java
new file mode 100644
index 000000000..7c9d6ba44
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/midwave/MidWaveEvent.java
@@ -0,0 +1,31 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.midwave;
+
+import plugily.projects.villagedefense.arena.Arena;
+
+public interface MidWaveEvent {
+
+ boolean canTrigger(Arena arena);
+
+ void initiate(Arena arena);
+
+ void cleanup(Arena arena);
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/midwave/PinataZombieEvent.java b/src/main/java/plugily/projects/villagedefense/arena/midwave/PinataZombieEvent.java
new file mode 100644
index 000000000..6da7771d0
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/midwave/PinataZombieEvent.java
@@ -0,0 +1,211 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.midwave;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.Particle;
+import org.bukkit.Sound;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.Ageable;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Item;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.ZombieVillager;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.Vector;
+import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
+import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+public class PinataZombieEvent implements MidWaveEvent, Listener {
+
+ public static final String PINATA_METADATA = "VD_PINATA_EVENT";
+ private final Main plugin;
+
+ public PinataZombieEvent(Main plugin) {
+ this.plugin = plugin;
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @Override
+ public boolean canTrigger(Arena arena) {
+ return arena.getWave() % 11 == 0;
+ }
+
+ @Override
+ public void initiate(Arena arena) {
+ LivingEntity target = (LivingEntity) arena.getStartLocation().getWorld().spawnEntity(arena.getStartLocation(), EntityType.ZOMBIE_VILLAGER);
+ target.setGlowing(true);
+ target.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.1);
+ target.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(100.0);
+ ((Ageable) target).setAdult();
+ target.setMetadata(PINATA_METADATA, new FixedMetadataValue(plugin, true));
+
+ ArmorStandHologram hologram = new ArmorStandHologram(target.getLocation().add(0, 0.25, 0),
+ ChatColor.translateAlternateColorCodes('&', "&e&lPUNCH ME"));
+ new BukkitRunnable() {
+ boolean toggle = false;
+ int ticks = 0;
+ int color = 0;
+
+ @Override
+ public void run() {
+ if (!target.hasMetadata(PINATA_METADATA) || target.isDead()) {
+ hologram.delete();
+ target.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation().clone().add(0, 0.5, 0), 1);
+ target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ZOMBIE_INFECT, 1, 0.5f);
+ for (int i = 0; i < 8; i++) {
+ dropNaturalItem(hologram.getLocation(), XMaterial.ROTTEN_FLESH.parseItem());
+ }
+ target.remove();
+ cancel();
+ return;
+ }
+ ArmorStand stand = hologram.getArmorStands().get(0);
+ stand.teleport(target.getLocation().add(0, 0.25, 0));
+ if (ticks % 5 == 0) {
+ for (Player player : arena.getPlayers()) {
+ try {
+ plugin.getGlowingEntities().setGlowing(target, player, getNextColor(color));
+ } catch (Exception ignored) {
+ }
+ color = (color + 1) % 7;
+ }
+ }
+ if (ticks % 10 == 0) {
+ String message;
+ if (toggle) {
+ message = ChatColor.translateAlternateColorCodes('&', "&c&lPUNCH ME");
+ } else {
+ message = ChatColor.translateAlternateColorCodes('&', "&e&lPUNCH ME");
+ }
+ toggle = !toggle;
+ stand.setCustomName(message);
+ }
+ ticks++;
+ }
+ }.runTaskTimer(plugin, 0, 1);
+ arena.getSpecialEntities().add(target);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_PINATA_EVENT")
+ .asKey()
+ .arena(arena)
+ .sendArena();
+ for (Player player : arena.getPlayers()) {
+ player.playSound(player, Sound.ENTITY_ZOMBIE_VILLAGER_CURE, 0.5f, 2f);
+ }
+ }
+
+ @Override
+ public void cleanup(Arena arena) {
+ for (LivingEntity livingEntity : arena.getSpecialEntities()) {
+ if (livingEntity.hasMetadata(PINATA_METADATA)) {
+ livingEntity.removeMetadata(PINATA_METADATA, plugin);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPinataFocus(EntityTargetLivingEntityEvent event) {
+ if (!(event.getTarget() instanceof ZombieVillager)) {
+ return;
+ }
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ if (!arena.getSpecialEntities().contains(event.getTarget())) {
+ continue;
+ }
+ if (!event.getTarget().hasMetadata(PINATA_METADATA)) {
+ continue;
+ }
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler
+ public void onPinataDamage(EntityDamageByEntityEvent event) {
+ //cancel all pinata damages
+ if (event.getDamager().hasMetadata(PINATA_METADATA)) {
+ event.setCancelled(true);
+ }
+ //drop rewards on pinata punch
+ if (event.getDamager() instanceof Player player && event.getEntity().hasMetadata(PINATA_METADATA)) {
+ if (!plugin.getArenaRegistry().isInArena(player)) {
+ return;
+ }
+ Vector velocity = event.getEntity().getLocation().getDirection().multiply(-1).normalize().multiply(2.0);
+ event.getEntity().setVelocity(velocity);
+ //60% chance of drop
+ if (ThreadLocalRandom.current().nextInt(0, 100) >= 40) {
+ doCustomDrop(player, event.getDamager().getLocation());
+ }
+ event.setDamage(1.0);
+ }
+ }
+
+ private void dropNaturalItem(Location location, ItemStack itemStack) {
+ Item item = location.getWorld().dropItemNaturally(location.clone().add(0, 0.5, 0), itemStack);
+ item.setInvulnerable(true);
+ item.setPickupDelay(Integer.MAX_VALUE);
+ item.setGravity(true);
+ item.setCustomNameVisible(false);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> item.remove(), 15);
+ }
+
+ private ChatColor getNextColor(int color) {
+ return switch (color) {
+ case 0 -> ChatColor.WHITE;
+ case 1 -> ChatColor.RED;
+ case 2 -> ChatColor.GOLD;
+ case 3 -> ChatColor.DARK_RED;
+ case 4 -> ChatColor.BLUE;
+ case 5 -> ChatColor.GREEN;
+ case 6 -> ChatColor.DARK_PURPLE;
+ default -> ChatColor.BLACK;
+ };
+ }
+
+ private void doCustomDrop(Player player, Location location) {
+ if (ThreadLocalRandom.current().nextBoolean()) {
+ int rand = ThreadLocalRandom.current().nextInt(4, 12);
+ plugin.getUserManager().getUser(player).adjustStatistic(plugin.getStatsStorage().getStatisticType("ORBS"), rand);
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&a+" + rand + " &7orbs"));
+ } else {
+ int amount = ThreadLocalRandom.current().nextInt(1, 3);
+ for (int i = 0; i < amount; i++) {
+ dropNaturalItem(location, XMaterial.ROTTEN_FLESH.parseItem());
+ }
+ player.getInventory().addItem(new ItemStack(Material.ROTTEN_FLESH, amount));
+ }
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/midwave/RottenOfferEvent.java b/src/main/java/plugily/projects/villagedefense/arena/midwave/RottenOfferEvent.java
new file mode 100644
index 000000000..000ec86de
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/midwave/RottenOfferEvent.java
@@ -0,0 +1,154 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.midwave;
+
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.Particle;
+import org.bukkit.Sound;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.scheduler.BukkitRunnable;
+import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
+import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
+import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.creatures.CreatureUtils;
+import plugily.projects.villagedefense.creatures.v1_9_UP.CustomCreature;
+
+import java.util.Map;
+
+public class RottenOfferEvent implements MidWaveEvent, Listener {
+
+ public static final String ROTTEN_SALE_METADATA = "VD_TRADER_ROTTEN_SALE";
+ private final Main plugin;
+
+ public RottenOfferEvent(Main plugin) {
+ this.plugin = plugin;
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @Override
+ public boolean canTrigger(Arena arena) {
+ return arena.getWave() % 7 == 0;
+ }
+
+ @Override
+ public void initiate(Arena arena) {
+ LivingEntity target = (LivingEntity) arena.getStartLocation().getWorld().spawnEntity(arena.getStartLocation(), EntityType.WANDERING_TRADER);
+ String name = CreatureUtils.getRandomVillagerName();
+ target.setCustomName(name);
+ target.setCustomNameVisible(true);
+ target.setMetadata(CustomCreature.CREATURE_CUSTOM_NAME_METADATA, new FixedMetadataValue(plugin, name));
+ target.getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(1.0);
+ target.setGlowing(true);
+
+ String offerMessage = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_ROTTEN_OFFER").asKey().build();
+ ArmorStandHologram hologram = new ArmorStandHologram(target.getLocation().add(0, 0.25, 0), offerMessage);
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ if (!target.hasMetadata(ROTTEN_SALE_METADATA)) {
+ hologram.delete();
+ target.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation().clone().add(0, 0.5, 0), 1);
+ target.getWorld().playSound(target.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1, .5f);
+ target.remove();
+ cancel();
+ return;
+ }
+ ArmorStand stand = hologram.getArmorStands().get(0);
+ stand.teleport(target.getLocation().add(0, 0.25, 0));
+ }
+ }.runTaskTimer(plugin, 0, 1);
+ target.setMetadata(ROTTEN_SALE_METADATA, new FixedMetadataValue(plugin, true));
+ arena.addSpecialEntity(target);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_ROTTEN_SALE")
+ .asKey()
+ .value(ChatColor.translateAlternateColorCodes('&', "&c&lROTTEN FLESH"))
+ .arena(arena)
+ .sendArena();
+ for (Player player : arena.getPlayers()) {
+ player.playSound(player, Sound.ENTITY_WANDERING_TRADER_TRADE, 1, 1.15f);
+ }
+ }
+
+ @Override
+ public void cleanup(Arena arena) {
+ for (LivingEntity livingEntity : arena.getSpecialEntities()) {
+ if (livingEntity.hasMetadata(ROTTEN_SALE_METADATA)) {
+ livingEntity.removeMetadata(ROTTEN_SALE_METADATA, plugin);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onTraderDamage(EntityDamageByEntityEvent event) {
+ if (!event.getEntity().hasMetadata(ROTTEN_SALE_METADATA)) {
+ return;
+ }
+ //cancel no matter what
+ event.setCancelled(true);
+ }
+
+ @EventHandler
+ public void onInteract(PlayerInteractEntityEvent event) {
+ if (!event.getRightClicked().hasMetadata(ROTTEN_SALE_METADATA)) {
+ return;
+ }
+ Player player = event.getPlayer();
+ if (!plugin.getArenaRegistry().isInArena(player)) {
+ return;
+ }
+ event.setCancelled(true);
+ if (!player.getInventory().contains(Material.ROTTEN_FLESH)) {
+ player.playSound(player, Sound.ENTITY_WANDERING_TRADER_NO, 1, 1);
+ return;
+ }
+ int count = 0;
+ for (Map.Entry entry : player.getInventory().all(Material.ROTTEN_FLESH).entrySet()) {
+ count += entry.getValue().getAmount();
+ }
+ player.getInventory().remove(Material.ROTTEN_FLESH);
+ Arena arena = plugin.getArenaRegistry().getArena(player);
+ arena.changeArenaOptionBy("ROTTEN_FLESH_AMOUNT", count);
+ int orbs = (int) (count * 1.45);
+ plugin.getUserManager().getUser(player).adjustStatistic(plugin.getStatsStorage().getStatisticType("ORBS"), orbs);
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&a+" + orbs + " &7orbs"));
+ player.playSound(player, Sound.ENTITY_WANDERING_TRADER_TRADE, 1, 1);
+ if (!arena.checkLevelUpRottenFlesh() || arena.getArenaOption("ROTTEN_FLESH_LEVEL") >= 30) {
+ return;
+ }
+ for (Player arenaPlayer : arena.getPlayers()) {
+ arenaPlayer.setHealth(VersionUtils.getMaxHealth(player));
+ VersionUtils.setMaxHealth(player, VersionUtils.getMaxHealth(player) + 2.0);
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_ROTTEN_FLESH_LEVEL_UP").asKey().player(arenaPlayer).sendPlayer();
+ }
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/midwave/ShopOfferEvent.java b/src/main/java/plugily/projects/villagedefense/arena/midwave/ShopOfferEvent.java
new file mode 100644
index 000000000..4964aabd8
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/midwave/ShopOfferEvent.java
@@ -0,0 +1,94 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.midwave;
+
+import org.bukkit.Sound;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Villager;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.scheduler.BukkitRunnable;
+import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
+import plugily.projects.minigamesbox.classic.utils.hologram.ArmorStandHologram;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.arena.managers.ShopManager;
+import plugily.projects.villagedefense.creatures.v1_9_UP.CustomCreature;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
+
+public class ShopOfferEvent implements MidWaveEvent {
+
+ private final Main plugin;
+
+ public ShopOfferEvent(Main plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public boolean canTrigger(Arena arena) {
+ return arena.getWave() % 5 == 0;
+ }
+
+ @Override
+ public void initiate(Arena arena) {
+ List list = arena.getVillagers()
+ .stream()
+ .filter(v -> !v.isDead())
+ .collect(Collectors.toList());
+ Villager target = list.get(ThreadLocalRandom.current().nextInt(list.size()));
+ target.setGlowing(true);
+
+ String offerMessage = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_SPECIAL_OFFER").asKey().build();
+ ArmorStandHologram hologram = new ArmorStandHologram(target.getLocation().add(0, 0.25, 0), offerMessage);
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ if (!target.hasMetadata(ShopManager.SHOP_OFFER_METADATA)) {
+ hologram.delete();
+ cancel();
+ return;
+ }
+ ArmorStand stand = hologram.getArmorStands().get(0);
+ stand.teleport(target.getLocation().add(0, 0.25, 0));
+ }
+ }.runTaskTimer(plugin, 0, 1);
+ target.setMetadata(ShopManager.SHOP_OFFER_METADATA, new FixedMetadataValue(plugin, true));
+ new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_OFFERING_SALE")
+ .asKey()
+ .value(target.getMetadata(CustomCreature.CREATURE_CUSTOM_NAME_METADATA).get(0).asString())
+ .arena(arena)
+ .sendArena();
+ for (Player player : arena.getPlayers()) {
+ player.playSound(player, Sound.ENTITY_VILLAGER_TRADE, 1, 1.15f);
+ }
+ }
+
+ @Override
+ public void cleanup(Arena arena) {
+ for (Villager villager : arena.getVillagers()) {
+ if (villager.hasMetadata(ShopManager.SHOP_OFFER_METADATA)) {
+ villager.setGlowing(false);
+ villager.removeMetadata(ShopManager.SHOP_OFFER_METADATA, plugin);
+ }
+ }
+ }
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/powerup/IronDeliveryPowerup.java b/src/main/java/plugily/projects/villagedefense/arena/powerup/IronDeliveryPowerup.java
new file mode 100644
index 000000000..60c8c7ce9
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/powerup/IronDeliveryPowerup.java
@@ -0,0 +1,199 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.powerup;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.Sound;
+import org.bukkit.World;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Creature;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.IronGolem;
+import org.bukkit.entity.Item;
+import org.bukkit.metadata.FixedMetadataValue;
+import org.bukkit.scheduler.BukkitRunnable;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XParticle;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.handlers.hologram.ArmorStandHologram;
+import plugily.projects.villagedefense.handlers.upgrade.NewEntityUpgradeManager;
+import plugily.projects.villagedefense.kits.utils.KitSpecifications;
+
+public class IronDeliveryPowerup implements Powerup {
+
+ private final Main plugin;
+
+ public IronDeliveryPowerup(Main plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public boolean canSpawn(Arena arena) {
+ return arena.getWave() >= 5;
+ }
+
+ @Override
+ public void spawn(Arena arena, Location location) {
+ ArmorStandHologram hologram = new ArmorStandHologram(location.clone().add(0, -1.35, 0))
+ .appendItem(XMaterial.IRON_BLOCK.parseItem())
+ .appendLine(ChatColor.translateAlternateColorCodes('&', "&e&lIRON DELIVERY"));
+
+ hologram.setPickupHandler(player -> {
+ if (!plugin.getArenaRegistry().getArena(player).equals(arena)) {
+ return;
+ }
+ XSound.ENTITY_PLAYER_LEVELUP.play(player, 1, 0);
+ XSound.ENTITY_IRON_GOLEM_DEATH.play(arena.getStartLocation(), 1, 0);
+ int count;
+ KitSpecifications.GameTimeState state = KitSpecifications.getTimeState(arena);
+ if (state == KitSpecifications.GameTimeState.EARLY) {
+ count = 1;
+ } else if (state == KitSpecifications.GameTimeState.MID) {
+ count = 2;
+ } else {
+ count = 3;
+ }
+ for (int i = 0; i < count; i++) {
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ XSound.ENTITY_IRON_GOLEM_REPAIR.play(arena.getStartLocation(), 1, 1.25f);
+ Creature golem = arena.spawnGolemForce(arena.getStartLocation(), player);
+ if (golem == null) {
+ return;
+ }
+ golem.setMetadata(NewEntityUpgradeManager.UPGRADES_DISABLED_METADATA, new FixedMetadataValue(plugin, true));
+ NewEntityUpgradeManager upgradeManager = plugin.getEntityUpgradeManager();
+ upgradeManager.getRegisteredUpgrades()
+ .stream()
+ .filter(u -> u.getApplicableEntity() == EntityType.IRON_GOLEM)
+ .forEach(upgrade -> upgradeManager.applyUpgradeSilent(golem, player, upgrade));
+ ArmorStandHologram golemHologram = new ArmorStandHologram(golem.getLocation())
+ .appendLine(ChatColor.translateAlternateColorCodes('&', "&e&lIRON DELIVERY"));
+ golem.getWorld().playSound(golem.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 0.5f);
+
+ new BukkitRunnable() {
+ int tick = 0;
+ boolean toggle = false;
+
+ @Override
+ public void run() {
+ if (tick == 400 || golemHologram.isDeleted() || golemHologram.getArmorStands().isEmpty()) {
+ World world = golem.getLocation().getWorld();
+ world.spawnParticle(Particle.EXPLOSION_LARGE, golem.getLocation().clone().add(0, 0.5, 0), 1);
+ world.playSound(golem.getLocation(), Sound.ENTITY_ENDERMAN_TELEPORT, 1, 0.5f);
+ arena.removeIronGolem((IronGolem) golem);
+ golemHologram.delete();
+ cancel();
+ return;
+ }
+ ArmorStand stand = golemHologram.getArmorStands().get(0);
+ stand.teleport(golem.getLocation().clone().add(0, 1.1, 0));
+ //postpone countdown until wave starts but still teleport moving holograms
+ if (!arena.isFighting()) {
+ return;
+ }
+ int modulo = tick < 100 ? 10 : tick > 350 ? 3 : 5;
+ if (tick % modulo == 0) {
+ String message;
+ if (toggle) {
+ message = ChatColor.translateAlternateColorCodes('&', "&c&lIRON DELIVERY (" + ((400 - tick) / 20) + "s)");
+ } else {
+ message = ChatColor.translateAlternateColorCodes('&', "&e&lIRON DELIVERY (" + ((400 - tick) / 20) + "s)");
+ }
+ toggle = !toggle;
+ stand.setCustomName(message);
+ }
+ tick++;
+ }
+ }.runTaskTimer(plugin, 1, 1);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ if (!golemHologram.isDeleted()) {
+ golemHologram.delete();
+ }
+ }, /* remove after 40 seconds to prevent staying even if arena is finished */ 20 * 40);
+ }, 15 * (i + 1));
+ }
+ hologram.delete();
+ });
+
+ new BukkitRunnable() {
+ boolean toggle = true;
+ boolean grounded = false;
+ boolean flyReverse = false;
+ int tick = 0;
+
+ @Override
+ public void run() {
+ if (tick == 200 || hologram.isDeleted() || hologram.getArmorStands().isEmpty()) {
+ hologram.getLocation().getWorld().spawnParticle(XParticle.getParticle("EXPLOSION_HUGE"), hologram.getLocation(), 1);
+ hologram.delete();
+ cancel();
+ return;
+ }
+ if (hologram.getEntityItem().isOnGround() && !grounded) {
+ grounded = true;
+ hologram.getEntityItem().setGravity(false);
+ hologram.getEntityItem().teleport(hologram.getEntityItem().getLocation().add(0, 0.75, 0));
+ }
+ if (grounded) {
+ hologram.getEntityItem().setGravity(true);
+ Location newLocation = hologram.getEntityItem().getLocation().clone().add(0, 0.015 * (flyReverse ? -1 : 1), 0);
+ hologram.getEntityItem().teleport(newLocation);
+ hologram.getEntityItem().setGravity(false);
+ if (tick % 60 == 0) {
+ flyReverse = !flyReverse;
+ }
+ }
+ ArmorStand stand = hologram.getArmorStands().get(0);
+ int modulo = tick < 100 ? 10 : tick > 150 ? 3 : 5;
+ if (tick % modulo == 0) {
+ String message;
+ if (toggle) {
+ message = ChatColor.translateAlternateColorCodes('&', "&c&lIRON DELIVERY (" + ((200 - tick) / 20) + "s)");
+ } else {
+ message = ChatColor.translateAlternateColorCodes('&', "&e&lIRON DELIVERY (" + ((200 - tick) / 20) + "s)");
+ }
+ toggle = !toggle;
+ stand.setCustomName(message);
+ }
+ if (tick % 10 == 0) {
+ for (int i = 0; i < 2; i++) {
+ Item item = hologram.getLocation().getWorld().dropItemNaturally(stand.getLocation().clone().add(0, 0.5, 0), XMaterial.IRON_INGOT.parseItem());
+ item.setInvulnerable(true);
+ item.setPickupDelay(Integer.MAX_VALUE);
+ item.setGravity(true);
+ item.setCustomNameVisible(false);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> item.remove(), 15);
+ }
+ }
+ stand.teleport(hologram.getEntityItem().getLocation().clone().add(0, -1.25, 0));
+ tick++;
+ }
+ }.runTaskTimer(plugin, 1, 1);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ if (!hologram.isDeleted()) {
+ hologram.delete();
+ }
+ }, /* remove after 40 seconds to prevent staying even if arena is finished */ 20 * 40);
+ }
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/powerup/MoneyPouchPowerup.java b/src/main/java/plugily/projects/villagedefense/arena/powerup/MoneyPouchPowerup.java
new file mode 100644
index 000000000..2ab91eef8
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/powerup/MoneyPouchPowerup.java
@@ -0,0 +1,163 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.powerup;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Item;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.handlers.hologram.ArmorStandHologram;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class MoneyPouchPowerup implements Powerup {
+
+ private final List goldBlocks = Arrays.asList(XMaterial.GOLD_NUGGET.parseItem(), XMaterial.GOLD_INGOT.parseItem());
+ private final Random random = new Random();
+ private final Main plugin;
+
+ public MoneyPouchPowerup(Main plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public boolean canSpawn(Arena arena) {
+ return true;
+ }
+
+ @Override
+ public void spawn(Arena arena, Location location) {
+ ArmorStandHologram hologram = new ArmorStandHologram(location.clone().add(0, -1.35, 0))
+ .appendItem(XMaterial.GOLD_BLOCK.parseItem())
+ .appendLines(ChatColor.translateAlternateColorCodes('&', "&e&lMONEY POUCH"))
+ .appendLines(ChatColor.translateAlternateColorCodes('&', "&7Click me!"));
+
+ AtomicInteger pouchHits = new AtomicInteger(10);
+ hologram.setTouchHandler(player -> {
+ if (!plugin.getArenaRegistry().getArena(player).equals(arena)) {
+ return;
+ }
+ XSound.BLOCK_LAVA_POP.play(player);
+ Item item = hologram.getLocation().getWorld().dropItemNaturally(hologram.getLocation(), goldBlocks.get(random.nextInt(goldBlocks.size())));
+ item.setInvulnerable(true);
+ item.setPickupDelay(Integer.MAX_VALUE);
+ item.setGravity(true);
+ item.setCustomNameVisible(false);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> item.remove(), 15);
+ int rand = random.nextInt(3, 15);
+ plugin.getUserManager().getUser(player).adjustStatistic(plugin.getStatsStorage().getStatisticType("ORBS"), rand);
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&a+" + rand + " &7orbs"));
+ int hits = pouchHits.decrementAndGet();
+ if (hits <= 0) {
+ hologram.delete();
+ }
+ });
+
+ new BukkitRunnable() {
+ boolean toggle = true;
+ boolean grounded = false;
+ boolean flyReverse = false;
+ boolean soundPlayed = false;
+ int tick = 0;
+
+ @Override
+ public void run() {
+ Item entityItem = hologram.getEntityItem();
+ if (tick == 190) {
+ XSound.BLOCK_ANVIL_DESTROY.play(hologram.getLocation(), 1, 1.25f);
+ soundPlayed = true;
+ }
+ if (tick == 200 || hologram.isDeleted() || hologram.getArmorStands().isEmpty()) {
+ if (!soundPlayed) {
+ XSound.BLOCK_ANVIL_DESTROY.play(hologram.getLocation(), 1, 1.25f);
+ }
+ for (int i = 0; i < 12; i++) {
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ Item item = hologram.getLocation().getWorld().dropItemNaturally(entityItem.getLocation(), goldBlocks.get(random.nextInt(goldBlocks.size())));
+ item.setVelocity(item.getVelocity().multiply(random.nextDouble(1.0, 1.5)));
+ item.setInvulnerable(true);
+ item.setPickupDelay(Integer.MAX_VALUE);
+ item.setGravity(true);
+ item.setCustomNameVisible(false);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> item.remove(), 15);
+ }, random.nextInt(1, 10));
+ }
+ hologram.delete();
+ cancel();
+ return;
+ }
+ if (hologram.getEntityItem().isOnGround() && !grounded) {
+ grounded = true;
+ entityItem.setGravity(false);
+ entityItem.teleport(hologram.getEntityItem().getLocation().add(0, 0.75, 0));
+ }
+ if (grounded) {
+ entityItem.setGravity(true);
+ Location newLocation = hologram.getEntityItem().getLocation().clone().add(0, 0.015 * (flyReverse ? -1 : 1), 0);
+ entityItem.teleport(newLocation);
+ entityItem.setGravity(false);
+ if (tick % 60 == 0) {
+ flyReverse = !flyReverse;
+ }
+ }
+ ArmorStand stand = hologram.getArmorStands().get(0);
+ int modulo = tick < 100 ? 10 : tick > 150 ? 3 : 5;
+ if (tick % modulo == 0) {
+ String message;
+ if (toggle) {
+ message = ChatColor.translateAlternateColorCodes('&', "&c&lMONEY POUCH (" + ((200 - tick) / 20) + "s)");
+ } else {
+ message = ChatColor.translateAlternateColorCodes('&', "&e&lMONEY POUCH (" + ((200 - tick) / 20) + "s)");
+ }
+ toggle = !toggle;
+ stand.setCustomName(message);
+ }
+ if (tick % 10 == 0) {
+ for (int i = 0; i < 2; i++) {
+ Item item = hologram.getLocation().getWorld().dropItemNaturally(stand.getLocation().clone().add(0, 0.5, 0), goldBlocks.get(random.nextInt(goldBlocks.size())));
+ item.setInvulnerable(true);
+ item.setPickupDelay(Integer.MAX_VALUE);
+ item.setGravity(true);
+ item.setCustomNameVisible(false);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> item.remove(), 15);
+ }
+ }
+ stand.teleport(entityItem.getLocation().clone().add(0, -1.25 + 0.27, 0));
+ hologram.getArmorStands().get(1).teleport(entityItem.getLocation().clone().add(0, -1.25, 0));
+ tick++;
+ }
+ }.runTaskTimer(plugin, 1, 1);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ if (!hologram.isDeleted()) {
+ hologram.delete();
+ }
+ }, /* remove after 40 seconds to prevent staying even if arena is finished */ 20 * 40);
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/powerup/Powerup.java b/src/main/java/plugily/projects/villagedefense/arena/powerup/Powerup.java
new file mode 100644
index 000000000..3c4fba50a
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/powerup/Powerup.java
@@ -0,0 +1,30 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.powerup;
+
+import org.bukkit.Location;
+import plugily.projects.villagedefense.arena.Arena;
+
+public interface Powerup {
+
+ boolean canSpawn(Arena arena);
+
+ void spawn(Arena arena, Location location);
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/powerup/PowerupEvents.java b/src/main/java/plugily/projects/villagedefense/arena/powerup/PowerupEvents.java
new file mode 100644
index 000000000..8381f7b48
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/powerup/PowerupEvents.java
@@ -0,0 +1,68 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.powerup;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDeathEvent;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.creatures.CreatureUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * @author Plajer
+ *
+ * Created at 06.10.2023
+ */
+public class PowerupEvents implements Listener {
+
+ private final List powerups = new ArrayList<>();
+ private final Random random = new Random();
+ private Main plugin;
+
+ public PowerupEvents(Main plugin) {
+ this.plugin = plugin;
+ powerups.add(new IronDeliveryPowerup(plugin));
+ powerups.add(new MoneyPouchPowerup(plugin));
+ powerups.add(new RandomPowerup(plugin));
+ plugin.getServer().getPluginManager().registerEvents(this, plugin);
+ }
+
+ @EventHandler
+ public void onPowerupDrop(EntityDeathEvent event) {
+ if (!CreatureUtils.isEnemy(event.getEntity())) {
+ return;
+ }
+ for (Arena arena : plugin.getArenaRegistry().getPluginArenas()) {
+ if (!arena.getEnemies().contains(event.getEntity())) {
+ continue;
+ }
+ if (ThreadLocalRandom.current().nextDouble(0.0, 100.0) <= 1.5) {
+ powerups.get(random.nextInt(powerups.size())).spawn(arena, event.getEntity().getLocation().clone().add(0, 0.1, 0));
+ }
+ }
+ }
+
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/powerup/RandomPowerup.java b/src/main/java/plugily/projects/villagedefense/arena/powerup/RandomPowerup.java
new file mode 100644
index 000000000..0900fb6d7
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/powerup/RandomPowerup.java
@@ -0,0 +1,237 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.powerup;
+
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Creature;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Villager;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.scheduler.BukkitRunnable;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XMaterial;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XParticle;
+import plugily.projects.minigamesbox.classic.utils.version.xseries.XSound;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.creatures.CreatureUtils;
+import plugily.projects.villagedefense.handlers.hologram.ArmorStandHologram;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiConsumer;
+
+public class RandomPowerup implements Powerup {
+
+ private final List localPowerups = new ArrayList<>();
+ private final Main plugin;
+
+ public RandomPowerup(Main plugin) {
+ this.plugin = plugin;
+ registerLocalPowerups();
+ }
+
+ private void registerLocalPowerups() {
+ String powerupMessage = color("&7You received %name%&7 powerup from %player%!");
+ localPowerups.add(new LocalRandomPowerup(
+ color("&e&lREJUVENATION"),
+ color("&7Heal and absorption for 5s for you and your pets!"),
+ (arena, player) -> {
+ for (Player target : arena.getPlayersLeft()) {
+ target.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 20 * 5, 0));
+ target.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 20 * 5, 0));
+ if (!target.equals(player)) {
+ player.sendMessage(powerupMessage.replace("%name%", color("&e&lREJUVENATION")).replace("%player%", player.getName()));
+ }
+ }
+ List pets = new ArrayList<>();
+ pets.addAll(arena.getWolves());
+ pets.addAll(arena.getIronGolems());
+ for (LivingEntity pet : pets) {
+ pet.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 20 * 5, 0));
+ pet.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 20 * 5, 0));
+ }
+ }
+ ));
+ localPowerups.add(new LocalRandomPowerup(
+ color("&b&lSWIFTNESS"),
+ color("&7Speed boost for 5s for you and your pets!"),
+ (arena, player) -> {
+ for (Player target : arena.getPlayersLeft()) {
+ target.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 20 * 5, 0));
+ if (!target.equals(player)) {
+ player.sendMessage(powerupMessage.replace("%name%", color("&b&lSWIFTNESS")).replace("%player%", player.getName()));
+ }
+ }
+ List pets = new ArrayList<>();
+ pets.addAll(arena.getWolves());
+ pets.addAll(arena.getIronGolems());
+ for (LivingEntity pet : pets) {
+ pet.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 20 * 5, 0));
+ pet.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 20 * 5, 0));
+ }
+ }
+ ));
+ localPowerups.add(new LocalRandomPowerup(
+ color("&d&lTIME STOP"),
+ color("&7Alive enemies are frozen in time for 3 seconds!"),
+ (arena, player) -> {
+ for (Creature creature : arena.getEnemies()) {
+ CreatureUtils.doStunEnemy(creature, 3);
+ }
+ }
+ ));
+ localPowerups.add(new LocalRandomPowerup(
+ color("&6&lJACKPOT"),
+ color("&7You won jackpot prize of 300 orbs!"),
+ (arena, player) -> {
+ int orbs = 300;
+ plugin.getUserManager().getUser(player).adjustStatistic(plugin.getStatsStorage().getStatisticType("ORBS"), orbs);
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&a+" + orbs + " &7orbs"));
+ }
+ ));
+ //todo test divine barrier
+ localPowerups.add(new LocalRandomPowerup(
+ color("&f&lDIVINE BARRIER"),
+ color("&7Villagers are protected from damage for 10s!"),
+ (arena, player) -> {
+ for (Villager villager : arena.getVillagers()) {
+ villager.setNoDamageTicks(20 * 10);
+ for (Player target : arena.getPlayers()) {
+ try {
+ plugin.getGlowingEntities().setGlowing(villager, target, ChatColor.YELLOW);
+ } catch (ReflectiveOperationException ignored) {
+ }
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ try {
+ plugin.getGlowingEntities().unsetGlowing(villager, target);
+ } catch (ReflectiveOperationException ignored) {
+ }
+ }, 20 * 10);
+ }
+ }
+ }
+ ));
+ }
+
+ private String color(String text) {
+ return ChatColor.translateAlternateColorCodes('&', text);
+ }
+
+ @Override
+ public boolean canSpawn(Arena arena) {
+ return true;
+ }
+
+ @Override
+ public void spawn(Arena arena, Location location) {
+ ArmorStandHologram hologram = new ArmorStandHologram(location.clone().add(0, -1.5, 0))
+ .appendItem(XMaterial.BLAZE_POWDER.parseItem())
+ .appendLine(ChatColor.translateAlternateColorCodes('&', "&e&lPOWERUP"));
+ hologram.setPickupHandler(player -> {
+ if (!plugin.getArenaRegistry().getArena(player).equals(arena)) {
+ return;
+ }
+ XSound.ENTITY_PLAYER_LEVELUP.play(player, 1, 0);
+ XSound.ENTITY_VILLAGER_YES.play(player);
+ hologram.delete();
+ onPickup(arena, player);
+ });
+ List materials = Arrays.asList(XMaterial.BLAZE_POWDER.parseItem(), XMaterial.COCOA_BEANS.parseItem(), XMaterial.ANVIL.parseItem(), XMaterial.NETHER_STAR.parseItem());
+
+ new BukkitRunnable() {
+ boolean toggle = true;
+ boolean grounded = false;
+ boolean flyReverse = false;
+ int tick = 0;
+ int index = 0;
+
+ @Override
+ public void run() {
+ if (tick == 200 || hologram.isDeleted() || hologram.getArmorStands().isEmpty()) {
+ hologram.getLocation().getWorld().spawnParticle(XParticle.getParticle("EXPLOSION_HUGE"), hologram.getLocation(), 1);
+ hologram.delete();
+ cancel();
+ return;
+ }
+ if (hologram.getEntityItem().isOnGround() && !grounded) {
+ grounded = true;
+ hologram.getEntityItem().setGravity(false);
+ hologram.getEntityItem().teleport(hologram.getEntityItem().getLocation().add(0, 0.75, 0));
+ }
+ if (grounded) {
+ hologram.getEntityItem().setGravity(true);
+ Location newLocation = hologram.getEntityItem().getLocation().clone().add(0, 0.015 * (flyReverse ? -1 : 1), 0);
+ hologram.getEntityItem().teleport(newLocation);
+ hologram.getEntityItem().setGravity(false);
+ if (tick % 60 == 0) {
+ flyReverse = !flyReverse;
+ }
+ }
+ ArmorStand stand = hologram.getArmorStands().get(0);
+ int modulo = tick < 100 ? 10 : tick > 150 ? 3 : 5;
+ if (tick % modulo == 0) {
+ String message;
+ if (toggle) {
+ message = ChatColor.translateAlternateColorCodes('&', "&c&lRANDOM POWERUP (" + ((200 - tick) / 20) + "s)");
+ } else {
+ message = ChatColor.translateAlternateColorCodes('&', "&e&lRANDOM POWERUP (" + ((200 - tick) / 20) + "s)");
+ }
+ toggle = !toggle;
+ stand.setCustomName(message);
+ }
+ if (tick % 10 == 0) {
+ hologram.getEntityItem().setItemStack(materials.get(index));
+ index++;
+ if (index >= materials.size()) {
+ index = 0;
+ }
+
+ stand.getLocation().getWorld().spawnParticle(XParticle.getParticle("LAVA"), hologram.getEntityItem().getLocation(), 2);
+ }
+ stand.teleport(hologram.getEntityItem().getLocation().clone().add(0, -1.25, 0));
+ tick++;
+ }
+ }.runTaskTimer(plugin, 1, 1);
+ Bukkit.getScheduler().runTaskLater(plugin, () -> {
+ if (!hologram.isDeleted()) {
+ hologram.delete();
+ }
+ }, /* remove after 40 seconds to prevent staying even if arena is finished */ 20 * 40);
+ }
+
+ private void onPickup(Arena arena, Player player) {
+ Collections.shuffle(localPowerups);
+ for (LocalRandomPowerup powerup : localPowerups) {
+ powerup.onPickup().accept(arena, player);
+ break;
+ }
+ }
+
+ private record LocalRandomPowerup(String name, String description, BiConsumer onPickup) {
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/record/RecordsManager.java b/src/main/java/plugily/projects/villagedefense/arena/record/RecordsManager.java
new file mode 100644
index 000000000..71375a480
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/arena/record/RecordsManager.java
@@ -0,0 +1,75 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.arena.record;
+
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
+import plugily.projects.minigamesbox.classic.kits.basekits.Kit;
+import plugily.projects.villagedefense.Main;
+import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.user.VDUser;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Handles creation of users records on particular maps
+ */
+//todo records announce on game end
+//todo record per map placeholder (papi)
+public class RecordsManager {
+
+ private final Main plugin;
+
+ public RecordsManager(Main plugin) {
+ this.plugin = plugin;
+ }
+
+ /**
+ * Attempts to register survived gameplay wave as a player record if possible.
+ * If new record is made an announcement is sent to the player.
+ */
+ public void registerAndAnnounceRecord(Player player, Arena arena) {
+ Kit kit = plugin.getUserManager().getUser(player).getKit();
+ VDUser vdUser = plugin.getVdUserManager().getUser(player);
+ List records = vdUser.getGameplayRecords()
+ .getOrDefault(arena.getMapName(), new ArrayList<>())
+ .stream()
+ .filter(record -> record.getMapId().equals(arena.getMapName()))
+ .collect(Collectors.toList());
+ VDUser.GameplayRecord newRecord = new VDUser.GameplayRecord(arena.getMapName(), kit.getName(), arena.getWave());
+ records.add(newRecord);
+ List updatedRecords = records
+ .stream()
+ .sorted(Comparator.comparing(VDUser.GameplayRecord::getWave).reversed())
+ .limit(3)
+ .collect(Collectors.toList());
+ vdUser.getGameplayRecords().put(arena.getMapName(), updatedRecords);
+ if (!updatedRecords.contains(newRecord)) {
+ return;
+ }
+ player.playSound(player, Sound.ENTITY_VILLAGER_YES, 1, 1);
+ player.playSound(player, Sound.ENTITY_PLAYER_LEVELUP, 1, 1.25f);
+ new MessageBuilder("VD_GOLD_NEW_RECORD_REACHED").asKey().player(player).value(kit.getName()).sendPlayer();
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/arena/states/InGameState.java b/src/main/java/plugily/projects/villagedefense/arena/states/InGameState.java
index a2d5bb5f3..190e8818f 100644
--- a/src/main/java/plugily/projects/villagedefense/arena/states/InGameState.java
+++ b/src/main/java/plugily/projects/villagedefense/arena/states/InGameState.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.arena.states;
@@ -22,6 +22,8 @@
import plugily.projects.minigamesbox.classic.arena.PluginArena;
import plugily.projects.minigamesbox.classic.arena.states.PluginInGameState;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
+import plugily.projects.minigamesbox.classic.handlers.language.TitleBuilder;
+import plugily.projects.minigamesbox.classic.utils.helper.SoundHelper;
import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.villagedefense.arena.Arena;
@@ -48,10 +50,8 @@ public void handleCall(PluginArena arena) {
int zombiesLeft = pluginArena.getZombiesLeft();
getPlugin().getDebugger().debug("Arena {0} Zombies to spawn {1} Zombies left {2} Fighting {3}", arena.getId(), arena.getArenaOption("ZOMBIES_TO_SPAWN"), zombiesLeft, pluginArena.isFighting());
if(pluginArena.isFighting()) {
- if(ServerVersion.Version.isCurrentHigher(ServerVersion.Version.v1_8_R3)) {
- pluginArena.getCreatureTargetManager().targetCreatures();
- pluginArena.getCreatureTargetManager().targetRideableCreatures();
- }
+ pluginArena.getCreatureTargetManager().targetCreatures();
+ pluginArena.getCreatureTargetManager().targetRideableCreatures();
if(zombiesLeft <= 0) {
pluginArena.setFighting(false);
pluginArena.getPlugin().getArenaManager().endWave(pluginArena);
@@ -63,8 +63,8 @@ public void handleCall(PluginArena arena) {
int zombiesLeftFrom = getPlugin().getConfig().getInt("Glowing-Status.Creatures-Left");
int startingWave;
if(zombiesLeftFrom > 0 && zombiesLeft <= zombiesLeftFrom
- && (startingWave = getPlugin().getConfig().getInt("Glowing-Status.Starting-Wave")) > 0
- && pluginArena.getWave() >= startingWave) {
+ && (startingWave = getPlugin().getConfig().getInt("Glowing-Status.Starting-Wave")) > 0
+ && pluginArena.getWave() >= startingWave) {
for(org.bukkit.entity.Creature remaining : pluginArena.getEnemies()) {
if(!remaining.isGlowing()) { // To avoid setting glowing property every time
remaining.setGlowing(true);
@@ -82,9 +82,14 @@ public void handleCall(PluginArena arena) {
if(arena.getArenaOption("ZOMBIES_TO_SPAWN") < 0) {
arena.setArenaOption("ZOMBIES_TO_SPAWN", 0);
}
- } else if(arena.getTimer() <= 0) {
- pluginArena.setFighting(true);
- pluginArena.getPlugin().getArenaManager().startWave(pluginArena);
+ } else if(arena.getTimer() <= 3) {
+ SoundHelper.playArenaCountdown(arena);
+ if(arena.getTimer() <= 0) {
+ pluginArena.setFighting(true);
+ pluginArena.getPlugin().getArenaManager().startWave(pluginArena);
+ } else if(arena.getTimer() >= 1) {
+ new TitleBuilder("IN_GAME_MESSAGES_VILLAGE_WAVE_TITLE_STARTING_" + arena.getTimer()).asKey().arena(arena).sendArena();
+ }
}
}
diff --git a/src/main/java/plugily/projects/villagedefense/boot/AdditionalValueInitializer.java b/src/main/java/plugily/projects/villagedefense/boot/AdditionalValueInitializer.java
index 4b2075c34..e1af83f21 100644
--- a/src/main/java/plugily/projects/villagedefense/boot/AdditionalValueInitializer.java
+++ b/src/main/java/plugily/projects/villagedefense/boot/AdditionalValueInitializer.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.boot;
@@ -57,10 +57,6 @@ private void registerConfigOptions() {
getConfigPreferences().registerOption("RESPAWN_IN_GAME_JOIN", new ConfigOption("Respawn.In-Game-Join", true));
getConfigPreferences().registerOption("LIMIT_WAVE_UNLIMITED", new ConfigOption("Limit.Wave.Unlimited", true));
getConfigPreferences().registerOption("LIMIT_ENTITY_BUY_AFTER_DEATH", new ConfigOption("Limit.Wave.Entity-Buy-After-Death", true));
- getConfigPreferences().registerOption("ZOMBIE_HEALTHBAR", new ConfigOption("Creatures.Health-Bar", true));
- getConfigPreferences().registerOption("NAME_VISIBILITY_GOLEM", new ConfigOption("Name-Visibility.Golem", true));
- getConfigPreferences().registerOption("NAME_VISIBILITY_WOLF", new ConfigOption("Name-Visibility.Wolf", true));
- getConfigPreferences().registerOption("NAME_VISIBILITY_VILLAGER", new ConfigOption("Name-Visibility.Villager", true));
}
private void registerStatistics() {
diff --git a/src/main/java/plugily/projects/villagedefense/boot/MessageInitializer.java b/src/main/java/plugily/projects/villagedefense/boot/MessageInitializer.java
index e8f39b320..f8afca4d2 100644
--- a/src/main/java/plugily/projects/villagedefense/boot/MessageInitializer.java
+++ b/src/main/java/plugily/projects/villagedefense/boot/MessageInitializer.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.boot;
@@ -40,6 +40,7 @@ public MessageInitializer(Main plugin) {
}
public void registerMessages() {
+ registerGoldMessages();
getMessageManager().registerMessage("COMMANDS_ADMIN_ADDED_ORBS", new Message("Commands.Admin.Added-Orbs", ""));
getMessageManager().registerMessage("COMMANDS_ADMIN_RECEIVED_ORBS", new Message("Commands.Admin.Received-Orbs", ""));
@@ -53,12 +54,19 @@ public void registerMessages() {
getMessageManager().registerMessage("IN_GAME_MESSAGES_ADMIN_REMOVED_ZOMBIES", new Message("In-Game.Messages.Admin.Removed.Zombies", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ADMIN_REMOVED_WOLVES", new Message("In-Game.Messages.Admin.Removed.Wolves", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_ADMIN_CHANGED_WAVE", new Message("In-Game.Messages.Admin.Changed.Wave", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_ADMIN_NOTHING_T0_CLEAN", new Message("In-Game.Messages.Admin.Nothing-To-Clean", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_ROTTEN_FLESH_LEVEL_UP", new Message("In-Game.Messages.Village.Rotten-Flesh-Level-Up", ""));
- getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_FEEL_REFRESHED", new Message("In-Game.Messages.Village.You-Feel-Refreshed", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_DIED", new Message("In-Game.Messages.Village.Villager.Died", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_NAMES", new Message("In-Game.Messages.Village.Villager.Names", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_SPECIAL_OFFER", new Message("In-Game.Messages.Village.Villager.Special-Offer", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_OFFERING_SALE", new Message("In-Game.Messages.Village.Villager.Offering-Sale", ""));
+
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_ROTTEN_OFFER", new Message("In-Game.Messages.Village.Villager.Rotten-Offer", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_ROTTEN_SALE", new Message("In-Game.Messages.Village.Villager.Rotten-Sale", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_VILLAGER_PINATA_EVENT", new Message("In-Game.Messages.Village.Villager.Pinata-Event", ""));
+
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_STUCK_ZOMBIES", new Message("In-Game.Messages.Village.Wave.Stuck-Zombies", ""));
/*unused*/
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_SPECTATOR_WARNING", new Message("In-Game.Messages.Village.Wave.Spectator-Warning", ""));
@@ -68,13 +76,19 @@ public void registerMessages() {
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_STARTED", new Message("In-Game.Messages.Village.Wave.Started", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_TITLE_START", new Message("In-Game.Messages.Village.Wave.Title.Start", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_TITLE_END", new Message("In-Game.Messages.Village.Wave.Title.End", ""));
- getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ORBS_PICKUP", new Message("In-Game.Messages.Village.Orbs.Pickup", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_TITLE_STARTING_3", new Message("In-Game.Messages.Village.Wave.Title.Start-3", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_TITLE_STARTING_2", new Message("In-Game.Messages.Village.Wave.Title.Start-2", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_TITLE_STARTING_1", new Message("In-Game.Messages.Village.Wave.Title.Start-1", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_CANT_RIDE_OTHER", new Message("In-Game.Messages.Village.Entities.Cant-Ride-Other", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_CANT_UPGRADE_THIS", new Message("In-Game.Messages.Village.Entities.Cant-Upgrade-This", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_CANT_UPGRADE_OTHER", new Message("In-Game.Messages.Village.Entities.Cant-Upgrade-Other", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_SPAWN", new Message("In-Game.Messages.Village.Entities.Wolf.Spawn", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_NAME", new Message("In-Game.Messages.Village.Entities.Wolf.Name", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_WOLF_DEATH", new Message("In-Game.Messages.Village.Entities.Wolf.Death", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_DEATH", new Message("In-Game.Messages.Village.Entities.Golem.Death", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_SPAWN", new Message("In-Game.Messages.Village.Entities.Golem.Spawn", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_NAME", new Message("In-Game.Messages.Village.Entities.Golem.Name", ""));
- getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_GOLEM_CANT_RIDE_OTHER", new Message("In-Game.Messages.Village.Entities.Golem.Cant-Ride-Other", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_WAVE_ENTITIES_ZOMBIE_STUNNED_NAME", new Message("In-Game.Messages.Village.Entities.Zombie.Stunned-Name", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_GUI", new Message("In-Game.Messages.Village.Shop.GUI", ""));
@@ -83,7 +97,13 @@ public void registerMessages() {
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_MOB_LIMIT_REACHED", new Message("In-Game.Messages.Village.Shop.Mob-Limit-Reached", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_NOT_ENOUGH_CURRENCY", new Message("In-Game.Messages.Village.Shop.Not-Enough-Currency", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_CURRENCY", new Message("In-Game.Messages.Village.Shop.Currency", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_WAVE_LOCK", new Message("In-Game.Messages.Village.Shop.Wave-Lock", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_ITEM_LOCKED", new Message("In-Game.Messages.Village.Shop.Item-Locked-Name", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_WAVE_STILL_LOCKED", new Message("In-Game.Messages.Village.Shop.Wave-Still-Locked", ""));
getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_NOT_DEFINED", new Message("In-Game.Messages.Village.Shop.Not-Defined", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_NEW_OFFERS_AVAILABLE", new Message("In-Game.Messages.Village.Shop.New-Shop-Offers", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_SPECIAL_OFFER", new Message("In-Game.Messages.Village.Shop.Special-Offer", ""));
+ getMessageManager().registerMessage("IN_GAME_MESSAGES_VILLAGE_SHOP_AUTO_ARMOR_EQUIPPED", new Message("In-Game.Messages.Village.Shop.Auto-Armor-Equipped", ""));
getMessageManager().registerMessage("LEADERBOARD_STATISTICS_ORBS", new Message("Leaderboard.Statistics.Orbs", ""));
@@ -109,155 +129,20 @@ public void registerMessages() {
getMessageManager().registerMessage("UPGRADE_MENU_UPGRADES_DEFENSE_NAME", new Message("Upgrade-Menu.Upgrades.Final-Defense.Name", ""));
getMessageManager().registerMessage("UPGRADE_MENU_UPGRADES_DEFENSE_DESCRIPTION", new Message("Upgrade-Menu.Upgrades.Final-Defense.Description", ""));
-
- //CLEANER KIT
-
- getMessageManager().registerMessage("KIT_CONTENT_CLEANER_NAME", new Message("Kit.Content.Cleaner.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_CLEANER_DESCRIPTION", new Message("Kit.Content.Cleaner.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_CLEANER_GAME_ITEM_NAME", new Message("Kit.Content.Cleaner.Game-Item.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_CLEANER_GAME_ITEM_DESCRIPTION", new Message("Kit.Content.Cleaner.Game-Item.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_CLEANER_CLEANED_MAP", new Message("Kit.Content.Cleaner.Cleaned.Map", ""));
- getMessageManager().registerMessage("KIT_CONTENT_CLEANER_CLEANED_NOTHING", new Message("Kit.Content.Cleaner.Cleaned.Nothing", ""));
-
-//ZOMBIE_TELEPORTER KIT
-
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_NAME", new Message("Kit.Content.Zombie-Teleporter.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_DESCRIPTION", new Message("Kit.Content.Zombie-Teleporter.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_GAME_ITEM_NAME", new Message("Kit.Content.Zombie-Teleporter.Game-Item.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_GAME_ITEM_DESCRIPTION", new Message("Kit.Content.Zombie-Teleporter.Game-Item.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_GAME_ITEM_GUI", new Message("Kit.Content.Zombie-Teleporter.Game-Item.GUI", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_TELEPORT_ZOMBIE", new Message("Kit.Content.Zombie-Teleporter.Teleport.Zombie", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ZOMBIE_TELEPORTER_TELEPORT_NOT_FOUND", new Message("Kit.Content.Zombie-Teleporter.Teleport.Not-Found", ""));
-
-//KNIGHT
+ //KNIGHT
getMessageManager().registerMessage("KIT_CONTENT_KNIGHT_NAME", new Message("Kit.Content.Knight.Name", ""));
getMessageManager().registerMessage("KIT_CONTENT_KNIGHT_DESCRIPTION", new Message("Kit.Content.Knight.Description", ""));
-//LIGHT_TANK
-
- getMessageManager().registerMessage("KIT_CONTENT_LIGHT_TANK_NAME", new Message("Kit.Content.Light-Tank.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_LIGHT_TANK_DESCRIPTION", new Message("Kit.Content.Light-Tank.Description", ""));
-
-//ARCHER
-
- getMessageManager().registerMessage("KIT_CONTENT_ARCHER_NAME", new Message("Kit.Content.Archer.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_ARCHER_DESCRIPTION", new Message("Kit.Content.Archer.Description", ""));
-
-//PUNCHER
-
- getMessageManager().registerMessage("KIT_CONTENT_PUNCHER_NAME", new Message("Kit.Content.Puncher.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_PUNCHER_DESCRIPTION", new Message("Kit.Content.Puncher.Description", ""));
-
-//HEALER
-
- getMessageManager().registerMessage("KIT_CONTENT_HEALER_NAME", new Message("Kit.Content.Healer.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_HEALER_DESCRIPTION", new Message("Kit.Content.Healer.Description", ""));
-
-//LOOTER
-
- getMessageManager().registerMessage("KIT_CONTENT_LOOTER_NAME", new Message("Kit.Content.Looter.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_LOOTER_DESCRIPTION", new Message("Kit.Content.Looter.Description", ""));
-
-//RUNNER
-
- getMessageManager().registerMessage("KIT_CONTENT_RUNNER_NAME", new Message("Kit.Content.Runner.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_RUNNER_DESCRIPTION", new Message("Kit.Content.Runner.Description", ""));
-
-//MEDIUM_TANK
-
- getMessageManager().registerMessage("KIT_CONTENT_MEDIUM_TANK_NAME", new Message("Kit.Content.Medium-Tank.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_MEDIUM_TANK_DESCRIPTION", new Message("Kit.Content.Medium-Tank.Description", ""));
-
-//WORKER
-
- getMessageManager().registerMessage("KIT_CONTENT_WORKER_NAME", new Message("Kit.Content.Worker.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WORKER_DESCRIPTION", new Message("Kit.Content.Worker.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WORKER_GAME_ITEM_CHAT", new Message("Kit.Content.Worker.Game-Item.Chat", ""));
-
-//DOG_FRIEND
-
- getMessageManager().registerMessage("KIT_CONTENT_DOG_FRIEND_NAME", new Message("Kit.Content.Dog-Friend.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_DOG_FRIEND_DESCRIPTION", new Message("Kit.Content.Dog-Friend.Description", ""));
-
-//HARDCORE
-
- getMessageManager().registerMessage("KIT_CONTENT_HARDCORE_NAME", new Message("Kit.Content.Hardcore.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_HARDCORE_DESCRIPTION", new Message("Kit.Content.Hardcore.Description", ""));
-
-//GOLEM_FRIEND
-
- getMessageManager().registerMessage("KIT_CONTENT_GOLEM_FRIEND_NAME", new Message("Kit.Content.Golem-Friend.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_GOLEM_FRIEND_DESCRIPTION", new Message("Kit.Content.Golem-Friend.Description", ""));
-
-//TORNADO
-
- getMessageManager().registerMessage("KIT_CONTENT_TORNADO_NAME", new Message("Kit.Content.Tornado.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TORNADO_DESCRIPTION", new Message("Kit.Content.Tornado.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TORNADO_GAME_ITEM_NAME", new Message("Kit.Content.Tornado.Game-Item.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TORNADO_GAME_ITEM_DESCRIPTION", new Message("Kit.Content.Tornado.Game-Item.Description", ""));
-
-//TERMINATOR
-
- getMessageManager().registerMessage("KIT_CONTENT_TERMINATOR_NAME", new Message("Kit.Content.Terminator.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TERMINATOR_DESCRIPTION", new Message("Kit.Content.Terminator.Description", ""));
-
-//TELEPORTER
-
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_NAME", new Message("Kit.Content.Teleporter.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_DESCRIPTION", new Message("Kit.Content.Teleporter.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_GAME_ITEM_NAME", new Message("Kit.Content.Teleporter.Game-Item.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_GAME_ITEM_DESCRIPTION", new Message("Kit.Content.Teleporter.Game-Item.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_GAME_ITEM_GUI", new Message("Kit.Content.Teleport.Game-Item.GUI", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_TELEPORT_VILLAGER", new Message("Kit.Content.Teleporter.Teleport.Villager", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_TELEPORT_WARNING", new Message("Kit.Content.Teleporter.Teleport.Warning", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_TELEPORT_PLAYER", new Message("Kit.Content.Teleporter.Teleport.Player", ""));
- getMessageManager().registerMessage("KIT_CONTENT_TELEPORTER_TELEPORT_NOT_FOUND", new Message("Kit.Content.Teleporter.Teleport.Not-Found", ""));
-
-//HEAVY_TANK
-
- getMessageManager().registerMessage("KIT_CONTENT_HEAVY_TANK_NAME", new Message("Kit.Content.Heavy-Tank.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_HEAVY_TANK_DESCRIPTION", new Message("Kit.Content.Heavy-Tank.Description", ""));
-
-//SHOT_BOW
-
- getMessageManager().registerMessage("KIT_CONTENT_SHOT_BOW_NAME", new Message("Kit.Content.Shot-Bow.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_SHOT_BOW_DESCRIPTION", new Message("Kit.Content.Shot-Bow.Description", ""));
-
-//BLOCKER
-
- getMessageManager().registerMessage("KIT_CONTENT_BLOCKER_NAME", new Message("Kit.Content.Blocker.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_BLOCKER_DESCRIPTION", new Message("Kit.Content.Blocker.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_BLOCKER_GAME_ITEM_NAME", new Message("Kit.Content.Blocker.Game-Item.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_BLOCKER_GAME_ITEM_DESCRIPTION", new Message("Kit.Content.Blocker.Game-Item.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_BLOCKER_PLACE_SUCCESS", new Message("Kit.Content.Blocker.Place.Success", ""));
- getMessageManager().registerMessage("KIT_CONTENT_BLOCKER_PLACE_FAIL", new Message("Kit.Content.Blocker.Place.Fail", ""));
-
-//PREMIUM_HARDCORE
-
- getMessageManager().registerMessage("KIT_CONTENT_PREMIUM_HARDCORE_NAME", new Message("Kit.Content.Premium-Hardcore.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_PREMIUM_HARDCORE_DESCRIPTION", new Message("Kit.Content.Premium-Hardcore.Description", ""));
-
-//MEDIC
-
- getMessageManager().registerMessage("KIT_CONTENT_MEDIC_NAME", new Message("Kit.Content.Medic.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_MEDIC_DESCRIPTION", new Message("Kit.Content.Medic.Description", ""));
-
-//WILD_NAKED
-
- getMessageManager().registerMessage("KIT_CONTENT_WILD_NAKED_NAME", new Message("Kit.Content.Wild-Naked.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WILD_NAKED_DESCRIPTION", new Message("Kit.Content.Wild-Naked.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WILD_NAKED_CANNOT_WEAR_ARMOR", new Message("Kit.Content.Wild-Naked.Cannot-Wear-Armor", ""));
-
-//WIZARD
-
- getMessageManager().registerMessage("KIT_CONTENT_WIZARD_NAME", new Message("Kit.Content.Wizard.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WIZARD_DESCRIPTION", new Message("Kit.Content.Wizard.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WIZARD_GAME_ITEM_ESSENCE_NAME", new Message("Kit.Content.Wizard.Game-Item.Essence.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WIZARD_GAME_ITEM_ESSENCE_DESCRIPTION", new Message("Kit.Content.Wizard.Game-Item.Essence.Description", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WIZARD_GAME_ITEM_WAND_NAME", new Message("Kit.Content.Wizard.Game-Item.Wand.Name", ""));
- getMessageManager().registerMessage("KIT_CONTENT_WIZARD_GAME_ITEM_WAND_DESCRIPTION", new Message("Kit.Content.Wizard.Game-Item.Wand.Description", ""));
+ //GENERAL FOR KITS
+ getMessageManager().registerMessage("KIT_LOCKED_TILL", new Message("Kit.Locked-Till", ""));
+ getMessageManager().registerMessage("KIT_ABILITY_UNLOCKED", new Message("Kit.Ability-Unlocked", ""));
+ getMessageManager().registerMessage("KIT_ABILITY_POWER_INCREASED", new Message("Kit.Ability-Power-Increased", ""));
+ getMessageManager().registerMessage("KIT_PASSIVE_POWER_INCREASED", new Message("Kit.Passive-Power-Increased", ""));
+ }
+ private void registerGoldMessages() {
+ getMessageManager().registerMessage("VD_GOLD_NEW_RECORD_REACHED", new Message("Gold-Messages.New-Record-Reached", ""));
}
private void registerLocales() {
diff --git a/src/main/java/plugily/projects/villagedefense/boot/PlaceholderInitializer.java b/src/main/java/plugily/projects/villagedefense/boot/PlaceholderInitializer.java
index e7b54f132..f3e608b15 100644
--- a/src/main/java/plugily/projects/villagedefense/boot/PlaceholderInitializer.java
+++ b/src/main/java/plugily/projects/villagedefense/boot/PlaceholderInitializer.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.boot;
@@ -24,6 +24,7 @@
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
import plugily.projects.minigamesbox.classic.handlers.placeholder.Placeholder;
import plugily.projects.minigamesbox.classic.handlers.placeholder.PlaceholderManager;
+import plugily.projects.minigamesbox.classic.user.User;
import plugily.projects.villagedefense.Main;
import plugily.projects.villagedefense.arena.Arena;
import plugily.projects.villagedefense.arena.ArenaRegistry;
@@ -167,6 +168,21 @@ public String getValue(PluginArena arena) {
return Integer.toString(arena.getArenaOption("ROTTEN_FLESH_AMOUNT"));
}
});
+ getPlaceholderManager().registerPlaceholder(new Placeholder("orbs_amount", Placeholder.PlaceholderType.ARENA, Placeholder.PlaceholderExecutor.ALL) {
+ @Override
+ public String getValue(Player player, PluginArena arena) {
+ User user = plugin.getUserManager().getUser(player);
+ if(user.getArena() == null) {
+ return "0";
+ }
+ return Integer.toString(user.getStatistic("ORBS"));
+ }
+
+ @Override
+ public String getValue(PluginArena arena) {
+ return "undefined";
+ }
+ });
}
private PlaceholderManager getPlaceholderManager() {
diff --git a/src/main/java/plugily/projects/villagedefense/commands/arguments/ArgumentsRegistry.java b/src/main/java/plugily/projects/villagedefense/commands/arguments/ArgumentsRegistry.java
index adb5e8f19..615114973 100644
--- a/src/main/java/plugily/projects/villagedefense/commands/arguments/ArgumentsRegistry.java
+++ b/src/main/java/plugily/projects/villagedefense/commands/arguments/ArgumentsRegistry.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.commands.arguments;
@@ -23,7 +23,9 @@
import plugily.projects.villagedefense.commands.arguments.admin.AddOrbsArgument;
import plugily.projects.villagedefense.commands.arguments.admin.ClearEntitiesArgument;
import plugily.projects.villagedefense.commands.arguments.admin.RespawnArgument;
+import plugily.projects.villagedefense.commands.arguments.admin.ScriptEngineDebugArgument;
import plugily.projects.villagedefense.commands.arguments.admin.SetPriceArgument;
+import plugily.projects.villagedefense.commands.arguments.admin.SetWaveUnlockArgument;
import plugily.projects.villagedefense.commands.arguments.admin.arena.SetWaveArgument;
/**
@@ -46,5 +48,7 @@ public ArgumentsRegistry(Main plugin) {
new ClearEntitiesArgument(this);
new RespawnArgument(this);
new SetPriceArgument(this);
+ new SetWaveUnlockArgument(this);
+ new ScriptEngineDebugArgument(this);
}
}
diff --git a/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ClearEntitiesArgument.java b/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ClearEntitiesArgument.java
index 25c6e7cfd..2ae68b4bb 100644
--- a/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ClearEntitiesArgument.java
+++ b/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ClearEntitiesArgument.java
@@ -1,19 +1,19 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.commands.arguments.admin;
@@ -63,7 +63,7 @@ public void execute(CommandSender sender, String[] args) {
switch(args[1].toLowerCase()) {
case "villager":
if(arena.getVillagers().isEmpty()) {
- new MessageBuilder("KIT_CONTENT_CLEANER_CLEANED_NOTHING").asKey().send(sender);
+ new MessageBuilder("IN_GAME_MESSAGES_ADMIN_NOTHING_T0_CLEAN").asKey().send(sender);
return;
}
for(Villager villager : arena.getVillagers()) {
@@ -76,7 +76,7 @@ public void execute(CommandSender sender, String[] args) {
break;
case "zombie":
if(arena.getEnemies().isEmpty()) {
- new MessageBuilder("KIT_CONTENT_CLEANER_CLEANED_NOTHING").asKey().send(sender);
+ new MessageBuilder("IN_GAME_MESSAGES_ADMIN_NOTHING_T0_CLEAN").asKey().send(sender);
return;
}
ArenaUtils.removeSpawnedEnemies(arena);
@@ -86,7 +86,7 @@ public void execute(CommandSender sender, String[] args) {
break;
case "golem":
if(arena.getIronGolems().isEmpty()) {
- new MessageBuilder("KIT_CONTENT_CLEANER_CLEANED_NOTHING").asKey().send(sender);
+ new MessageBuilder("IN_GAME_MESSAGES_ADMIN_NOTHING_T0_CLEAN").asKey().send(sender);
return;
}
for(IronGolem golem : arena.getIronGolems()) {
@@ -99,7 +99,7 @@ public void execute(CommandSender sender, String[] args) {
break;
case "wolf":
if(arena.getWolves().isEmpty()) {
- new MessageBuilder("KIT_CONTENT_CLEANER_CLEANED_NOTHING").asKey().send(sender);
+ new MessageBuilder("IN_GAME_MESSAGES_ADMIN_NOTHING_T0_CLEAN").asKey().send(sender);
return;
}
for(Wolf wolf : arena.getWolves()) {
diff --git a/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ScriptEngineDebugArgument.java b/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ScriptEngineDebugArgument.java
new file mode 100644
index 000000000..6fe41cb56
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/ScriptEngineDebugArgument.java
@@ -0,0 +1,70 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.commands.arguments.admin;
+
+import plugily.projects.villagedefense.commands.arguments.ArgumentsRegistry;
+
+/**
+ * @author Plajer
+ *
+ * Created at 03.09.2023
+ */
+public class ScriptEngineDebugArgument {
+
+ public ScriptEngineDebugArgument(ArgumentsRegistry registry) {
+ /*registry.mapArgument("villagedefenseadmin", new LabeledCommandArgument("scripttest", Arrays.asList("villagedefense.admin.scripttest"),
+ CommandArgument.ExecutorType.PLAYER, new LabelData("/vda scripttest &c[text]", "/vda scripttest",
+ "&7Perform a rewards script engine test\n&6Permission: &7villagedefense.admin.scripttest")) {
+ @Override
+ public void execute(CommandSender sender, String[] args) {
+ Player player = (Player) sender;
+ if(!registry.getPlugin().getBukkitHelper().checkIsInGameInstance(player)) {
+ return;
+ }
+ Arena arena = (Arena) registry.getPlugin().getArenaRegistry().getArena(player);
+ StringBuilder combined = new StringBuilder();
+ for(String argument : args) {
+ if(argument.equals("scripttest")) {
+ continue;
+ }
+ combined = combined.append(argument);
+ }
+ javax.script.ScriptEngine engine;
+ try {
+ engine = new NashornScriptEngineFactory().getScriptEngine();
+ } catch(Exception ex) {
+ player.sendMessage("Engine failed to initialize");
+ player.sendMessage(ex.getMessage());
+ return;
+ }
+ engine.put("player", player);
+ engine.put("server", Bukkit.getServer());
+ engine.put("arena", arena);
+ engine.put("plugin", registry.getPlugin());
+ try {
+ engine.eval(combined.toString());
+ } catch(ScriptException ex) {
+ player.sendMessage("Evaluation failed at " + ex.getColumnNumber() + ":" + ex.getLineNumber() + ", details:");
+ player.sendMessage(ex.getMessage());
+ }
+ }
+ });*/
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/SetWaveUnlockArgument.java b/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/SetWaveUnlockArgument.java
new file mode 100644
index 000000000..1feee65c0
--- /dev/null
+++ b/src/main/java/plugily/projects/villagedefense/commands/arguments/admin/SetWaveUnlockArgument.java
@@ -0,0 +1,88 @@
+/*
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package plugily.projects.villagedefense.commands.arguments.admin;
+
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import plugily.projects.minigamesbox.classic.commands.arguments.data.CommandArgument;
+import plugily.projects.minigamesbox.classic.commands.arguments.data.LabelData;
+import plugily.projects.minigamesbox.classic.commands.arguments.data.LabeledCommandArgument;
+import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
+import plugily.projects.minigamesbox.classic.utils.helper.ItemBuilder;
+import plugily.projects.minigamesbox.classic.utils.misc.complement.ComplementAccessor;
+import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
+import plugily.projects.minigamesbox.number.NumberUtils;
+import plugily.projects.villagedefense.commands.arguments.ArgumentsRegistry;
+
+import java.util.List;
+
+/**
+ * @author Plajer
+ *
+ * Created at 24.11.2018
+ */
+public class SetWaveUnlockArgument {
+
+ public SetWaveUnlockArgument(ArgumentsRegistry registry) {
+ registry.mapArgument("villagedefenseadmin", new LabeledCommandArgument("setwaveunlock", "villagedefense.admin.setwaveunlock", CommandArgument.ExecutorType.PLAYER,
+ new LabelData("/vda setwaveunlock &6", "/vda setwaveunlock ",
+ "&7Set wave at which item is purchasable in the shop\n&6Permission: &7villagedefense.admin.setwaveunlock")) {
+ @Override
+ public void execute(CommandSender sender, String[] args) {
+ if(args.length == 1 || !NumberUtils.isInteger(args[1])) {
+ new MessageBuilder(ChatColor.RED + "Please type wave number!").prefix().send(sender);
+ return;
+ }
+
+ Player player = (Player) sender;
+ ItemStack item = VersionUtils.getItemInHand(player);
+ if(item == null || item.getType() == Material.AIR) {
+ new MessageBuilder("COMMANDS_HOLD_ANY_ITEM").asKey().player(player).sendPlayer();
+ return;
+ }
+
+ ItemMeta meta = item.getItemMeta();
+ if(meta == null || !meta.hasLore()) {
+ VersionUtils.setItemInHand(player, new ItemBuilder(item)
+ .lore(Integer.parseInt(args[1]) + " wave_lock").build());
+ new MessageBuilder("COMMANDS_COMMAND_EXECUTED").asKey().player(player).sendPlayer();
+ return;
+ }
+
+ //check any price from lore
+ List lore = ComplementAccessor.getComplement().getLore(meta);
+ for(String search : lore) {
+ if (search.endsWith("wave_lock")) {
+ lore.remove(search);
+ break;
+ }
+ }
+ lore.add(0, Integer.parseInt(args[1]) + " wave_lock");
+ ComplementAccessor.getComplement().setLore(meta, lore);
+ item.setItemMeta(meta);
+ new MessageBuilder("COMMANDS_COMMAND_EXECUTED").asKey().player(player).sendPlayer();
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/plugily/projects/villagedefense/creatures/BaseCreatureInitializer.java b/src/main/java/plugily/projects/villagedefense/creatures/BaseCreatureInitializer.java
index 2b4cf55fd..db6823210 100644
--- a/src/main/java/plugily/projects/villagedefense/creatures/BaseCreatureInitializer.java
+++ b/src/main/java/plugily/projects/villagedefense/creatures/BaseCreatureInitializer.java
@@ -1,20 +1,20 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.creatures;
@@ -29,28 +29,13 @@
import plugily.projects.minigamesbox.classic.utils.misc.MiscUtils;
public interface BaseCreatureInitializer {
+
Villager spawnVillager(Location location);
Wolf spawnWolf(Location location);
IronGolem spawnGolem(Location location);
- Creature spawnFastZombie(Location location);
-
- Creature spawnBabyZombie(Location location);
-
- Creature spawnHardZombie(Location location);
-
- Creature spawnPlayerBuster(Location location);
-
- Creature spawnGolemBuster(Location location);
-
- Creature spawnVillagerBuster(Location location);
-
- Creature spawnKnockbackResistantZombies(Location location);
-
- Creature spawnVillagerSlayer(Location location);
-
default void applyFollowRange(Creature zombie) {
MiscUtils.getEntityAttribute(zombie, Attribute.GENERIC_FOLLOW_RANGE).ifPresent(ai -> ai.setBaseValue(200.0D));
}
diff --git a/src/main/java/plugily/projects/villagedefense/creatures/CachedObject.java b/src/main/java/plugily/projects/villagedefense/creatures/CachedObject.java
deleted file mode 100644
index 4b54cae71..000000000
--- a/src/main/java/plugily/projects/villagedefense/creatures/CachedObject.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package plugily.projects.villagedefense.creatures;
-
-/**
- * @author Plajer
- *
- * Created at 06.01.2019
- */
-public class CachedObject {
-
- private final String fieldName;
- private final Class> clazz;
- private final Object object;
-
- public CachedObject(String fieldName, Class> clazz, Object object) {
- this.fieldName = fieldName;
- this.clazz = clazz;
- this.object = object;
- }
-
- public String getFieldName() {
- return fieldName;
- }
-
- public Class> getClazz() {
- return clazz;
- }
-
- public Object getObject() {
- return object;
- }
-}
diff --git a/src/main/java/plugily/projects/villagedefense/creatures/CreatureUtils.java b/src/main/java/plugily/projects/villagedefense/creatures/CreatureUtils.java
index 5fbe41331..3d52c8529 100644
--- a/src/main/java/plugily/projects/villagedefense/creatures/CreatureUtils.java
+++ b/src/main/java/plugily/projects/villagedefense/creatures/CreatureUtils.java
@@ -1,44 +1,40 @@
/*
- * Village Defense - Protect villagers from hordes of zombies
- * Copyright (c) 2023 Plugily Projects - maintained by Tigerpanzer_02 and contributors
+ * Village Defense - Protect villagers from hordes of zombies
+ * Copyright (c) 2024 Plugily Projects - maintained by Tigerpanzer_02 and contributors
*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
*/
package plugily.projects.villagedefense.creatures;
+import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
+import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
+import org.bukkit.metadata.FixedMetadataValue;
import plugily.projects.minigamesbox.classic.handlers.language.MessageBuilder;
-import plugily.projects.minigamesbox.classic.utils.version.ServerVersion;
import plugily.projects.minigamesbox.classic.utils.version.VersionUtils;
-import plugily.projects.minigamesbox.string.StringFormatUtils;
import plugily.projects.villagedefense.Main;
import plugily.projects.villagedefense.arena.Arena;
+import plugily.projects.villagedefense.creatures.v1_9_UP.CustomCreature;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
-import java.util.logging.Level;
/**
* @author Plajer
@@ -48,10 +44,9 @@
public class CreatureUtils {
private static String[] villagerNames = ("Jagger,Kelsey,Kelton,Haylie,Harlow,Howard,Wulffric,Winfred,Ashley,Bailey,Beckett,Alfredo,Alfred,Adair,Edgar,ED,Eadwig,Edgaras,Buckley,Stanley,Nuffley,"
- + "Mary,Jeffry,Rosaly,Elliot,Harry,Sam,Rosaline,Tom,Ivan,Kevin,Adam,Emma,Mira,Jeff,Isac,Nico").split(",");
+ + "Mary,Jeffry,Rosaly,Elliot,Harry,Sam,Rosaline,Tom,Ivan,Kevin,Adam,Emma,Mira,Jeff,Isac,Nico").split(",");
private static Main plugin;
private static BaseCreatureInitializer creatureInitializer;
- private static final List cachedObjects = new ArrayList<>();
private CreatureUtils() {
}
@@ -59,40 +54,7 @@ private CreatureUtils() {
public static void init(Main plugin) {
CreatureUtils.plugin = plugin;
villagerNames = new MessageBuilder("IN_GAME_MESSAGES_VILLAGE_VILLAGER_NAMES").asKey().build().split(",");
- creatureInitializer = initCreatureInitializer();
- }
-
- public static BaseCreatureInitializer initCreatureInitializer() {
- switch(ServerVersion.Version.getCurrent()) {
- case v1_8_R3:
- return new plugily.projects.villagedefense.creatures.v1_8_R3.CreatureInitializer();
- default:
- return new plugily.projects.villagedefense.creatures.v1_9_UP.CreatureInitializer();
- }
- }
-
- public static Object getPrivateField(String fieldName, Class> clazz, Object object) {
- for(CachedObject cachedObject : cachedObjects) {
- if(cachedObject.getClazz().equals(clazz) && cachedObject.getFieldName().equals(fieldName)) {
- return cachedObject.getObject();
- }
- }
- try {
- Field field = clazz.getDeclaredField(fieldName);
-
- AccessController.doPrivileged((PrivilegedAction