Skip to content

Commit

Permalink
add module to enable explosion of entities with pumpkins on their head
Browse files Browse the repository at this point in the history
change a few config paths for better understanding
add a few comments
improve here and there
  • Loading branch information
xGinko committed Nov 13, 2023
1 parent 9a32f65 commit 0987233
Show file tree
Hide file tree
Showing 17 changed files with 402 additions and 123 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>me.xginko</groupId>
<artifactId>PumpkinPVPReloaded</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
<packaging>jar</packaging>

<name>PumpkinPVPReloaded</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public PostPumpkinExplodeEvent(
public boolean hasExploded() {
return hasExploded;
}
public float getExplosionPower() {
public float getExplodePower() {
return explosionPower;
}
public boolean hasSetFire() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package me.xginko.pumpkinpvpreloaded.events;

import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class PostPumpkinHeadEntityExplodeEvent extends Event {

private static final @NotNull HandlerList handlers = new HandlerList();

private final @NotNull LivingEntity pumpkinHead;
private final @Nullable Player killer;
private final @NotNull Location explodeLocation;
private final float explodePower;
private final boolean setFire, destroyedBlocks, hasExploded;

public PostPumpkinHeadEntityExplodeEvent(
@NotNull LivingEntity pumpkinHead,
final @Nullable Player killer,
@NotNull Location explodeLocation,
final float explosionPower,
final boolean setFire,
final boolean destroyedBlocks,
final boolean hasExploded
) {
this.pumpkinHead = pumpkinHead;
this.killer = killer;
this.explodeLocation = explodeLocation;
this.explodePower = explosionPower;
this.setFire = setFire;
this.destroyedBlocks = destroyedBlocks;
this.hasExploded = hasExploded;
}

public @NotNull LivingEntity getPumpkinHeadEntity() {
return pumpkinHead;
}
public @Nullable Player getKiller() {
return killer;
}
public @NotNull Location getExplodeLocation() {
return explodeLocation;
}
public boolean hasExploded() {
return hasExploded;
}
public float getExplodePower() {
return explodePower;
}
public boolean hasSetFire() {
return setFire;
}
public boolean hasDestroyedBlocks() {
return destroyedBlocks;
}

@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static @NotNull HandlerList getHandlerList() {
return handlers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package me.xginko.pumpkinpvpreloaded.events;

import me.xginko.pumpkinpvpreloaded.PumpkinPVPConfig;
import me.xginko.pumpkinpvpreloaded.PumpkinPVPReloaded;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class PrePumpkinHeadEntityExplodeEvent extends Event implements Cancellable {

private static final @NotNull HandlerList handlers = new HandlerList();
private boolean isCancelled;

private @NotNull LivingEntity pumpkinHead;
private final @Nullable Player killer;
private @NotNull Location explodeLocation;
private float explodePower;
private boolean setFire, breakBlocks;

public PrePumpkinHeadEntityExplodeEvent(
@NotNull LivingEntity pumpkinHead,
final @Nullable Player killer,
@NotNull Location explodeLocation
) {
this.pumpkinHead = pumpkinHead;
this.killer = killer;
this.explodeLocation = explodeLocation;
PumpkinPVPConfig config = PumpkinPVPReloaded.getConfiguration();
this.explodePower = config.explosion_power;
this.setFire = config.explosion_set_fire;
this.breakBlocks = config.explosion_break_blocks;
this.isCancelled = false;
}

public @NotNull LivingEntity getPumpkinHeadEntity() {
return pumpkinHead;
}
public void setPumpkinHeadEntity(@NotNull LivingEntity pumpkinHead) {
this.pumpkinHead = pumpkinHead;
}
public @Nullable Player getKiller() {
return killer;
}
public @NotNull Location getExplodeLocation() {
return explodeLocation;
}
public void setExplodeLocation(@NotNull Location explodeLocation) {
this.explodeLocation = explodeLocation;
}
public float getExplodePower() {
return explodePower;
}
public void setExplodePower(float explodePower) {
this.explodePower = explodePower;
}
public boolean shouldSetFire() {
return setFire;
}
public void setFire(boolean setFire) {
this.setFire = setFire;
}
public boolean shouldBreakBlocks() {
return breakBlocks;
}
public void setBreakBlocks(boolean breakBlocks) {
this.breakBlocks = breakBlocks;
}

@Override
public void setCancelled(boolean cancel) {
isCancelled = cancel;
}
@Override
public boolean isCancelled() {
return isCancelled;
}
@Override
public @NotNull HandlerList getHandlers() {
return handlers;
}
public static @NotNull HandlerList getHandlerList() {
return handlers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import com.google.common.collect.ImmutableMap;
import me.xginko.pumpkinpvpreloaded.PumpkinPVPReloaded;
import me.xginko.pumpkinpvpreloaded.events.PrePumpkinExplodeEvent;
import me.xginko.pumpkinpvpreloaded.events.PrePumpkinHeadEntityExplodeEvent;
import org.bukkit.Location;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
Expand All @@ -25,7 +27,7 @@

public class AdjustDamageInfo implements PumpkinPVPModule, Listener {

private final Cache<Location, Player> pumpkinExploders;
private final Cache<Location, LivingEntity> pumpkinExploders;
private final Map<EntityDamageEvent.DamageModifier, ? extends Function<? super Double, Double>> emptyDamageModifierMap;

protected AdjustDamageInfo() {
Expand Down Expand Up @@ -55,18 +57,23 @@ private void onPrePumpkinExplode(PrePumpkinExplodeEvent event) {
this.pumpkinExploders.put(event.getExplodeLocation(), event.getExploder());
}

@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
private void onPrePumpkinHeadExplode(PrePumpkinHeadEntityExplodeEvent event) {
this.pumpkinExploders.put(event.getExplodeLocation(), event.getPumpkinHeadEntity());
}

@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
private void onDamageByBlock(EntityDamageByBlockEvent event) {
if (!event.getEntityType().equals(EntityType.PLAYER)) return;
if (!event.getCause().equals(EntityDamageEvent.DamageCause.BLOCK_EXPLOSION)) return;

final Player player = (Player) event.getEntity();
final Player exploder = getClosestPumpkinExploder(player.getLocation());
final Player damagedPlayer = (Player) event.getEntity();
final LivingEntity exploder = getClosestPumpkinExploder(damagedPlayer.getLocation());
if (exploder == null) return;

final EntityDamageByEntityEvent damageByExploder = new EntityDamageByEntityEvent(
exploder,
player,
damagedPlayer,
EntityDamageEvent.DamageCause.BLOCK_EXPLOSION,
new EnumMap<>(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, event.getFinalDamage())),
emptyDamageModifierMap,
Expand All @@ -78,15 +85,16 @@ private void onDamageByBlock(EntityDamageByBlockEvent event) {
return;
}

player.setLastDamageCause(damageByExploder);
player.setKiller(exploder);
damagedPlayer.setLastDamageCause(damageByExploder);
if (exploder.getType().equals(EntityType.PLAYER))
damagedPlayer.setKiller((Player) exploder);
}

private @Nullable Player getClosestPumpkinExploder(Location playerLoc) {
private @Nullable LivingEntity getClosestPumpkinExploder(Location playerLoc) {
double distance = 50.0;
Player closestExploder = null;
LivingEntity closestExploder = null;

for (Map.Entry<Location, Player> explosion : this.pumpkinExploders.asMap().entrySet()) {
for (Map.Entry<Location, LivingEntity> explosion : this.pumpkinExploders.asMap().entrySet()) {
final Location explosionLoc = explosion.getKey();
if (explosionLoc.getWorld().getUID().equals(playerLoc.getWorld().getUID())) {
final double currentDistance = playerLoc.distance(explosionLoc);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package me.xginko.pumpkinpvpreloaded.modules;

import me.xginko.pumpkinpvpreloaded.modules.effects.DeathSoundEffects;
import me.xginko.pumpkinpvpreloaded.modules.effects.FireworkEffects;
import me.xginko.pumpkinpvpreloaded.modules.effects.LightningEffects;
import me.xginko.pumpkinpvpreloaded.modules.triggers.*;
import me.xginko.pumpkinpvpreloaded.modules.mechanics.RateLimitPumpkinExplosions;
import me.xginko.pumpkinpvpreloaded.modules.mechanics.RequireBaseBlocks;
import me.xginko.pumpkinpvpreloaded.modules.mechanics.EnablePerWorld;

import java.util.HashSet;

public interface PumpkinPVPModule {
Expand All @@ -14,17 +22,21 @@ static void reloadModules() {
modules.forEach(PumpkinPVPModule::disable);
modules.clear();

modules.add(new AdjustDamageInfo());
modules.add(new DeathSoundEffects());
modules.add(new ExplodePumpkinOnShear());
modules.add(new ExplodePumpkinOnLeftClick());
modules.add(new ExplodePumpkinOnRightClick());
modules.add(new ExplodePumpkinOnPlace());
modules.add(new RateLimitPumpkinExplosions());
modules.add(new RequireBaseBlocks());
modules.add(new ExplodePumpkinHeadEntities());

modules.add(new FireworkEffects());
modules.add(new LightningEffects());
modules.add(new WhitelistedWorlds());
modules.add(new DeathSoundEffects());

modules.add(new RateLimitPumpkinExplosions());
modules.add(new RequireBaseBlocks());
modules.add(new EnablePerWorld());

modules.add(new AdjustDamageInfo());

modules.forEach(module -> {
if (module.shouldEnable()) module.enable();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package me.xginko.pumpkinpvpreloaded.modules;
package me.xginko.pumpkinpvpreloaded.modules.effects;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import me.xginko.pumpkinpvpreloaded.PumpkinPVPConfig;
import me.xginko.pumpkinpvpreloaded.PumpkinPVPReloaded;
import me.xginko.pumpkinpvpreloaded.events.PostPumpkinExplodeEvent;
import me.xginko.pumpkinpvpreloaded.events.PostPumpkinHeadEntityExplodeEvent;
import me.xginko.pumpkinpvpreloaded.modules.PumpkinPVPModule;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.event.EventHandler;
Expand All @@ -22,9 +25,14 @@ public class DeathSoundEffects implements PumpkinPVPModule, Listener {

private final Cache<Location, Float> pumpkinExplosions;
private final List<Sound> deathSounds = new ArrayList<>();
private final float volume;

protected DeathSoundEffects() {
public DeathSoundEffects() {
shouldEnable();
PumpkinPVPConfig config = PumpkinPVPReloaded.getConfiguration();
config.addComment("pumpkin-deaths.death-sound.enable",
"Players dying to a pumpkin explosion will make a spooky configurable sound.");
this.volume = config.getFloat("pumpkin-deaths.death-sound.volume", -1.0F, "-1 means default settings.");
this.pumpkinExplosions = Caffeine.newBuilder().expireAfterWrite(Duration.ofSeconds(1)).build();
PumpkinPVPReloaded.getConfiguration().getList("pumpkin-deaths.death-sound.sounds", List.of(
Sound.ENTITY_GOAT_SCREAMING_DEATH.name(),
Expand Down Expand Up @@ -65,15 +73,25 @@ public void disable() {
HandlerList.unregisterAll(this);
}

@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
@EventHandler(priority = EventPriority.LOWEST)
private void onPostPumpkinExplode(PostPumpkinExplodeEvent event) {
this.pumpkinExplosions.put(event.getExplodeLocation(), event.getExplosionPower());
if (event.hasExploded()) {
this.pumpkinExplosions.put(event.getExplodeLocation(), event.getExplodePower());
}
}

@EventHandler(priority = EventPriority.LOWEST)
private void onPostPumpkinHeadExplode(PostPumpkinHeadEntityExplodeEvent event) {
if (event.hasExploded()) {
this.pumpkinExplosions.put(event.getExplodeLocation(), event.getExplodePower());
}
}

@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
private void onPlayerDeath(PlayerDeathEvent event) {
if (isNearPumpkinExplosion(event.getPlayer().getLocation())) {
event.setDeathSound(this.deathSounds.get(new Random().nextInt(0, this.deathSounds.size())));
if (volume != -1.0F) event.setDeathSoundVolume(volume);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package me.xginko.pumpkinpvpreloaded.modules;
package me.xginko.pumpkinpvpreloaded.modules.effects;

import me.xginko.pumpkinpvpreloaded.PumpkinPVPConfig;
import me.xginko.pumpkinpvpreloaded.PumpkinPVPReloaded;
import me.xginko.pumpkinpvpreloaded.events.PostPumpkinExplodeEvent;
import me.xginko.pumpkinpvpreloaded.events.PostPumpkinHeadEntityExplodeEvent;
import me.xginko.pumpkinpvpreloaded.modules.PumpkinPVPModule;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Location;
Expand All @@ -20,7 +22,7 @@ public class FireworkEffects implements PumpkinPVPModule, Listener {
private final List<FireworkEffect> fireWorkEffects = new ArrayList<>();
private boolean has_enough_colors = true;

protected FireworkEffects() {
public FireworkEffects() {
shouldEnable();
PumpkinPVPConfig config = PumpkinPVPReloaded.getConfiguration();
List<Color> parsedColors = new ArrayList<>();
Expand Down Expand Up @@ -95,7 +97,20 @@ public void disable() {
}

@EventHandler(priority = EventPriority.LOWEST)
private void onPrePumpkinExplode(PostPumpkinExplodeEvent event) {
private void onPostPumpkinExplode(PostPumpkinExplodeEvent event) {
if (event.hasExploded()) {
final Location explosionLoc = event.getExplodeLocation();
Firework firework = explosionLoc.getWorld().spawn(explosionLoc, Firework.class);
FireworkMeta meta = firework.getFireworkMeta();
meta.clearEffects();
meta.addEffect(fireWorkEffects.get(new Random().nextInt(0, fireWorkEffects.size())));
firework.setFireworkMeta(meta);
firework.detonate();
}
}

@EventHandler(priority = EventPriority.LOWEST)
private void onPostPumpkinHeadExplode(PostPumpkinHeadEntityExplodeEvent event) {
if (event.hasExploded()) {
final Location explosionLoc = event.getExplodeLocation();
Firework firework = explosionLoc.getWorld().spawn(explosionLoc, Firework.class);
Expand Down
Loading

0 comments on commit 0987233

Please sign in to comment.