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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,14 @@ fair, heart-pounding battles that keep players on their toes. Here’s a rundown
in action:
<img alt="Combat log anti logout feature" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/combatlog.gif?raw=true" width="420">

- **Support for newest features**
Our plugin features cooldown and delays for tridents, spears and much more. With **out of the box** configurable feats.
<img alt="Combat log anti logout feature" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/spear.gif?raw=true" width="420">

- **Customize combat experience**
Add custom effects to players in combat or death. Everything should be configurable and user-friendly:
<img alt="Lightning strikes when players die" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/lightning.gif?raw=true" width="420">

<img alt="Flare indicates players death location" src="https://github.com/EternalCodeTeam/EternalCombat/blob/master/assets/flare.gif?raw=true" width="420">

- **Spawn Protection (Configurable)**
Expand Down
Binary file added assets/spear.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ object Versions {

const val PLACEHOLDER_API = "2.12.3"
const val LANDS_API = "7.25.4"
const val WORLDEDIT = "3ISh7ADm" //cannot use numeric version bc of duplicated version on modrinth
const val PACKETEVENTS = "2.11.1"
const val WORLDGUARD = "7.0.15-beta-01"
const val LUCKPERMS = "5.5.17"

}

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

import java.time.Duration;
import java.util.UUID;

public interface SpearService {
boolean isOnCooldown(UUID uuid);
void saveCooldown(UUID uuid);
Duration getRemainingCooldown(UUID uuid);
void removeCooldown(UUID uuid);
}
Comment thread
CitralFlo marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
import com.eternalcode.combat.fight.pearl.PearlController;
import com.eternalcode.combat.fight.pearl.PearlService;
import com.eternalcode.combat.fight.pearl.PearlServiceImpl;
import com.eternalcode.combat.fight.spear.SpearLungeController;
import com.eternalcode.combat.fight.spear.SpearService;
import com.eternalcode.combat.fight.spear.SpearServiceImpl;
import com.eternalcode.combat.fight.tagout.FightTagOutCommand;
import com.eternalcode.combat.fight.tagout.FightTagOutController;
import com.eternalcode.combat.fight.tagout.FightTagOutService;
Expand Down Expand Up @@ -150,6 +153,8 @@ public void onEnable() {
BorderService borderService = new BorderServiceImpl(scheduler, server, regionProvider, eventManager, () -> pluginConfig.border);
KnockbackService knockbackService = new KnockbackService(pluginConfig, scheduler, regionProvider);

SpearService spearService = new SpearServiceImpl(pluginConfig.spear);

this.liteCommands = LiteBukkitFactory.builder(FALLBACK_PREFIX, this, server)
.message(LiteBukkitMessages.PLAYER_NOT_FOUND, pluginConfig.messagesSettings.playerNotFound)
.message(LiteBukkitMessages.PLAYER_ONLY, pluginConfig.messagesSettings.admin.onlyForPlayers)
Expand Down Expand Up @@ -214,6 +219,8 @@ public void onEnable() {

new KnockbackMountController(noticeService, this.regionProvider, this.fightManager).register(this);

new SpearLungeController(this, fightManager, spearService, pluginConfig.spear, noticeService);

eventManager.subscribe(
PlayerDeathEvent.class,
pluginConfig.drop.dropEventPriority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.eternalcode.combat.fight.effect.FightEffectSettings;
import com.eternalcode.combat.fight.knockback.KnockbackSettings;
import com.eternalcode.combat.fight.pearl.PearlSettings;
import com.eternalcode.combat.fight.spear.SpearSettings;
import com.eternalcode.combat.fight.trident.TridentSettings;
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
Expand Down Expand Up @@ -44,6 +45,13 @@ public class PluginConfig extends OkaeriConfig {
})
public TridentSettings trident = new TridentSettings();

@Comment({
" ",
"# Settings related to Spears with lunge",
"# Set cooldown for spear lunging"
})
public SpearSettings spear = new SpearSettings();

@Comment({
" ",
"# Custom effects applied during combat.",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.eternalcode.combat.fight.spear;

import com.eternalcode.combat.fight.FightManager;
import com.eternalcode.combat.notification.NoticeService;
import com.eternalcode.combat.util.DurationUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
Comment thread
CitralFlo marked this conversation as resolved.

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.UUID;

public class SpearLungeController implements Listener {

private final SpearService spearService;

public SpearLungeController(Plugin plugin, FightManager fightManager, SpearService spearService, SpearSettings settings, NoticeService noticeService) {
this.spearService = spearService;

try {
Class<? extends Event> lungeEventClass = Class.forName("io.papermc.paper.event.entity.EntityLungeEvent").asSubclass(Event.class);
MethodHandles.Lookup lookup = MethodHandles.lookup();

MethodHandle getEntityHandle = lookup.findVirtual(lungeEventClass, "getEntity", MethodType.methodType(Entity.class));
MethodHandle setCancelledHandle = lookup.findVirtual(lungeEventClass, "setCancelled", MethodType.methodType(void.class, boolean.class));

Bukkit.getPluginManager().registerEvent(
lungeEventClass,
this,
EventPriority.NORMAL,
(listener, event) -> {
if (!settings.lungeCooldown || !lungeEventClass.isInstance(event)) {
return;
}

try {
Entity entity = (Entity) getEntityHandle.invoke(event);

if (!(entity instanceof Player player)) {
return;
}

UUID uuid = player.getUniqueId();

if (settings.onlyForFight && !fightManager.isInCombat(uuid)) {
return;
}

if (this.spearService.isOnCooldown(uuid)) {
setCancelledHandle.invoke(event, true);

noticeService.create()
.player(uuid)
.notice(settings.lungeOnCooldown)
.placeholder("{TIME}", DurationUtil.format(spearService.getRemainingCooldown(uuid), !settings.useMillis))
.send();
} else {
spearService.saveCooldown(uuid);
}
} catch (Throwable e) {
plugin.getLogger().warning("Failed to handle EntityLungeEvent: " + e.getMessage());
}
},
plugin
);
} catch (ClassNotFoundException e) {
// Silently ignore: Server version is too old to have EntityLungeEvent
} catch (Throwable e) {
plugin.getLogger().warning("Failed to hook EntityLungeEvent: " + e.getMessage());
}
}
Comment thread
CitralFlo marked this conversation as resolved.

@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
this.spearService.removeCooldown(event.getPlayer().getUniqueId());
}
}
Comment thread
CitralFlo marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.eternalcode.combat.fight.spear;

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

public class SpearServiceImpl implements SpearService {

private final SpearSettings settings;
private final Map<UUID, Instant> cooldowns = new ConcurrentHashMap<>();

public SpearServiceImpl(SpearSettings settings) {
this.settings = settings;
}

@Override
public boolean isOnCooldown(UUID uuid) {
return !this.getRemainingCooldown(uuid).isZero();
}

@Override
public void saveCooldown(UUID uuid) {
this.cooldowns.put(uuid, Instant.now().plus(this.settings.lungeCooldownDuration));
}

@Override
public Duration getRemainingCooldown(UUID uuid) {
Instant expiration = this.cooldowns.get(uuid);

if (expiration == null) {
return Duration.ZERO;
}

Instant now = Instant.now();
if (now.isAfter(expiration)) {
this.cooldowns.remove(uuid);
return Duration.ZERO;
}

return Duration.between(now, expiration);
}

@Override
public void removeCooldown(UUID uuid) {
this.cooldowns.remove(uuid);
}
}
Comment thread
CitralFlo marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.eternalcode.combat.fight.spear;

import com.eternalcode.multification.notice.Notice;
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
import java.time.Duration;

public class SpearSettings extends OkaeriConfig {

@Comment("# Should spears have lunge cooldown or delay between uses? True for cooldown, False for vanilla mechanics")
public boolean lungeCooldown = false;

@Comment("# Should cooldown be applied only during fights")
public boolean onlyForFight = true;

@Comment("# Duration of cooldown")
public Duration lungeCooldownDuration = Duration.ofSeconds(5);

@Comment("# Should milliseconds be used for last second of cooldown for more precise time")
public boolean useMillis = true;

@Comment({
"# Notice sent to the players that try to use spears before cooldown ends.",
"# Placeholder: {TIME} - time left of cooldown"
})
public Notice lungeOnCooldown = Notice.builder().actionBar("<dark_red>Spear cannot be used for next <red>{TIME}</red></dark_red>")
.build();

}
Loading