Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: group mode duels never ended #138

Merged
merged 1 commit into from
Jan 30, 2025
Merged
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
2 changes: 1 addition & 1 deletion src/main/java/me/roinujnosde/titansbattle/BaseGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public BaseGame(TitansBattle plugin, BaseGameConfiguration config) {
this.gameManager = plugin.getGameManager();
this.config = config;
if (getConfig().isGroupMode() && groupManager == null) {
throw new IllegalStateException("gameManager cannot be null in a group mode game");
throw new IllegalStateException("groupManager cannot be null in a group mode game");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private void removeDuelist(@NotNull Warrior warrior) {
if (getConfig().isGroupMode()) {
if (lost(warrior)) {
Group group = getGroup(warrior);
groupDuelists.forEach(d -> d.isDuelist(group));
groupDuelists.forEach(d -> d.remove(group));
groupDuelists.removeIf(d -> d.getDuelists().isEmpty());
}
} else {
Expand Down Expand Up @@ -125,21 +125,25 @@ protected void processRemainingPlayers(@NotNull Warrior warrior) {
}
}

//died during semi-finals, goes for third place
if (getDuelsCount() == 2) {
if (config.isGroupMode()) {
Group group = getGroup(warrior);
//noinspection DataFlowIssue
casualties.stream().filter(p -> isMember(group, p)).forEach(waitingThirdPlace::add);
} else {
waitingThirdPlace.add(warrior);
}
Bukkit.getScheduler().runTaskLater(plugin, () -> {
//disconnected
waitingThirdPlace.removeIf(w -> w.toOnlinePlayer() == null);
}, 5L);
}

//delaying the next duel, so there is time for other players to respawn
Bukkit.getScheduler().runTaskLater(plugin, this::startNextDuel, 20L);
}

//died during semi-finals, goes for third place
if (getDuelsCount() == 2) {
waitingThirdPlace.add(warrior);
Bukkit.getScheduler().runTaskLater(plugin, () -> {
//disconnected
if (warrior.toOnlinePlayer() == null) {
waitingThirdPlace.remove(warrior);
}
}, 5L);
}

removeDuelist(warrior);
}

Expand Down
65 changes: 65 additions & 0 deletions src/test/java/me/roinujnosde/titansbattle/FakeGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package me.roinujnosde.titansbattle;

import me.roinujnosde.titansbattle.types.Group;
import me.roinujnosde.titansbattle.types.GroupData;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

public class FakeGroup extends Group {

private static int lastId = 0;
private final int id;
private final List<UUID> members = new ArrayList<>();

public FakeGroup(@NotNull GroupData data) {
super(data);
id = ++lastId;
}

@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
if (!super.equals(object)) return false;
FakeGroup fakeGroup = (FakeGroup) object;
return getId() == fakeGroup.getId();
}

@Override
public int hashCode() {
return Objects.hash(super.hashCode(), getId());
}

@Override
public @NotNull String getName() {
return Integer.toString(id);
}

@Override
public @NotNull String getId() {
return Integer.toString(id);
}

@Override
public void disband() {
throw new UnsupportedOperationException();
}

@Override
public boolean isMember(@NotNull UUID uuid) {
return members.contains(uuid);
}

public void addMember(@NotNull UUID uuid) {
members.add(uuid);
}

@Override
public boolean isLeaderOrOfficer(@NotNull UUID uuid) {
return members.contains(uuid) && members.get(0) == uuid;
}
}
6 changes: 5 additions & 1 deletion src/test/java/me/roinujnosde/titansbattle/FakePlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,12 @@ public class FakePlayer implements Player {
private final String name;

public FakePlayer() {
uuid = UUID.randomUUID();
this(UUID.randomUUID());
}

public FakePlayer(UUID uuid) {
name = Material.values()[(int) (Math.random() * Material.values().length)].name();
this.uuid = uuid;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@
import me.roinujnosde.titansbattle.managers.DatabaseManager;
import me.roinujnosde.titansbattle.managers.GameManager;
import me.roinujnosde.titansbattle.types.GameConfiguration;
import me.roinujnosde.titansbattle.types.GroupData;
import me.roinujnosde.titansbattle.types.Prizes;
import me.roinujnosde.titansbattle.types.Warrior;
import me.roinujnosde.titansbattle.types.Winners;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.PluginManager;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;

Expand All @@ -31,31 +28,33 @@

public class EliminationTournamentGameTest {


static Server server;
static PluginManager pluginManager;
static FakeBukkitScheduler scheduler = new FakeBukkitScheduler();
static TitansBattle plugin;
static FakeGroupManager groupManager;
static DatabaseManager databaseManager;
static GameConfiguration config;
static EliminationTournamentGame game;
EliminationTournamentGame game = new EliminationTournamentGame(plugin, config);


@BeforeAll
public static void setup() {
plugin = mock(TitansBattle.class);
Mockito.mockStatic(TitansBattle.class).when(TitansBattle::getInstance).thenReturn(plugin);

pluginManager = mock(PluginManager.class);

server = mock(Server.class);
when(server.getLogger()).thenReturn(mock(Logger.class));
when(server.getScheduler()).thenReturn(scheduler);
when(server.getPluginManager()).thenReturn(pluginManager);
when(server.getOfflinePlayer(any(UUID.class))).thenAnswer(i -> new FakePlayer(i.getArgument(0)));

databaseManager = mock(DatabaseManager.class);
when(databaseManager.getTodaysWinners()).thenReturn(mock(Winners.class));
databaseManager = new DatabaseManager();

FileConfiguration fileConfiguration = mock(FileConfiguration.class);

plugin = mock(TitansBattle.class);
when(plugin.getLogger()).thenReturn(mock(Logger.class));
when(plugin.getGameManager()).thenReturn(mock(GameManager.class));
when(plugin.getDatabaseManager()).thenReturn(databaseManager);
Expand All @@ -64,6 +63,9 @@ public static void setup() {
when(plugin.getConfig()).thenReturn(fileConfiguration);
when(fileConfiguration.getString(anyString(), anyString())).thenReturn("");

groupManager = new FakeGroupManager(plugin);
when(plugin.getGroupManager()).thenReturn(groupManager);

config = mock(GameConfiguration.class);
when(config.getAnnouncementStartingInterval()).thenReturn(5);
when(config.getAnnouncementStartingTimes()).thenReturn(2);
Expand All @@ -79,11 +81,6 @@ public static void setup() {
Bukkit.setServer(server);
}

@BeforeEach
public void setupGame() {
game = new EliminationTournamentGame(plugin, config);
}

@RepeatedTest(50)
public void simpleWinnerOdd(RepetitionInfo repetitionInfo) {
simpleWinner(repetitionInfo.getCurrentRepetition(), 1);
Expand All @@ -95,6 +92,8 @@ public void simpleWinnerEven(RepetitionInfo repetitionInfo) {
}

private void simpleWinner(int players, int oddOrEven) {
when(config.isGroupMode()).thenReturn(false);

game.start();
scheduler.performOneTick();
for (int i = 0; i < players; i++) {
Expand Down Expand Up @@ -129,4 +128,78 @@ private void simpleWinner(int players, int oddOrEven) {
assertEquals(1, expectedWinner.getVictories("test-game"));
}

@RepeatedTest(20)
public void groupModeOdd(RepetitionInfo repetitionInfo) {
groupMode(repetitionInfo.getCurrentRepetition(), 1);
}

@RepeatedTest(20)
public void groupModeEven(RepetitionInfo repetitionInfo) {
groupMode(repetitionInfo.getCurrentRepetition(), 0);
}

private void groupMode(int size, int oddOrEven) {
groupManager.getGroups().clear();
when(config.isGroupMode()).thenReturn(true);

game.start();
scheduler.performOneTick();
for (int i = 0; i < size; i++) {
FakeGroup group = new FakeGroup(new GroupData());
groupManager.addGroup(group);
for (int j = 0; j < 4 + oddOrEven; j++) {
Warrior warrior = databaseManager.getWarrior(UUID.randomUUID());
group.addMember(warrior.getUniqueId());

game.onJoin(warrior);
}
}

assertTrue(game.isLobby());
scheduler.performTicks(300); //lobby announcements
assertFalse(game.isLobby());

Warrior expectedWinner = game.getParticipants().get(0);

int count = 0;
while (game.getGroupParticipants().size() > 1) {
List<Warrior> current = new ArrayList<>(game.getCurrentFighters());
Warrior victim = null;
if (count % 2 == oddOrEven) {
List<Warrior> list = game.getParticipants().parallelStream().filter(w -> !current.contains(w) && w != expectedWinner).collect(Collectors.toList());
if (!list.isEmpty()) {
Warrior warrior = list.get(list.size() - 1);
game.onDisconnect(warrior);
}
} else {
Warrior killer = null;
for (Warrior warrior : current) {
if (warrior != expectedWinner) {
victim = warrior;
break;
}
}
for (Warrior warrior : current) {
if (victim != null && warrior != victim && warrior.getGroup() != victim.getGroup()) {
killer = warrior;
break;
}
}

if (victim != null && killer != null) {
game.onDeath(victim, killer);
} else {
throw new IllegalStateException();
}
}

scheduler.performTicks(21); //respawn delay
if (victim != null) {
assertTrue(game.getCasualties().contains(victim));
}
count++;
}
assertEquals(1, expectedWinner.getVictories("test-game"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package me.roinujnosde.titansbattle.games;

import me.roinujnosde.titansbattle.TitansBattle;
import me.roinujnosde.titansbattle.managers.GroupManager;
import me.roinujnosde.titansbattle.types.Group;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

public class FakeGroupManager extends GroupManager {

private final Set<Group> groups = new HashSet<>();

public FakeGroupManager(@NotNull TitansBattle plugin) {
super(plugin);
}

@Override
public @NotNull Set<Group> getGroups() {
return groups;
}

public void addGroup(@NotNull Group group) {
groups.add(group);
}

@Override
public @Nullable Group getGroup(@NotNull UUID uuid) {
for (Group group : groups) {
if (group.isMember(uuid)) {
return group;
}
}
return null;
}

@Override
public boolean sameGroup(@NotNull UUID player1, @NotNull UUID player2) {
Group firstGroup = getGroup(player1);
if (firstGroup == null) {
return false;
}
return firstGroup.equals(getGroup(player2));
}
}
Loading