Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ object Versions {
const val PACKETEVENTS = "2.11.1"
const val WORLDGUARD = "7.0.15-beta-01"
const val LUCKPERMS = "5.5.17"
const val ETERNALCORE = "2.0.0"

}

Expand Down
17 changes: 10 additions & 7 deletions eternalcombat-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription

import io.papermc.hangarpublishplugin.model.Platforms
import org.gradle.kotlin.dsl.shadowJar
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription

plugins {
`eternalcombat-java`
Expand Down Expand Up @@ -96,11 +96,14 @@ bukkit {

tasks {
runServer {
minecraftVersion("1.21.10")
downloadPlugins.modrinth("WorldEdit", Versions.WORLDEDIT)
downloadPlugins.modrinth("PacketEvents", "${Versions.PACKETEVENTS}+spigot")
downloadPlugins.modrinth("WorldGuard", Versions.WORLDGUARD)
downloadPlugins.modrinth("LuckPerms", "v${Versions.LUCKPERMS}-bukkit")
minecraftVersion("1.21.11")
downloadPlugins {
modrinth("WorldEdit", Versions.WORLDEDIT)
modrinth("PacketEvents", "${Versions.PACKETEVENTS}+spigot")
modrinth("WorldGuard", Versions.WORLDGUARD)
modrinth("LuckPerms", "v${Versions.LUCKPERMS}-bukkit")
modrinth("EternalCore", Versions.ETERNALCORE)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@
package com.eternalcode.combat;

import com.eternalcode.combat.border.BorderTriggerController;
import com.eternalcode.combat.border.BorderService;
import com.eternalcode.combat.border.BorderServiceImpl;
import com.eternalcode.combat.border.BorderTriggerController;
import com.eternalcode.combat.border.animation.block.BorderBlockController;
import com.eternalcode.combat.border.animation.particle.ParticleController;
import com.eternalcode.combat.bridge.BridgeService;
import com.eternalcode.combat.crystalpvp.RespawnAnchorListener;
import com.eternalcode.combat.config.ConfigService;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.crystalpvp.EndCrystalListener;
import com.eternalcode.combat.crystalpvp.RespawnAnchorListener;
import com.eternalcode.combat.event.EventManager;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.FightManagerImpl;
import com.eternalcode.combat.fight.FightTagCommand;
import com.eternalcode.combat.fight.FightTask;
import com.eternalcode.combat.fight.controller.FightActionBlockerController;
import com.eternalcode.combat.fight.controller.FightBypassAdminController;
import com.eternalcode.combat.fight.controller.FightBypassCreativeController;
import com.eternalcode.combat.fight.controller.FightBypassPermissionController;
import com.eternalcode.combat.fight.controller.FightInventoryController;
import com.eternalcode.combat.fight.controller.FightMessageController;
import com.eternalcode.combat.fight.controller.FightTagController;
import com.eternalcode.combat.fight.controller.FightUnTagController;
import com.eternalcode.combat.fight.death.DeathCommandController;
import com.eternalcode.combat.fight.death.DeathCommandExecutor;
import com.eternalcode.combat.fight.death.DeathCommandService;
import com.eternalcode.combat.fight.death.DeathFlareController;
import com.eternalcode.combat.fight.death.DeathLightningController;
import com.eternalcode.combat.fight.drop.DropKeepInventoryService;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.drop.DropService;
import com.eternalcode.combat.fight.effect.FightEffectService;
import com.eternalcode.combat.fight.firework.FireworkController;
import com.eternalcode.combat.fight.knockback.KnockbackService;
import com.eternalcode.combat.fight.tagout.FightTagOutService;
import com.eternalcode.combat.fight.pearl.FightPearlService;
import com.eternalcode.combat.handler.InvalidUsageHandlerImpl;
import com.eternalcode.combat.handler.MissingPermissionHandlerImpl;
import com.eternalcode.combat.config.ConfigService;
import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.death.KillerResolver;
import com.eternalcode.combat.fight.drop.DropController;
import com.eternalcode.combat.fight.drop.DropKeepInventoryService;
import com.eternalcode.combat.fight.drop.DropKeepInventoryServiceImpl;
import com.eternalcode.combat.fight.drop.DropService;
import com.eternalcode.combat.fight.drop.DropServiceImpl;
import com.eternalcode.combat.fight.drop.impl.PercentDropModifier;
import com.eternalcode.combat.fight.drop.impl.PlayersHealthDropModifier;
import com.eternalcode.combat.fight.FightTagCommand;
import com.eternalcode.combat.fight.controller.FightActionBlockerController;
import com.eternalcode.combat.fight.controller.FightMessageController;
import com.eternalcode.combat.fight.controller.FightTagController;
import com.eternalcode.combat.fight.controller.FightUnTagController;
import com.eternalcode.combat.fight.effect.FightEffectController;
import com.eternalcode.combat.event.EventManager;
import com.eternalcode.combat.fight.FightManagerImpl;
import com.eternalcode.combat.fight.FightTask;
import com.eternalcode.combat.fight.effect.FightEffectService;
import com.eternalcode.combat.fight.effect.FightEffectServiceImpl;
import com.eternalcode.combat.fight.firework.FireworkController;
import com.eternalcode.combat.fight.knockback.KnockbackRegionController;
import com.eternalcode.combat.fight.knockback.KnockbackService;
import com.eternalcode.combat.fight.logout.LogoutController;
import com.eternalcode.combat.fight.logout.LogoutService;
import com.eternalcode.combat.fight.pearl.FightPearlController;
import com.eternalcode.combat.fight.pearl.FightPearlService;
import com.eternalcode.combat.fight.pearl.FightPearlServiceImpl;
import com.eternalcode.combat.fight.tagout.FightTagOutCommand;
import com.eternalcode.combat.fight.tagout.FightTagOutController;
import com.eternalcode.combat.fight.tagout.FightTagOutService;
import com.eternalcode.combat.fight.tagout.FightTagOutServiceImpl;
import com.eternalcode.combat.fight.tagout.FightTagOutCommand;
import com.eternalcode.combat.handler.InvalidUsageHandlerImpl;
import com.eternalcode.combat.handler.MissingPermissionHandlerImpl;
import com.eternalcode.combat.notification.NoticeService;
import com.eternalcode.combat.fight.knockback.KnockbackRegionController;
import com.eternalcode.combat.region.RegionProvider;
import com.eternalcode.combat.updater.UpdaterNotificationController;
import com.eternalcode.combat.updater.UpdaterService;
Expand All @@ -62,7 +66,6 @@
import dev.rollczi.litecommands.bukkit.LiteBukkitFactory;
import dev.rollczi.litecommands.bukkit.LiteBukkitMessages;
import dev.rollczi.litecommands.folia.FoliaExtension;
import java.time.Duration;
import net.kyori.adventure.platform.AudienceProvider;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import net.kyori.adventure.text.minimessage.MiniMessage;
Expand All @@ -74,6 +77,7 @@
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

Expand Down Expand Up @@ -175,6 +179,10 @@ public void onEnable() {
new PlayersHealthDropModifier(pluginConfig.drop, logoutService)
).forEach(this.dropService::registerModifier);

KillerResolver killerResolver = new KillerResolver(this.fightManager, server, pluginConfig);
DeathCommandExecutor deathCommandExecutor = new DeathCommandExecutor(server);
DeathCommandService deathCommandService = new DeathCommandService(pluginConfig, this.fightManager, killerResolver, deathCommandExecutor);

eventManager.subscribe(
new FightTagController(this.fightManager, pluginConfig),
new FightUnTagController(this.fightManager, pluginConfig, logoutService),
Expand All @@ -183,6 +191,7 @@ public void onEnable() {
new FightBypassCreativeController(server, pluginConfig),
new FightActionBlockerController(this.fightManager, noticeService, pluginConfig, server),
new FightPearlController(pluginConfig.pearl, noticeService, this.fightManager, this.fightPearlService),
new DeathCommandController(deathCommandService, server),
new DeathFlareController(pluginConfig, server, scheduler, this),
new DeathLightningController(pluginConfig, server),
new UpdaterNotificationController(updaterService, pluginConfig, this.audienceProvider, miniMessage),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ public class PluginConfig extends OkaeriConfig {
@Comment({
" ",
"# Settings related to commands during combat.",
"# Configure command restrictions and behaviors for players in combat."
"# Configure command restrictions and behaviors for players in combat.",
"# You can also execute which commands will be executed post-death and on logout of the player."
})
public CommandSettings commands = new CommandSettings();

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

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.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerRespawnEvent;

public class DeathCommandController implements Listener {

private final DeathCommandService deathCommandService;
private final Server server;

public DeathCommandController(DeathCommandService deathCommandService, Server server) {
this.deathCommandService = deathCommandService;
this.server = server;
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
void onPlayerUntag(FightUntagEvent event) {
Player player = this.server.getPlayer(event.getPlayer());

if (player == null) {
return;
}

this.deathCommandService.handleUntag(player, event.getCause());
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
void onPlayerDeath(PlayerDeathEvent event) {
this.deathCommandService.handleDeath(event.getEntity());
}

@EventHandler(priority = EventPriority.MONITOR)
void onPlayerRespawn(PlayerRespawnEvent event) {
this.deathCommandService.handleRespawn(event.getPlayer());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.eternalcode.combat.fight.death;

import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;

import java.util.Collection;

public class DeathCommandExecutor {

private final Server server;

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

public void dispatch(DeathSettings.PostDeathCommandSettings.PostDeathCommands settings, Player player, String killerName) {
String playerName = player.getName();

this.dispatch(settings.console, this.server.getConsoleSender(), playerName, killerName);
this.dispatch(settings.player, player, playerName, killerName);
}

public void dispatch(Collection<String> commands, CommandSender sender, String playerName, String killerName) {
for (String command : commands) {
String resolved = this.replacePlaceholders(command, playerName, killerName);
this.server.dispatchCommand(sender, resolved);
}
}

private String replacePlaceholders(String command, String playerName, String killerName) {
return command
.replace("{player}", playerName)
.replace("{killer}", killerName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.eternalcode.combat.fight.death;

import com.eternalcode.combat.config.implementation.PluginConfig;
import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.fight.event.CauseOfUnTag;
import org.bukkit.entity.Player;

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class DeathCommandService {

private final PluginConfig config;
private final FightManager fightManager;
private final KillerResolver killerResolver;
private final DeathCommandExecutor executor;

private final Map<UUID, String> killerNames = new ConcurrentHashMap<>();
private final Set<UUID> handledByUntag = Collections.newSetFromMap(new ConcurrentHashMap<>());

public DeathCommandService(PluginConfig config, FightManager fightManager, KillerResolver killerResolver, DeathCommandExecutor executor) {
this.config = config;
this.fightManager = fightManager;
this.killerResolver = killerResolver;
this.executor = executor;
}

public void handleUntag(Player player, CauseOfUnTag cause) {
UUID playerUUID = player.getUniqueId();

if (cause == CauseOfUnTag.DEATH || cause == CauseOfUnTag.DEATH_BY_PLAYER) {
String killerName = this.killerResolver.resolveKillerName(playerUUID, player);
this.handleDeathInCombat(player, killerName);
this.handledByUntag.add(playerUUID);
this.killerNames.put(playerUUID, killerName);
return;
}

this.executor.dispatch(this.config.death.postDeathCommands.onUntag, player, this.config.death.postDeathCommands.unknownKillerPlaceholder);
}

public void handleDeath(Player player) {
UUID playerUUID = player.getUniqueId();
String killerName = this.killerResolver.resolveKillerName(playerUUID, player);

this.killerNames.putIfAbsent(playerUUID, killerName);

this.executor.dispatch(this.config.death.postDeathCommands.onAnyDeath, player, killerName);

if (this.handledByUntag.remove(playerUUID)) {
return;
}

if (this.fightManager.isInCombat(playerUUID)) {
this.handleDeathInCombat(player, killerName);
}
}

public void handleRespawn(Player player) {
UUID playerUUID = player.getUniqueId();

this.handledByUntag.remove(playerUUID);

String killerName = this.killerNames.remove(playerUUID);
if (killerName == null) {
killerName = this.config.death.postDeathCommands.unknownKillerPlaceholder;
}

this.executor.dispatch(this.config.death.postDeathCommands.afterRespawn, player, killerName);
}

private void handleDeathInCombat(Player player, String killerName) {
this.executor.dispatch(this.config.death.postDeathCommands.onDeathInCombat, player, killerName);

Player killer = this.killerResolver.resolveKiller(player.getUniqueId(), player);
if (killer != null) {
this.executor.dispatch(this.config.death.postDeathCommands.killerPostDeathCommands, killer, player.getName(), killerName);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import eu.okaeri.configs.annotation.Comment;
import org.bukkit.FireworkEffect;

import java.util.List;

public class DeathSettings extends OkaeriConfig {

@Comment({
Expand Down Expand Up @@ -74,4 +76,37 @@ public static class FlareSettings extends OkaeriConfig {
public int secondaryParticleCount = 3;

}

@Comment({
"Commands that will be executed after a player's death.",
"You can use {player} to represent the name of the player who died and {killer} for the killer's name (if applicable)."
})
public PostDeathCommandSettings postDeathCommands = new PostDeathCommandSettings();

public static class PostDeathCommandSettings extends OkaeriConfig {

public PostDeathCommands onDeathInCombat = new PostDeathCommands();

public PostDeathCommands onAnyDeath = new PostDeathCommands();

public PostDeathCommands afterRespawn = new PostDeathCommands();

public PostDeathCommands onUntag = new PostDeathCommands();

public static class PostDeathCommands extends OkaeriConfig {
public List<String> console = List.of();
public List<String> player = List.of();
}

@Comment({
"# List of commands that will be executed from the killer's perspective after killing a player.",
"# Use {player} to represent the name of the player who was killed and {killer} for the killer's name (if applicable)."
})
public List<String> killerPostDeathCommands = List.of(
"say You have killed {player} in combat!"
);

@Comment("# The returned string when the killer is unknown")
public String unknownKillerPlaceholder = "Unknown";
}
}
Loading