Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ac0a158
WIP permission for back on death.
vLuckyyy Sep 13, 2025
32bce4b
Improve back logic
Jakubk15 Oct 4, 2025
1b130ad
Merge branch 'master' into back-on-deatch-permission-wip
Jakubk15 Oct 4, 2025
c733197
Update eternalcore-core/src/main/java/com/eternalcode/core/configurat…
Jakubk15 Oct 4, 2025
a2b33a8
Adjust to others' suggestions
Jakubk15 Oct 11, 2025
043f190
Document tpaTimer to also work for /back command
Jakubk15 Oct 11, 2025
98fc5f6
Simplify if-else statement
Jakubk15 Oct 11, 2025
d973b9c
Merge branch 'master' into back-on-deatch-permission-wip
Jakubk15 Oct 11, 2025
ad729d7
Merge branch 'master' into back-on-deatch-permission-wip
Jakubk15 Oct 18, 2025
ed16382
Add missing comma
Jakubk15 Oct 18, 2025
265a842
wip
Jakubk15 Oct 18, 2025
cc42f2d
Update messages
Jakubk15 Oct 18, 2025
75ea7fd
Adjust to others' suggestions (WIP)
Jakubk15 Oct 24, 2025
738ee16
Remove unused imports
Jakubk15 Oct 24, 2025
29b76e2
Create a default executor for /back command
Jakubk15 Oct 24, 2025
16362d6
Add proper permission to BackCommand
Jakubk15 Oct 25, 2025
8f7ffa1
Reduce nesting level
Jakubk15 Oct 25, 2025
282c4bd
Properly send a message to player when teleporting back
Jakubk15 Oct 25, 2025
b41d2d4
Fix ClassCastException
Jakubk15 Oct 25, 2025
ecae120
Revert accidental world name change
Jakubk15 Oct 28, 2025
52a5d8a
Encapsulate classes
Jakubk15 Oct 28, 2025
ca54463
Merge branch 'master' into back-on-deatch-permission-wip
Jakubk15 Nov 22, 2025
8a61a51
Delete deprecated translations in favor for the new dedicated back se…
Jakubk15 Nov 22, 2025
16b10fe
Fix comment formatting in TeleportRequestConfig
Jakubk15 Nov 22, 2025
5fc66b8
Merge branch 'master' into back-on-deatch-permission-wip
Jakubk15 Nov 30, 2025
6518f6c
Rename `backTeleportTimer` to `backTeleportTime` in BackSettings, Bac…
vLuckyyy Dec 1, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.eternalcode.core.feature.afk.AfkSettings;
import com.eternalcode.core.feature.automessage.AutoMessageConfig;
import com.eternalcode.core.feature.automessage.AutoMessageSettings;
import com.eternalcode.core.feature.back.BackConfig;
import com.eternalcode.core.feature.back.BackSettings;
import com.eternalcode.core.feature.broadcast.BroadcastConfig;
import com.eternalcode.core.feature.broadcast.BroadcastSettings;
import com.eternalcode.core.feature.butcher.ButcherConfig;
Expand Down Expand Up @@ -50,8 +52,6 @@
import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
import eu.okaeri.configs.annotation.Header;
import org.bukkit.Sound;

import java.io.File;

