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
13 changes: 12 additions & 1 deletion Hooks/Team-Lands/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
dependencies {
compileOnly("com.github.angeschossen:LandsAPI:6.44.6")
// Latest public Lands 8 API artifact.
compileOnly("com.incredibleplugins:lands-api:8.0.0")
testImplementation(project(":API"))
testImplementation("io.papermc.paper:paper-api:26.2.build.62-beta")
testImplementation("com.incredibleplugins:lands-api:8.0.0")
testImplementation("org.junit.jupiter:junit-jupiter:5.13.4")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.13.4")
testImplementation("org.mockito:mockito-core:5.18.0")
}

tasks.test {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import me.angeschossen.lands.api.LandsIntegration;
import me.angeschossen.lands.api.events.LandDeleteEvent;
import me.angeschossen.lands.api.land.Land;
import me.angeschossen.lands.api.land.enums.LandType;
import me.angeschossen.lands.api.player.LandPlayer;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
Expand All @@ -18,10 +20,15 @@
public class LandHook implements KothTeam {

private final KothPlugin plugin;
private final LandsIntegration lands;

public LandHook(KothPlugin plugin) {
super();
this(plugin, LandsIntegration.of(plugin));
}

LandHook(KothPlugin plugin, LandsIntegration lands) {
this.plugin = plugin;
this.lands = lands;
}

@Override
Expand All @@ -38,12 +45,25 @@ public List<Player> getOnlinePlayer(OfflinePlayer player) {
return new ArrayList<>(optional.get().getOnlinePlayers());
}

return Collections.singletonList(player.getPlayer());
Player onlinePlayer = player.getPlayer();
return onlinePlayer == null ? Collections.emptyList() : Collections.singletonList(onlinePlayer);
}

private Optional<? extends Land> getLandByPlayer(OfflinePlayer player) {
LandsIntegration api = LandsIntegration.of(this.plugin);
return api.getLandPlayer(player.getUniqueId()).getLands().stream().findFirst();
LandPlayer landPlayer = this.lands.getLandPlayer(player.getUniqueId());
if (landPlayer == null) return Optional.empty();

Land ownedLand = landPlayer.getOwningLand();
if (isUsableLand(ownedLand)) return Optional.of(ownedLand);

return landPlayer.getLands().stream()
.filter(this::isUsableLand)
.sorted((left, right) -> left.getULID().toString().compareTo(right.getULID().toString()))
.findFirst();
}

private boolean isUsableLand(Land land) {
return land != null && land.exists() && land.getLandType() == LandType.LAND && land.getULID() != null;
}

@Override
Expand All @@ -56,12 +76,13 @@ public String getLeaderName(OfflinePlayer player) {
@Override
public String getTeamId(OfflinePlayer player) {
Optional<? extends Land> optional = getLandByPlayer(player);
return optional.map(land -> String.valueOf(land.getId())).orElseGet(() -> player.getUniqueId().toString());
return optional.map(land -> land.getULID().toString()).orElseGet(() -> player.getUniqueId().toString());
}

@EventHandler
public void onDisband(LandDeleteEvent event) {
this.plugin.onTeamDisband(String.valueOf(event.getLand().getId()));
Land land = event.getLand();
if (land.getULID() != null) this.plugin.onTeamDisband(land.getULID().toString());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package fr.maxlego08.koth.hook.teams;

import fr.maxlego08.koth.api.KothPlugin;
import me.angeschossen.lands.api.LandsIntegration;
import me.angeschossen.lands.api.applicationframework.util.ULID;
import me.angeschossen.lands.api.events.LandDeleteEvent;
import me.angeschossen.lands.api.land.Land;
import me.angeschossen.lands.api.land.enums.LandType;
import me.angeschossen.lands.api.player.LandPlayer;
import org.bukkit.OfflinePlayer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class LandHookTest {

private final UUID playerId = UUID.fromString("7e8eeb2c-ffce-44ae-8935-692898e84067");
private KothPlugin plugin;
private LandsIntegration lands;
private OfflinePlayer player;
private LandPlayer landPlayer;
private LandHook hook;

@BeforeEach
void setUp() {
plugin = mock(KothPlugin.class);
lands = mock(LandsIntegration.class);
player = mock(OfflinePlayer.class);
landPlayer = mock(LandPlayer.class);
when(player.getUniqueId()).thenReturn(playerId);
when(lands.getLandPlayer(playerId)).thenReturn(landPlayer);
hook = new LandHook(plugin, lands);
}

@Test
void usesCurrentUlidForOwnedLand() {
Land ownedLand = usableLand("01JZKOTHOWNEDLAND0000000000");
when(landPlayer.getOwningLand()).thenReturn(ownedLand);

assertEquals("01JZKOTHOWNEDLAND0000000000", hook.getTeamId(player));
}

@Test
void choosesStableValidMembershipWhenPlayerOwnsNoLand() {
Land later = usableLand("01JZKOTHZZZZZZZZZZZZZZZZZ");
Land earlier = usableLand("01JZKOTHAAAAAAAAAAAAAAAAA");
Land deleted = usableLand("01JZKOTHDELETED0000000000");
when(deleted.exists()).thenReturn(false);
doReturn(List.of(later, deleted, earlier)).when(landPlayer).getLands();

assertEquals("01JZKOTHAAAAAAAAAAAAAAAAA", hook.getTeamId(player));
}

@Test
void fallsBackToPlayerUuidWithoutUsableLand() {
Land adminLand = usableLand("01JZKOTHADMIN000000000000");
when(adminLand.getLandType()).thenReturn(LandType.ADMIN);
doReturn(List.of(adminLand)).when(landPlayer).getLands();

assertEquals(playerId.toString(), hook.getTeamId(player));
}

@Test
void disbandUsesSameCurrentUlidIdentifier() {
Land land = usableLand("01JZKOTHDISBAND0000000000");
LandDeleteEvent event = mock(LandDeleteEvent.class);
when(event.getLand()).thenReturn(land);

hook.onDisband(event);

verify(plugin).onTeamDisband("01JZKOTHDISBAND0000000000");
}

private Land usableLand(String id) {
Land land = mock(Land.class);
ULID ulid = mock(ULID.class);
when(ulid.toString()).thenReturn(id);
when(land.exists()).thenReturn(true);
when(land.getLandType()).thenReturn(LandType.LAND);
when(land.getULID()).thenReturn(ulid);
return land;
}
}