Skip to content
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 @@ -4,24 +4,27 @@
import net.onelitefeather.cygnus.common.config.GameConfig;

/**
* This class calculates the amount of pages that should be allocated for the dynamic page system.
* The amount of pages is calculated based on the amount of players online.
* If the amount of players online is less than 4, the minimum amount of pages will be returned.
* Otherwise, the amount of pages will be calculated based on the amount of players online.
* Utility class for calculating the number of pages allocated for the dynamic page system.
* The page count is based on the number of current online players.
*
* @author theEvilReaper
* @version 1.0.0
* @version 1.1.0
* @since 1.0.0
*/

public final class PageCalculation {

private static final int PLAYER_SIZE_FOR_DYNAMIC_PAGE_ALLOCATION = 4;
private static final int PAGE_COUNT_MULTIPLIER = 2;

/**
* Calculates the amount of pages that should be allocated for the dynamic page system.
* Calculates the number of pages to allocate for the dynamic page system.
* <p>
* If the number of online players (excluding one) is less than {@value #PLAYER_SIZE_FOR_DYNAMIC_PAGE_ALLOCATION},
* {@link GameConfig#MIN_PAGE_COUNT} is returned. Otherwise, the page count is determined by
* multiplying the adjusted player count by {@value #PAGE_COUNT_MULTIPLIER}.
*
* @return the amount of pages that should be allocated
* @return the number of pages to allocate, at least {@link GameConfig#MIN_PAGE_COUNT}
*/
public static int calculatePageAmount() {
int currentPlayers = MinecraftServer.getConnectionManager().getOnlinePlayers().size();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@
import java.util.concurrent.CompletableFuture;

/**
* The {@link PageEntity} is a custom entity which represents a page that can be collected by the player.
* The entity is used to display the page and to interact with it.
* To improve the interaction the entity has a hitbox which is used to detect the interaction.
* Represents a collectible page entity that can be picked up by a player.
* The entity consists of a visual display and an interaction hitbox to improve pickup detection.
*
* @author theEvilReaper
* @version 1.0.0
* @version 1.1.0
* @since 1.0.0
**/
*/
@SuppressWarnings("java:S3252")
public final class PageEntity extends Entity {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.instance.Instance;
import net.minestom.server.utils.Direction;
import net.minestom.server.utils.validate.Check;
import net.onelitefeather.cygnus.common.Messages;
import net.onelitefeather.cygnus.common.page.event.PageDiscoveryCompletedEvent;
import net.onelitefeather.cygnus.common.util.Helper;
import net.theevilreaper.aves.util.Broadcaster;
import net.theevilreaper.aves.util.functional.VoidConsumer;
import net.theevilreaper.xerus.api.phase.GamePhase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -26,8 +28,10 @@
import static net.onelitefeather.cygnus.common.config.GameConfig.MIN_ACTIVE_PAGE_COUNT;

/**
* Handles the logic to manage and spawn pages during the {@link GamePhase}.
*
* @author theEvilReaper
* @version 1.0.0
* @version 1.1.0
* @since 1.0.0
**/
@SuppressWarnings("java:S3252")
Expand All @@ -37,7 +41,6 @@ public final class PageProvider {

private static final Lock CACHE_LOCK = new ReentrantLock();
private static final Lock PAGE_LOCK = new ReentrantLock();
private final VoidConsumer pageFinishFunction;
private final List<PageResource> globalCache;
private final Map<UUID, PageEntity> activePages;
private final Map<UUID, PageResource> usedResources;
Expand All @@ -47,8 +50,7 @@ public final class PageProvider {

private Component pageStatus = Component.empty();

public PageProvider(VoidConsumer pageFinishFunction) {
this.pageFinishFunction = pageFinishFunction;
public PageProvider() {
this.globalCache = new ArrayList<>();
this.usedResources = new HashMap<>();
this.activePages = new HashMap<>();
Expand All @@ -57,13 +59,18 @@ public PageProvider(VoidConsumer pageFinishFunction) {
this.currentPageCount = 1;
}

public void loadPageData(Set<PageResource> positions) {
/**
* Loads the required page data from the given set of {@link PageResource}s.
*
* @param resources given set of page resources
*/
public void loadPageData(Set<PageResource> resources) {
Check.argCondition(!globalCache.isEmpty(), "Can't load pages twice");

if (positions.isEmpty()) {
if (resources.isEmpty()) {
throw new IllegalStateException("Can't load a map without any pages");
}
this.globalCache.addAll(positions);
this.globalCache.addAll(resources);
}

public void collectStartPages(Instance instance) {
Expand All @@ -90,13 +97,21 @@ public void collectStartPages(Instance instance) {
LOGGER.info("This current page count is {}", currentPageCount);
}

/**
* Sets the max page amount.
*
* @param maxPageAmount to set
*/
public void setMaxPageAmount(int maxPageAmount) {
if (this.maxPageAmount != 0) {
throw new IllegalStateException("The max page amount can't be set twice");
}
this.maxPageAmount = maxPageAmount;
}

/**
* Spawns all pages that are currently in the active page map.
*/
public void spawn() {
this.updatePageDisplay();
try {
Expand All @@ -119,7 +134,6 @@ public void cleanUp() {
}

public void triggerTTLHandling(UUID uuid) {
// Fix #8: isEmpty-Check VOR removeEntity, damit activePages.get(uuid) noch gültig ist
if (this.globalCache.isEmpty()) {
this.activePages.get(uuid).enableInteraction();
return;
Expand All @@ -140,7 +154,6 @@ public void triggerTTLHandling(UUID uuid) {

pageEntity.teleport(Helper.updatePosition(newPos.position().asPos(), newPos.face()));

// Fix #6: activePages.put unter PAGE_LOCK statt CACHE_LOCK
try {
PAGE_LOCK.lock();
this.activePages.put(pageEntity.getHitBoxUUID(), pageEntity);
Expand All @@ -161,7 +174,7 @@ public void triggerPageFound(Player player, UUID uuid) {
updatePageData(pageEntity);

if (this.currentFoundedPageCount >= maxPageAmount) {
this.pageFinishFunction.apply();
EventDispatcher.call(new PageDiscoveryCompletedEvent());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
* during the GamePhase. It includes a string variable that represents the face used in the setup process.
* When spawning a page entity, it uses the opposite face from the provided face.
*
* @param position The position at which to spawn a page.
* @param face The face used in the resource setup process.
* @param position at which to spawn a page
* @param face used in the resource setup process
*/
public record PageResource(Point position, Direction face) { }
public record PageResource(Point position, Direction face) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.onelitefeather.cygnus.common.page.event;

import net.minestom.server.event.Event;

/**
* Event will be fired when each available page has been discovered by the players.
*
* @author theEvilReaper
* @version 1.0.0
* @since 2.3.1
*/
public class PageDiscoveryCompletedEvent implements Event {
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ void testPageTwiceLoading() {
Set<PageResource> pageResources = Set.of(
new PageResource(Pos.ZERO, Direction.NORTH)
);
PageProvider pageProvider = new PageProvider(() -> {});
PageProvider pageProvider = new PageProvider();
assertNotNull(pageProvider);

pageProvider.loadPageData(pageResources);
Expand All @@ -31,7 +31,7 @@ void testPageTwiceLoading() {

@Test
void testEmptyPageResourceUsage() {
PageProvider pageProvider = new PageProvider(() -> {});
PageProvider pageProvider = new PageProvider();
assertNotNull(pageProvider);
Set<PageResource> pageResources = Set.of();

Expand Down
11 changes: 4 additions & 7 deletions game/src/main/java/net/onelitefeather/cygnus/Cygnus.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package net.onelitefeather.cygnus;

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.page.PageDiscoveryCompleteListener;
import net.onelitefeather.cygnus.map.GameMapProvider;
import net.onelitefeather.cygnus.map.event.GameMapLoadedEvent;
import net.theevilreaper.aves.map.provider.AbstractMapProvider;
Expand Down Expand Up @@ -96,7 +98,7 @@ public Cygnus() {
this.staminaService = new StaminaService();
this.gameConfig = new GameConfigReader(path).getConfig();
MinecraftServer.getConnectionManager().setPlayerProvider(CygnusPlayer::new);
this.pageProvider = new PageProvider(this::handleAllPageFound);
this.pageProvider = new PageProvider();
this.mapProvider = new GameMapProvider(path);
this.view = new GameViewImpl(this::getViewComponent);
this.createTeams(this.gameConfig, this.teamService, this.ambientProvider);
Expand All @@ -112,12 +114,6 @@ private void initCommands() {
manager.register(new StartCommand(this.linearPhaseSeries));
}

private void handleAllPageFound() {
var gamePhase = (GamePhase) this.linearPhaseSeries.getCurrentPhase();
gamePhase.setFinishEvent(new GameFinishEvent(GameFinishEvent.Reason.ALL_PAGES_FOUND));
gamePhase.finish();
}

private void initListener() {
Supplier<Phase> phaseSupplier = this.linearPhaseSeries::getCurrentPhase;
var manager = MinecraftServer.getGlobalEventHandler();
Expand Down Expand Up @@ -155,6 +151,7 @@ private void registerGameListener() {
SlenderReviveEvent.class, new SlenderReviveListener(((GameMapProvider) this.mapProvider).getGameMap(), this.staminaService));
manager.addListener(GamePreLaunchEvent.class, new GamePreLaunchListener(this.pageProvider::setMaxPageAmount));
manager.addListener(StaminaStateChangeEvent.class, new StaminaStateChangeListener());
manager.addListener(PageDiscoveryCompletedEvent.class, new PageDiscoveryCompleteListener(this.linearPhaseSeries));
MinecraftServer.getPacketListenerManager().setPlayListener(ClientEntityActionPacket.class, CygnusEntityActionListener::listener);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.onelitefeather.cygnus.listener.page;

import net.onelitefeather.cygnus.common.page.event.PageDiscoveryCompletedEvent;
import net.onelitefeather.cygnus.event.GameFinishEvent;
import net.onelitefeather.cygnus.phase.GamePhase;
import net.theevilreaper.xerus.api.phase.LinearPhaseSeries;
import net.theevilreaper.xerus.api.phase.TimedPhase;

import java.util.function.Consumer;

public final class PageDiscoveryCompleteListener implements Consumer<PageDiscoveryCompletedEvent> {

private final LinearPhaseSeries<TimedPhase> phaseSeries;

public PageDiscoveryCompleteListener(LinearPhaseSeries<TimedPhase> phaseSeries) {
this.phaseSeries = phaseSeries;
}

@Override
public void accept(PageDiscoveryCompletedEvent event) {
if (!(this.phaseSeries.getCurrentPhase() instanceof GamePhase gamePhase)) return;
gamePhase.setFinishEvent(new GameFinishEvent(GameFinishEvent.Reason.ALL_PAGES_FOUND));
gamePhase.finish();
}
}
Loading