diff --git a/game/src/main/java/net/onelitefeather/cygnus/Cygnus.java b/game/src/main/java/net/onelitefeather/cygnus/Cygnus.java index 98df69d..5cdd665 100644 --- a/game/src/main/java/net/onelitefeather/cygnus/Cygnus.java +++ b/game/src/main/java/net/onelitefeather/cygnus/Cygnus.java @@ -3,18 +3,17 @@ import net.onelitefeather.cygnus.common.page.event.PageDiscoveryCompletedEvent; import net.onelitefeather.cygnus.event.GameStartEvent; import net.onelitefeather.cygnus.listener.game.GameStartListener; +import net.onelitefeather.cygnus.listener.view.ViewUpdateListener; import net.onelitefeather.cygnus.listener.page.PageDiscoveryCompleteListener; import net.onelitefeather.cygnus.map.GameMapProvider; import net.onelitefeather.cygnus.map.event.GameMapLoadedEvent; +import net.onelitefeather.cygnus.view.event.ViewUpdateEvent; import net.theevilreaper.aves.map.provider.AbstractMapProvider; -import net.theevilreaper.aves.util.Strings; -import net.theevilreaper.aves.util.TimeFormat; import net.theevilreaper.aves.util.functional.VoidConsumer; import net.theevilreaper.xerus.api.phase.LinearPhaseSeries; import net.theevilreaper.xerus.api.phase.Phase; import net.theevilreaper.xerus.api.phase.TimedPhase; import net.theevilreaper.xerus.api.team.TeamService; -import net.kyori.adventure.text.Component; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; @@ -28,7 +27,6 @@ import net.onelitefeather.cygnus.ambient.AmbientProvider; import net.onelitefeather.cygnus.command.StartCommand; import net.onelitefeather.cygnus.common.ListenerHandling; -import net.onelitefeather.cygnus.common.Messages; import net.onelitefeather.cygnus.common.config.GameConfig; import net.onelitefeather.cygnus.common.config.GameConfigReader; import net.onelitefeather.cygnus.common.event.GamePreLaunchEvent; @@ -100,7 +98,7 @@ public Cygnus() { MinecraftServer.getConnectionManager().setPlayerProvider(CygnusPlayer::new); this.pageProvider = new PageProvider(); this.mapProvider = new GameMapProvider(path); - this.view = new GameViewImpl(this::getViewComponent); + this.view = new GameViewImpl(); this.createTeams(this.gameConfig, this.teamService, this.ambientProvider); this.initPhases(); this.initCommands(); @@ -152,6 +150,8 @@ private void registerGameListener() { manager.addListener(GamePreLaunchEvent.class, new GamePreLaunchListener(this.pageProvider::setMaxPageAmount)); manager.addListener(StaminaStateChangeEvent.class, new StaminaStateChangeListener()); manager.addListener(PageDiscoveryCompletedEvent.class, new PageDiscoveryCompleteListener(this.linearPhaseSeries)); + manager.addListener(ViewUpdateEvent.class, new ViewUpdateListener(this.view, this.pageProvider)); + MinecraftServer.getPacketListenerManager().setPlayListener(ClientEntityActionPacket.class, CygnusEntityActionListener::listener); } @@ -180,14 +180,6 @@ private void finishGame() { MinecraftServer.getPacketListenerManager().setPlayListener(ClientEntityActionPacket.class, EntityActionListener::listener); } - private @NotNull Component getViewComponent() { - var gamePhase = (GamePhase) this.linearPhaseSeries.getCurrentPhase(); - return Messages.getViewComponent( - Strings.getTimeString(TimeFormat.MM_SS, gamePhase.getCurrentTicks()), - this.pageProvider.getPageStatus() - ); - } - private void triggerViewRuleUpdate(@NotNull Player player) { ViewRuleUpdater.updateViewer(player, this.teamService.getTeams().get(Helper.SURVIVOR_ID)); } diff --git a/game/src/main/java/net/onelitefeather/cygnus/listener/view/ViewUpdateListener.java b/game/src/main/java/net/onelitefeather/cygnus/listener/view/ViewUpdateListener.java new file mode 100644 index 0000000..920450a --- /dev/null +++ b/game/src/main/java/net/onelitefeather/cygnus/listener/view/ViewUpdateListener.java @@ -0,0 +1,34 @@ +package net.onelitefeather.cygnus.listener.view; + +import net.kyori.adventure.text.Component; +import net.onelitefeather.cygnus.common.Messages; +import net.onelitefeather.cygnus.common.page.PageProvider; +import net.onelitefeather.cygnus.phase.GamePhase; +import net.onelitefeather.cygnus.view.GameView; +import net.onelitefeather.cygnus.view.event.ViewUpdateEvent; +import net.theevilreaper.aves.util.Strings; +import net.theevilreaper.aves.util.TimeFormat; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +public class ViewUpdateListener implements Consumer { + + private final GameView gameView; + private final PageProvider pageProvider; + + public ViewUpdateListener(GameView gameView, PageProvider pageProvider) { + this.gameView = gameView; + this.pageProvider = pageProvider; + } + + @Override + public void accept(ViewUpdateEvent event) { + int ticks = event.ticks(); + Component component = Messages.getViewComponent( + Strings.getTimeString(TimeFormat.MM_SS, ticks), + this.pageProvider.getPageStatus() + ); + this.gameView.updateView(component); + } +} diff --git a/game/src/main/java/net/onelitefeather/cygnus/listener/view/package-info.java b/game/src/main/java/net/onelitefeather/cygnus/listener/view/package-info.java new file mode 100644 index 0000000..76c7451 --- /dev/null +++ b/game/src/main/java/net/onelitefeather/cygnus/listener/view/package-info.java @@ -0,0 +1,4 @@ +@NotNullByDefault +package net.onelitefeather.cygnus.listener.view; + +import org.jetbrains.annotations.NotNullByDefault; \ No newline at end of file diff --git a/game/src/main/java/net/onelitefeather/cygnus/phase/GamePhase.java b/game/src/main/java/net/onelitefeather/cygnus/phase/GamePhase.java index c109d51..5bd2152 100644 --- a/game/src/main/java/net/onelitefeather/cygnus/phase/GamePhase.java +++ b/game/src/main/java/net/onelitefeather/cygnus/phase/GamePhase.java @@ -2,6 +2,7 @@ import net.minestom.server.event.EventDispatcher; import net.onelitefeather.cygnus.event.GameStartEvent; +import net.onelitefeather.cygnus.view.event.ViewUpdateEvent; import net.theevilreaper.xerus.api.phase.TickDirection; import net.theevilreaper.xerus.api.phase.TimedPhase; import net.minestom.server.MinecraftServer; @@ -72,6 +73,6 @@ protected void onFinish() { */ @Override public void onUpdate() { - this.gameView.updateView(); + EventDispatcher.call(new ViewUpdateEvent(getCurrentTicks())); } } diff --git a/game/src/main/java/net/onelitefeather/cygnus/view/GameView.java b/game/src/main/java/net/onelitefeather/cygnus/view/GameView.java index 66c2077..17e0ad5 100644 --- a/game/src/main/java/net/onelitefeather/cygnus/view/GameView.java +++ b/game/src/main/java/net/onelitefeather/cygnus/view/GameView.java @@ -1,8 +1,21 @@ package net.onelitefeather.cygnus.view; +import net.kyori.adventure.text.Component; import net.theevilreaper.xerus.api.Joinable; +/** + * Represents a view that can be displayed to players + * + * @author theEvilReaper + * @version 1.1.0 + * @since 0.1.0 + */ public interface GameView extends Joinable { - void updateView(); + /** + * Updates the view with a new {@link Component} to display + * + * @param component to display + */ + void updateView(Component component); } diff --git a/game/src/main/java/net/onelitefeather/cygnus/view/GameViewImpl.java b/game/src/main/java/net/onelitefeather/cygnus/view/GameViewImpl.java index d44f624..2cdc8ac 100644 --- a/game/src/main/java/net/onelitefeather/cygnus/view/GameViewImpl.java +++ b/game/src/main/java/net/onelitefeather/cygnus/view/GameViewImpl.java @@ -11,16 +11,14 @@ public final class GameViewImpl implements GameView { private final BossBar bossBar; - private final ViewUpdater updateFunction; - public GameViewImpl(ViewUpdater updateFunction) { - this.updateFunction = updateFunction; + public GameViewImpl() { this.bossBar = BossBar.bossBar(Component.empty(), 1f, BossBar.Color.WHITE, BossBar.Overlay.PROGRESS); } @Override - public void updateView() { - this.bossBar.name(this.updateFunction.updateView()); + public void updateView(Component component) { + this.bossBar.name(component); } @Override diff --git a/game/src/main/java/net/onelitefeather/cygnus/view/ViewUpdater.java b/game/src/main/java/net/onelitefeather/cygnus/view/ViewUpdater.java deleted file mode 100644 index 4ae33c5..0000000 --- a/game/src/main/java/net/onelitefeather/cygnus/view/ViewUpdater.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.onelitefeather.cygnus.view; - -import net.kyori.adventure.text.Component; - -@FunctionalInterface -public interface ViewUpdater { - - Component updateView(); -} diff --git a/game/src/main/java/net/onelitefeather/cygnus/view/event/ViewUpdateEvent.java b/game/src/main/java/net/onelitefeather/cygnus/view/event/ViewUpdateEvent.java new file mode 100644 index 0000000..29a0de8 --- /dev/null +++ b/game/src/main/java/net/onelitefeather/cygnus/view/event/ViewUpdateEvent.java @@ -0,0 +1,14 @@ +package net.onelitefeather.cygnus.view.event; + +import net.minestom.server.event.Event; + +/** + * The event is used that the {@link net.onelitefeather.cygnus.view.GameView} needs to be updated. + * + * @param ticks value to update the view + * @author theEvilReaper + * @version 1.0.0 + * @since 2.3.1 + */ +public record ViewUpdateEvent(int ticks) implements Event { +} diff --git a/game/src/test/java/net/onelitefeather/cygnus/view/GameViewIntegrationTest.java b/game/src/test/java/net/onelitefeather/cygnus/view/GameViewIntegrationTest.java new file mode 100644 index 0000000..46dc8fd --- /dev/null +++ b/game/src/test/java/net/onelitefeather/cygnus/view/GameViewIntegrationTest.java @@ -0,0 +1,75 @@ +package net.onelitefeather.cygnus.view; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import net.minestom.server.entity.Player; +import net.minestom.server.event.EventFilter; +import net.minestom.server.instance.Instance; +import net.minestom.server.network.packet.server.play.BossBarPacket; +import net.minestom.testing.Collector; +import net.minestom.testing.Env; +import net.minestom.testing.TestConnection; +import net.minestom.testing.extension.MicrotusExtension; +import net.onelitefeather.cygnus.common.page.PageProvider; +import net.onelitefeather.cygnus.listener.view.ViewUpdateListener; +import net.onelitefeather.cygnus.view.event.ViewUpdateEvent; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MicrotusExtension.class) +class GameViewIntegrationTest { + + @Disabled("Investigate why this test is broken") + @Test + void testViewUpdate(Env env) { + Instance instance = env.createEmptyInstance(); + TestConnection connection = env.createConnection(); + Player player = connection.connect(instance); + GameView gameView = new GameViewImpl(); + PageProvider pageProvider = new PageProvider(); + + env.process().eventHandler().addListener(ViewUpdateEvent.class, new ViewUpdateListener(gameView, pageProvider)); + + Collector barCollector = connection.trackIncoming(BossBarPacket.class); + + gameView.addPlayer(player); + + barCollector.assertSingle(); + + ViewUpdateEvent updateEvent = new ViewUpdateEvent(100); + + EventFilter filter = EventFilter.from( + ViewUpdateEvent.class, + ViewUpdateEvent.class, + e -> e + ); + Collector eventCollector = env.trackEvent(ViewUpdateEvent.class, filter, updateEvent); + Collector secondBarCollector = connection.trackIncoming(BossBarPacket.class); + + env.process().eventHandler().call(updateEvent); + + env.tick(); + + eventCollector.assertSingle(); + eventCollector.assertSingle(event -> { + assertEquals(updateEvent.ticks(), event.ticks()); + }); + + secondBarCollector.assertSingle(bossBarPacket -> { + assertInstanceOf(BossBarPacket.UpdateTitleAction.class, bossBarPacket.action()); + + BossBarPacket.UpdateTitleAction updateTitle = ((BossBarPacket.UpdateTitleAction) bossBarPacket.action()); + assertEquals(1, updateTitle.components().size()); + Component component = updateTitle.components().stream().findAny().orElse(Component.empty()); + assertNotEquals(component, Component.empty()); + + String content = PlainTextComponentSerializer.plainText().serialize(component); + assertTrue(content.contains("Time: 01:40")); + }); + + env.destroyInstance(instance, true); + } +} diff --git a/game/src/test/java/net/onelitefeather/cygnus/view/event/ViewUpdateEventTest.java b/game/src/test/java/net/onelitefeather/cygnus/view/event/ViewUpdateEventTest.java new file mode 100644 index 0000000..826f49f --- /dev/null +++ b/game/src/test/java/net/onelitefeather/cygnus/view/event/ViewUpdateEventTest.java @@ -0,0 +1,16 @@ +package net.onelitefeather.cygnus.view.event; + +import net.minestom.server.event.Event; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ViewUpdateEventTest { + + @Test + void testEventCreation() { + ViewUpdateEvent viewUpdateEvent = new ViewUpdateEvent(100); + assertEquals(100, viewUpdateEvent.ticks()); + assertInstanceOf(Event.class, viewUpdateEvent); + } +}