Skip to content

Commit

Permalink
GH-116 Add Effects applied during Combat (#116)
Browse files Browse the repository at this point in the history
* Add inCombatEffects based on custom Events

* Improve give back of potion effects.

* Fix merge conflicts and add okaeri bukkit serdes.

* Simplification of loops, new methods and optimization

* Change HashMap based on Player to UUID for better security

* Fix issues

* Update src/main/java/com/eternalcode/combat/config/implementation/PluginConfig.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/effect/EffectService.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/effect/EffectService.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/effect/EffectService.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/event/FightDeathEvent.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/event/FightTagEvent.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/event/FightDeathEvent.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/FightManager.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/FightManager.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Update src/main/java/com/eternalcode/combat/fight/effect/EffectService.java

Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>

* Codestyle fixes

* Codestyle fixes

* Remove unnesesary FightDeathEvent.java, refactor class names to match project style, fixes in codestyle, move to UUID event pass down instead of bukkit player.

* Add brackets

* Follow Rollczi's review

* Follow DMK's review.

* simple rename

---------

Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com>
Co-authored-by: DMK <81445555+imDMK@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 2, 2023
1 parent 92535dd commit cceeb82
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 11 deletions.
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies {
// Okaeri configs
implementation("eu.okaeri:okaeri-configs-yaml-bukkit:5.0.0-beta.5")
implementation("eu.okaeri:okaeri-configs-serdes-commons:5.0.0-beta.5")
implementation("eu.okaeri:okaeri-configs-serdes-bukkit:5.0.0-beta.5")

// Panda utilities
implementation("org.panda-lang:panda-utilities:0.5.2-alpha")
Expand Down
19 changes: 13 additions & 6 deletions src/main/java/com/eternalcode/combat/CombatPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import com.eternalcode.combat.drop.DropManager;
import com.eternalcode.combat.drop.impl.PercentDropModifier;
import com.eternalcode.combat.drop.impl.PlayersHealthDropModifier;
import com.eternalcode.combat.fight.effect.FightEffectController;
import com.eternalcode.combat.event.EventCaller;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.FightTask;
import com.eternalcode.combat.fight.bossbar.FightBossBarService;
Expand All @@ -19,6 +21,7 @@
import com.eternalcode.combat.fight.controller.FightEscapeController;
import com.eternalcode.combat.fight.controller.FightTagController;
import com.eternalcode.combat.fight.controller.FightUnTagController;
import com.eternalcode.combat.fight.effect.FightEffectService;
import com.eternalcode.combat.fight.pearl.FightPearlController;
import com.eternalcode.combat.fight.pearl.FightPearlManager;
import com.eternalcode.combat.notification.NotificationAnnouncer;
Expand Down Expand Up @@ -47,7 +50,6 @@
public final class CombatPlugin extends JavaPlugin {

private FightManager fightManager;
private FightPearlManager fightPearlManager;

private FightBossBarService fightBossBarService;

Expand All @@ -64,10 +66,12 @@ public void onEnable() {
ConfigBackupService backupService = new ConfigBackupService(dataFolder);
ConfigService configService = new ConfigService(backupService);

EventCaller eventCaller = new EventCaller(server);

PluginConfig pluginConfig = configService.create(PluginConfig.class, new File(dataFolder, "config.yml"));

this.fightManager = new FightManager();
this.fightPearlManager = new FightPearlManager(pluginConfig.pearl);
this.fightManager = new FightManager(eventCaller);
FightPearlManager fightPearlManager = new FightPearlManager(pluginConfig.pearl);

UpdaterService updaterService = new UpdaterService(this.getDescription());

Expand Down Expand Up @@ -95,13 +99,15 @@ public void onEnable() {
.register();

FightTask fightTask = new FightTask(server, pluginConfig, this.fightManager, this.fightBossBarService, notificationAnnouncer);
this.getServer().getScheduler().runTaskTimerAsynchronously(this, fightTask, 20L, 20L);
this.getServer().getScheduler().runTaskTimer(this, fightTask, 20L, 20L);

new Metrics(this, 17803);

DropManager dropManager = new DropManager();
DropKeepInventoryManager keepInventoryManager = new DropKeepInventoryManager();

FightEffectService effectService = new FightEffectService();

Stream.of(
new PercentDropModifier(pluginConfig.dropSettings),
new PlayersHealthDropModifier(pluginConfig.dropSettings)
Expand All @@ -114,9 +120,10 @@ public void onEnable() {
new FightUnTagController(this.fightManager, pluginConfig, notificationAnnouncer),
new FightEscapeController(this.fightManager, pluginConfig, notificationAnnouncer),
new FightActionBlockerController(this.fightManager, notificationAnnouncer, pluginConfig),
new FightPearlController(pluginConfig.pearl, notificationAnnouncer, this.fightManager, this.fightPearlManager),
new FightPearlController(pluginConfig.pearl, notificationAnnouncer, this.fightManager, fightPearlManager),
new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage),
new RegionController(notificationAnnouncer, bridgeService.getRegionProvider(), this.fightManager, pluginConfig)
new RegionController(notificationAnnouncer, bridgeService.getRegionProvider(), this.fightManager, pluginConfig),
new FightEffectController(pluginConfig.effect, effectService, this.fightManager, this.getServer())
).forEach(listener -> this.getServer().getPluginManager().registerEvents(listener, this));

long millis = started.elapsed(TimeUnit.MILLISECONDS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.serdes.commons.SerdesCommons;
import eu.okaeri.configs.yaml.bukkit.YamlBukkitConfigurer;
import eu.okaeri.configs.yaml.bukkit.serdes.SerdesBukkit;

import java.io.File;
import java.util.HashSet;
Expand All @@ -25,7 +26,7 @@ public <T extends OkaeriConfig> T create(Class<T> config, File file) {

T configFile = ConfigManager.create(config);

configFile.withConfigurer(new YamlBukkitConfigurer(), new SerdesCommons());
configFile.withConfigurer(new YamlBukkitConfigurer(), new SerdesCommons(), new SerdesBukkit());
configFile.withSerdesPack(registry -> {
registry.register(new NotificationSerializer());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.eternalcode.combat.WhitelistBlacklistMode;
import com.eternalcode.combat.drop.DropSettings;
import com.eternalcode.combat.fight.effect.FightEffectSettings;
import com.eternalcode.combat.fight.pearl.FightPearlSettings;
import com.eternalcode.combat.notification.Notification;
import com.eternalcode.combat.notification.implementation.ActionBarNotification;
Expand All @@ -23,7 +24,10 @@ public class PluginConfig extends OkaeriConfig {
@Comment({" ", "# Ender pearl settings"})
public FightPearlSettings pearl = new FightPearlSettings();

@Comment({ " ", "# Set a custom way for a player's items to drop on death (if in combat)" })
@Comment({" ", "# Custom effects settings"})
public FightEffectSettings effect = new FightEffectSettings();

@Comment({" ", "# Set a custom way for a player's items to drop on death (if in combat)"})
public DropSettings dropSettings = new DropSettings();

public static class Settings extends OkaeriConfig {
Expand Down Expand Up @@ -114,9 +118,10 @@ public static class Settings extends OkaeriConfig {
public List<EntityType> disabledProjectileEntities = List.of(
EntityType.ENDER_PEARL
);

}

@Comment({ " ", "# Do you want to change the plugin messages?" })
@Comment({" ", "# Do you want to change the plugin messages?"})
public Messages messages = new Messages();

public static class Messages extends OkaeriConfig {
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/com/eternalcode/combat/event/EventCaller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.eternalcode.combat.event;

import org.bukkit.Server;
import org.bukkit.event.Event;

public class EventCaller {

private final Server server;

public EventCaller(Server server) {
this.server = server;
}

public <T extends Event> T callEvent(T event) {
this.server.getPluginManager().callEvent(event);

return event;
}

}
17 changes: 15 additions & 2 deletions src/main/java/com/eternalcode/combat/fight/FightManager.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package com.eternalcode.combat.fight;

import com.eternalcode.combat.event.EventCaller;
import com.eternalcode.combat.fight.event.FightTagEvent;
import com.eternalcode.combat.fight.event.FightUntagEvent;

import java.time.Duration;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;

public class FightManager {

private final Map<UUID, FightTag> fights = new ConcurrentHashMap<>();
private final Map<UUID, FightTag> fights = new HashMap<>();
private final EventCaller eventCaller;

public FightManager(EventCaller eventCaller) {
this.eventCaller = eventCaller;
}

public boolean isInCombat(UUID player) {
if (!this.fights.containsKey(player)) {
Expand All @@ -23,10 +32,14 @@ public boolean isInCombat(UUID player) {
}

public void untag(UUID player) {
this.eventCaller.callEvent(new FightUntagEvent(player));

this.fights.remove(player);
}

public void tag(UUID target, Duration delay) {
this.eventCaller.callEvent(new FightTagEvent(target));

Instant now = Instant.now();
Instant endOfCombatLog = now.plus(delay);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.eternalcode.combat.fight.effect;

import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.event.FightTagEvent;
import com.eternalcode.combat.fight.event.FightUntagEvent;
import org.bukkit.Server;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.potion.PotionEffect;

public class FightEffectController implements Listener {

private final FightEffectService effectService;
private final FightEffectSettings effectSettings;
private final FightManager fightManager;
private final Server server;

public FightEffectController(FightEffectSettings settings, FightEffectService effectService, FightManager fightManager, Server server) {
this.effectSettings = settings;
this.effectService = effectService;
this.fightManager = fightManager;
this.server = server;
}

@EventHandler
public void onTag(FightTagEvent event) {
if (!this.effectSettings.customEffectsEnabled) {
return;
}

Player player = this.server.getPlayer(event.getPlayer());

if (player == null) {
return;
}

this.effectSettings.customEffects.forEach((key, value) ->
this.effectService.applyCustomEffect(player, key, value));
}

@EventHandler
public void onQuit(PlayerQuitEvent event) {
if (!this.effectSettings.customEffectsEnabled) {
return;
}

Player player = event.getPlayer();
this.effectService.restoreActiveEffects(player);
}

@EventHandler
public void onUntag(FightUntagEvent event) {
if (!this.effectSettings.customEffectsEnabled) {
return;
}

Player player = this.server.getPlayer(event.getPlayer());

if (player == null) {
return;
}

this.effectSettings.customEffects.forEach((key, value) -> this.effectService.removeCustomEffect(player, key, value));

this.effectService.restoreActiveEffects(player);
}

@EventHandler
public void onDeath(PlayerDeathEvent event) {
if (!this.effectSettings.customEffectsEnabled) {
return;
}

Player player = event.getEntity();
this.effectService.clearStoredEffects(player);
}

@EventHandler
public void onEffectChange(EntityPotionEffectEvent event) {
if (!this.effectSettings.customEffectsEnabled) {
return;
}

if (!(event.getEntity() instanceof Player player)) {
return;
}

if (!this.fightManager.isInCombat(player.getUniqueId())) {
return;
}

PotionEffect newEffect = event.getNewEffect();
PotionEffect oldEffect = event.getOldEffect();

if (!this.isRemovedEffect(newEffect, oldEffect)) {
return;
}

Integer customAmplifier = this.effectSettings.customEffects.get(oldEffect.getType());

if (customAmplifier == null) {
return;
}

player.addPotionEffect(new PotionEffect(oldEffect.getType(), -1, customAmplifier));
}

private boolean isRemovedEffect(PotionEffect newEffect, PotionEffect oldEffect) {
return newEffect == null && oldEffect != null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.eternalcode.combat.fight.effect;

import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.List;
import java.util.ArrayList;

public class FightEffectService {

private final Map<UUID, List<PotionEffect>> activeEffects = new HashMap<>();
private static final int INFINITE_DURATION = -1;

public void storeActiveEffect(Player player, PotionEffect effect) {
List<PotionEffect> effects = this.activeEffects.computeIfAbsent(player.getUniqueId(), k -> new ArrayList<>());

effects.add(effect);
}

public void restoreActiveEffects(Player player) {
List<PotionEffect> currentEffects = this.getCurrentEffects(player);

for (PotionEffect effect : currentEffects) {
player.addPotionEffect(effect);
}

this.clearStoredEffects(player);
}

public void clearStoredEffects(Player player) {
this.activeEffects.remove(player.getUniqueId());
}

public List<PotionEffect> getCurrentEffects(Player player) {
return this.activeEffects.getOrDefault(player.getUniqueId(), new ArrayList<>());
}

public void applyCustomEffect(Player player, PotionEffectType type, Integer amplifier) {
PotionEffect activeEffect = player.getPotionEffect(type);

if (activeEffect == null) {
player.addPotionEffect(new PotionEffect(type, INFINITE_DURATION, amplifier));
return;
}

if (activeEffect.getAmplifier() > amplifier) {
return;
}

if (activeEffect.getDuration() == -1) {
return;
}

this.storeActiveEffect(player, activeEffect);
player.addPotionEffect(new PotionEffect(type, INFINITE_DURATION, amplifier));
}

public void removeCustomEffect(Player player, PotionEffectType type, Integer amplifier) {
PotionEffect activeEffect = player.getPotionEffect(type);

if (activeEffect == null) {
return;
}

if (activeEffect.getAmplifier() != amplifier) {
return;
}

player.removePotionEffect(type);
}
}
Loading

0 comments on commit cceeb82

Please sign in to comment.