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

feat: make plugin work in 1.14 #14

Merged
merged 3 commits into from
Apr 5, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public void onPlayerBedEnter(final PlayerBedEnterEvent event) {
skipper = new NightSkipper(plugin, world);
this.worldSkippers.put(worldName, skipper);
}

skipper.scheduleSkip();
}

@EventHandler
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package net.pupskuchen.timecontrol.nightskipping;

import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import net.pupskuchen.timecontrol.TimeControl;

class SkipAttempt extends BukkitRunnable {
private final NightSkipper skipper;

public SkipAttempt(final NightSkipper skipper) {
this.skipper = skipper;
}

@Override
public void run() {
this.skipper.skipNight();
}
}


class NightSkipScheduler {
private final TimeControl plugin;
private final NightSkipper skipper;
private final int sleepTicksToWake;

private BukkitTask skipTask;

public NightSkipScheduler(final TimeControl plugin, final NightSkipper skipper,
final int sleepTicksToWake) {
this.plugin = plugin;
this.skipper = skipper;
this.sleepTicksToWake = sleepTicksToWake;
}

public void scheduleSkip() {
this.cancel();
skipTask = new SkipAttempt(skipper).runTaskLater(plugin, sleepTicksToWake);
}

public void cancel() {
if (skipTask == null) {
return;
}

skipTask.cancel();
skipTask = null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,48 @@ public class NightSkipper {
private static final int SKIP_PERCENTAGE_FALLBACK = 100;

private final World world;
private final ConfigHandler config;
private final int skipPercentage;
private final TCLogger logger;
private final NightSkipScheduler skipScheduler;

public NightSkipper(final TimeControl plugin, final World world) {
this.world = world;
this.config = plugin.getConfigHandler();
this.logger = plugin.getTCLogger();
this.skipPercentage = getSkipPercentage(plugin.getConfigHandler());
this.skipScheduler = createSkipScheduler(plugin, world);
}

private int getSkipPercentage() {
public void scheduleSkip() {
if (skipScheduler == null || skipThresholdMet(false)) {
return;
}

skipScheduler.scheduleSkip();
logger.debug("Scheduled night skip for world \"%s\".", world.getName());
}

private void cancelScheduledSkip() {
if (skipScheduler != null) {
skipScheduler.cancel();
}
}

private NightSkipScheduler createSkipScheduler(final TimeControl plugin, final World world) {
if (!world.isGameRule("playersSleepingPercentage")) {
// In older versions, players aren't going to leave their beds by themselves,
// so we have to manually schedule the skip.
return new NightSkipScheduler(plugin, this, SKIPPABLE_SLEEP_TICKS + 1);
}

return null;
}

private int getSkipPercentage(final ConfigHandler config) {
if (!config.isPercentageEnabled(world)) {
try {
return world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE);
} catch (NoSuchFieldError e) {
logger.warn("Could not fetch game-rule value 'playersSleepingPercentage!"
logger.warn("Failed to read game rule 'playersSleepingPercentage!"
+ " Please enable players-sleeping-percentage in the plugin configuration.");
logger.warn("Using fallback percentage of %d %%.", SKIP_PERCENTAGE_FALLBACK);

Expand All @@ -44,33 +71,32 @@ private int getSkipPercentage() {
return config.getConfigPercentage(world);
}

private boolean skipThresholdMet() {
final int skipPercentage = getSkipPercentage();

private boolean skipThresholdMet(final boolean onlyFullyRested) {
if (skipPercentage <= 0) {
return true;
} else if (skipPercentage > 100) {
return false;
}

final int sleepTickThreshold = onlyFullyRested ? SKIPPABLE_SLEEP_TICKS : 1;
final List<Player> players = world.getPlayers();
final int sleeping = (int) players.stream()
.filter((player) -> player.getSleepTicks() >= SKIPPABLE_SLEEP_TICKS).count();
.filter((player) -> player.getSleepTicks() >= sleepTickThreshold).count();
final float sleepingPercentage = ((float) sleeping / players.size()) * 100;

return sleepingPercentage >= skipPercentage;
}

private boolean shouldSkipNight() {
public void skipNight() {
if (!TimeUtil.sleepAllowed(world)) {
return false;
return;
}

final boolean thresholdMet = skipThresholdMet();

return thresholdMet;
}
if (!skipThresholdMet(true)) {
if (!skipThresholdMet(false)) {
cancelScheduledSkip();
}

public void skipNight() {
if (!shouldSkipNight()) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: ${project.name}
main: net.pupskuchen.timecontrol.TimeControl
version: ${project.version}
api-version: 1.15
api-version: 1.14
author: pupskuchen
website: https://github.com/Pupskuchen/spigot-TimeControl
load: STARTUP
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void createSkipperAndStartGuard() {
NightSkipper skipper = mock.constructed().get(0);

verify(logger, times(1)).debug("%s (@ %s) entered a bed at %d", "somePlayerName", "someWorld", 15000L);
verifyNoInteractions(skipper);
verify(skipper).scheduleSkip();
}
}

Expand All @@ -119,7 +119,7 @@ public void restartExistingGuard() {
NightSkipper skipper = mock.constructed().get(0);

verify(logger, times(2)).debug("%s (@ %s) entered a bed at %d", "somePlayerName", "someWorld", 15000L);
verifyNoInteractions(skipper);
verify(skipper, times(2)).scheduleSkip();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.pupskuchen.timecontrol.nightskipping;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
Expand Down Expand Up @@ -35,16 +36,13 @@ public class NightSkipperTest {
@Mock
final World world = mock(World.class);

private NightSkipper skipper;

List<List<Player>> players = List.of(this.getPlayers(0, 50, 0), this.getPlayers(100, 50, 0),
this.getPlayers(100, 100, 50), this.getPlayers(100, 100, 100));

@BeforeEach
public void setup() {
when(plugin.getTCLogger()).thenReturn(logger);
when(plugin.getConfigHandler()).thenReturn(configManager);
skipper = new NightSkipper(plugin, world);
}

private Player getPlayer(int sleepTicks) {
Expand All @@ -58,10 +56,14 @@ private List<Player> getPlayers(int... sleepTicks) {

@Test
public void skipNightNoSleepAllowed() {
when(world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE)).thenReturn( 50);
final NightSkipper skipper = new NightSkipper(plugin, world);

try (MockedStatic<TimeUtil> mock = mockStatic(TimeUtil.class)) {
mock.when(() -> TimeUtil.sleepAllowed(world)).thenReturn(false);
skipper.skipNight();
verifyNoInteractions(world);
verify(world, times(0)).setTime(anyLong());
verify(world, times(0)).setTime(anyInt());
verifyNoInteractions(logger);
}
}
Expand All @@ -72,6 +74,8 @@ public void skipNightThresholdNotMet() {
when(world.getGameRuleValue(GameRule.PLAYERS_SLEEPING_PERCENTAGE)).thenReturn( 50);
when(world.getPlayers()).thenReturn(players.get(0));

final NightSkipper skipper = new NightSkipper(plugin, world);

try(MockedStatic<TimeUtil> mock = mockStatic(TimeUtil.class)) {
mock.when(() -> TimeUtil.sleepAllowed(world)).thenReturn(true);
skipper.skipNight();
Expand All @@ -86,6 +90,8 @@ public void skipNightByGameRule() {
when(world.getPlayers()).thenReturn(players.get(2));
when(world.getName()).thenReturn("fancy-world");

final NightSkipper skipper = new NightSkipper(plugin, world);

try(MockedStatic<TimeUtil> mock = mockStatic(TimeUtil.class)) {
mock.when(() -> TimeUtil.sleepAllowed(world)).thenReturn(true);
mock.when(() -> TimeUtil.getWakeTime(world)).thenReturn(123);
Expand All @@ -103,6 +109,7 @@ public void skipNightByByFallback() {
when(world.getPlayers()).thenReturn(players.get(2), players.get(3));
when(world.getName()).thenReturn("fancy-world");

final NightSkipper skipper = new NightSkipper(plugin, world);

try(MockedStatic<TimeUtil> mock = mockStatic(TimeUtil.class)) {
mock.when(() -> TimeUtil.sleepAllowed(world)).thenReturn(true);
Expand All @@ -111,9 +118,9 @@ public void skipNightByByFallback() {
verify(world, times(0)).setTime(anyLong());
skipper.skipNight();
verify(world, times(1)).setTime(123);
verify(logger, times(2)).warn("Could not fetch game-rule value 'playersSleepingPercentage!" +
" Please enable players-sleeping-percentage in the plugin configuration.");
verify(logger, times(2)).warn("Using fallback percentage of %d %%.", 100);
verify(logger, times(1)).warn("Failed to read game rule 'playersSleepingPercentage!"
+ " Please enable players-sleeping-percentage in the plugin configuration.");
verify(logger, times(1)).warn("Using fallback percentage of %d %%.", 100);

verify(logger, times(1)).info("Skipped the night on world \"%s\".", "fancy-world"); }

Expand All @@ -126,6 +133,8 @@ public void skipNightByByConfiguration() {
when(world.getPlayers()).thenReturn(players.get(2));
when(world.getName()).thenReturn("fancy-world");

final NightSkipper skipper = new NightSkipper(plugin, world);

try(MockedStatic<TimeUtil> mock = mockStatic(TimeUtil.class)) {
mock.when(() -> TimeUtil.sleepAllowed(world)).thenReturn(true);
mock.when(() -> TimeUtil.getWakeTime(world)).thenReturn(123);
Expand Down