@Header({
Expand Down Expand Up @@ -213,6 +213,12 @@ public static class Format extends OkaeriConfig {
@Comment("# Settings responsible for player vanish functionality")
VanishConfig vanish = new VanishConfig();

@Bean(proxied = BackSettings.class)
@Comment("")
@Comment("# Back Configuration")
@Comment("# Settings for the /back command functionality")
BackConfig back = new BackConfig();

@Override
public File getConfigFile(File dataFolder) {
return new File(dataFolder, "config.yml");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.eternalcode.core.configuration.migrations;

import static eu.okaeri.configs.migrate.ConfigMigrationDsl.move;

import eu.okaeri.configs.migrate.builtin.NamedMigration;

public class Migration_0030_Move_back_to_dedicated_section extends NamedMigration {
Migration_0030_Move_back_to_dedicated_section() {
super(
"Move back to dedicated section",
move("teleport.teleportedToLastLocation", "back.teleportedToLastTeleportLocation"),
move("teleport.teleportedSpecifiedPlayerLastLocation", "back.teleportedTargetPlayerToLastTeleportLocation"),
move("teleport.lastLocationNoExist", "back.lastLocationNotFound")
);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class Migrations {
new Migration_0013_Move_enchant_messages_to_dedicated_section(),
new Migration_0014_Move_butcher_messages_to_dedicated_section(),
new Migration_0015_Move_ignore_messages_to_dedicated_section(),
new Migration_0030_Move_back_to_dedicated_section(),
new Migration_0031_Move_death_messages_to_dedicated_section(),
new Migration_0032_Move_join_quit_messages_to_dedicated_section(),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.eternalcode.core.feature.back;

import com.eternalcode.annotations.scan.command.DescriptionDocs;
import com.eternalcode.commons.bukkit.position.Position;
import com.eternalcode.commons.bukkit.position.PositionAdapter;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.notice.NoticeService;
import com.eternalcode.core.viewer.Viewer;
import dev.rollczi.litecommands.annotations.argument.Arg;
import dev.rollczi.litecommands.annotations.command.Command;
import dev.rollczi.litecommands.annotations.context.Sender;
import dev.rollczi.litecommands.annotations.execute.Execute;
import dev.rollczi.litecommands.annotations.permission.Permission;
import java.util.Optional;
import org.bukkit.entity.Player;

@Command(name = "back")
public class BackCommand {

private final BackService backService;
private final NoticeService noticeService;

@Inject
public BackCommand(BackService backService, NoticeService noticeService) {
this.backService = backService;
this.noticeService = noticeService;
}


@Execute
@Permission("eternalcore.back")
@DescriptionDocs(description = "Teleport to your last teleport/death location, depending which one is most recent")
public void executeBack(@Sender Player player) {
Optional<Position> latestPositionOptional = this.backService.getLatestLocation(player.getUniqueId());
if (latestPositionOptional.isEmpty()) {
this.noticeService.player(player.getUniqueId(), translation -> translation.back().lastLocationNotFound());
return;
}
Position latestPosition = latestPositionOptional.get();
Position deathPosition = this.backService.getDeathLocation(player.getUniqueId()).orElse(null);

if (latestPosition.equals(deathPosition)) {
this.executeBackDeath(player);
return;
}
this.executeBackTeleport(player);
}


@Execute(name = "teleport")
@Permission("eternalcore.back.teleport")
@DescriptionDocs(description = "Teleport to your last teleport location")
public void executeBackTeleport(@Sender Player player) {
if (this.teleportBack(player)) {
this.noticeService.player(player.getUniqueId(), translation -> translation.back().teleportedToLastTeleportLocation());
return;
}
this.noticeService.player(player.getUniqueId(), translation -> translation.back().lastLocationNotFound());
}

@Execute(name = "death")
@Permission("eternalcore.back.death")
@DescriptionDocs(description = "Teleport to your last death location")
public void executeBackDeath(@Sender Player player) {
if (this.teleportBackDeath(player)) {
this.noticeService.player(player.getUniqueId(), translation -> translation.back().teleportedToLastDeathLocation());
return;
}
this.noticeService.player(player.getUniqueId(), translation -> translation.back().lastLocationNotFound());
}

@Execute(name = "teleport")
@Permission("eternalcore.back.teleport.other")
@DescriptionDocs(description = "Teleport specified player to their last teleport location", arguments = "<player>")
public void executeBackTeleportOther(@Sender Viewer viewer, @Arg Player target) {
if (!this.teleportBack(target)) {
this.noticeService.player(viewer.getUniqueId(), translation -> translation.back().lastLocationNotFound());
return;
}

this.noticeService.player(target.getUniqueId(), translation -> translation.back().teleportedToLastTeleportLocationByAdmin());
this.noticeService.create()
.viewer(viewer)
.notice(translation -> translation.back().teleportedTargetPlayerToLastTeleportLocation())
.placeholder("{PLAYER}", target.getName())
.send();
}

@Execute(name = "death")
@Permission("eternalcore.back.death.other")
@DescriptionDocs(description = "Teleport specified player to their last death location", arguments = "<player>")
public void executeBackDeathOther(@Sender Viewer viewer, @Arg Player target) {
if (!this.teleportBackDeath(target)) {
this.noticeService.player(viewer.getUniqueId(), translation -> translation.back().lastLocationNotFound());
return;
}

this.noticeService.player(target.getUniqueId(), translation -> translation.back().teleportedToLastDeathLocationByAdmin());
this.noticeService.create()
.viewer(viewer)
.notice(translation -> translation.back().teleportedTargetPlayerToLastDeathLocation())
.placeholder("{PLAYER}", target.getName())
.send();

}

private boolean teleportBack(Player target) {
Optional<Position> teleportLocation = this.backService.getTeleportLocation(target.getUniqueId());

if (teleportLocation.isPresent()) {
this.backService.teleportBack(target, PositionAdapter.convert(teleportLocation.get()));

return true;
}
return false;
}

private boolean teleportBackDeath(Player target) {
Optional<Position> deathLocation = this.backService.getDeathLocation(target.getUniqueId());

if (deathLocation.isPresent()) {
this.backService.teleportBack(target, PositionAdapter.convert(deathLocation.get()));

return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.eternalcode.core.feature.back;

import eu.okaeri.configs.OkaeriConfig;
import eu.okaeri.configs.annotation.Comment;
import java.time.Duration;
import lombok.Getter;
import lombok.experimental.Accessors;

@Getter
@Accessors(fluent = true)
public class BackConfig extends OkaeriConfig implements BackSettings {

@Comment("# Time of teleportation time in /back command.")
public Duration backTeleportTimer = Duration.ofSeconds(5);

@Comment("# Duration of caching last locations for /back command.")
public Duration backLocationCacheDuration = Duration.ofHours(1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.eternalcode.core.feature.back;

import com.eternalcode.commons.bukkit.position.PositionAdapter;
import com.eternalcode.core.injector.annotations.Inject;
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.PlayerTeleportEvent;

public class BackController implements Listener {

private final BackService backService;

@Inject
public BackController(BackService backService) {
this.backService = backService;
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerDeath(PlayerDeathEvent event) {
Player entity = event.getEntity();

this.backService.markDeathLocation(entity.getUniqueId(), PositionAdapter.convert(entity.getLocation()));
}

@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) {
if (event.getCause() == PlayerTeleportEvent.TeleportCause.PLUGIN) {
return;
}

this.backService.markTeleportLocation(event.getPlayer().getUniqueId(), PositionAdapter.convert(event.getFrom()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.eternalcode.core.feature.back;

import com.eternalcode.commons.bukkit.position.Position;
import com.eternalcode.commons.bukkit.position.PositionAdapter;
import com.eternalcode.core.feature.teleport.TeleportService;
import com.eternalcode.core.feature.teleport.TeleportTaskService;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.injector.annotations.component.Service;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.entity.Player;

@Service
public class BackService {

private static final String BYPASS_PERMISSION = "eternalcore.teleport.bypass";

private final TeleportService teleportService;
private final TeleportTaskService teleportTaskService;
private final BackSettings settings;

private final Cache<UUID, Position> deathLocations;
private final Cache<UUID, Position> teleportLocations;
private final Cache<UUID, Position> latestLocations;

@Inject
public BackService(
TeleportService teleportService,
TeleportTaskService teleportTaskService,
BackSettings settings
) {
this.teleportService = teleportService;
this.teleportTaskService = teleportTaskService;
this.settings = settings;

this.deathLocations = Caffeine.newBuilder()
.expireAfterWrite(settings.backLocationCacheDuration())
.build();
this.teleportLocations = Caffeine.newBuilder()
.expireAfterWrite(settings.backLocationCacheDuration())
.build();
this.latestLocations = Caffeine.newBuilder()
.expireAfterWrite(settings.backLocationCacheDuration())
.build();
}

public Optional<Position> getDeathLocation(UUID playerId) {
return Optional.ofNullable(deathLocations.getIfPresent(playerId));
}

public Optional<Position> getTeleportLocation(UUID playerId) {
return Optional.ofNullable(teleportLocations.getIfPresent(playerId));
}

public Optional<Position> getLatestLocation(UUID playerId) {
return Optional.ofNullable(latestLocations.getIfPresent(playerId));
}

public void markDeathLocation(UUID player, Position position) {
this.deathLocations.put(player, position);
this.latestLocations.put(player, position);
}

public void markTeleportLocation(UUID player, Position position) {
this.teleportLocations.put(player, position);
this.latestLocations.put(player, position);
}

public void teleportBack(Player player, Location location) {
if (player.hasPermission(BYPASS_PERMISSION)) {
teleportService.teleport(player, location);
return;
}
teleportTaskService.createTeleport(
player.getUniqueId(),
PositionAdapter.convert(player.getLocation()),
PositionAdapter.convert(location),
settings.backTeleportTimer()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.eternalcode.core.feature.back;

import java.time.Duration;

public interface BackSettings {

Duration backTeleportTimer();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backTeleportTime


Duration backLocationCacheDuration();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.eternalcode.core.feature.back.messages;

import com.eternalcode.multification.notice.Notice;

public interface BackMessages {

Notice lastLocationNotFound();

Notice teleportedToLastTeleportLocation();
Notice teleportedTargetPlayerToLastTeleportLocation();
Notice teleportedToLastTeleportLocationByAdmin();

Notice teleportedToLastDeathLocation();
Notice teleportedTargetPlayerToLastDeathLocation();
Notice teleportedToLastDeathLocationByAdmin();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.eternalcode.core.feature.back.messages;

import com.eternalcode.multification.notice.Notice;
import eu.okaeri.configs.OkaeriConfig;
import lombok.Getter;
import lombok.experimental.Accessors;

@Getter
@Accessors(fluent = true)
public class ENBackMessages extends OkaeriConfig implements BackMessages {

public Notice lastLocationNotFound = Notice.chat(
"<red>► <white>You don't have any last location to teleport to!");

public Notice teleportedToLastTeleportLocation = Notice.chat(
"<green>► <white>You have been teleported to your last location!");
public Notice teleportedTargetPlayerToLastTeleportLocation = Notice.chat(
"<green>► <white>Player <green>{PLAYER} <white>has been teleported to their last location!");
public Notice teleportedToLastTeleportLocationByAdmin = Notice.chat(
"<green>► <white>You have been teleported to your last location by an administrator!");

public Notice teleportedToLastDeathLocation = Notice.chat(
"<green>► <white>You have been teleported to your last death location!");
public Notice teleportedTargetPlayerToLastDeathLocation = Notice.chat(
"<green>► <white>Player <green>{PLAYER} <white>has been teleported to their last death location!");
public Notice teleportedToLastDeathLocationByAdmin = Notice.chat(
"<green>► <white>You have been teleported to your last death location by an administrator!");
}
Loading