Skip to content

Commit

Permalink
refactor: arena exit clean up actions
Browse files Browse the repository at this point in the history
- create PlayerExitedArenaEvent
- on arena exit remove AllowShopScreenComponent (players only need the shop in-game)
- move check for condition changes that trigger a phase change into LASSystem
- switch player to white team instead of removing LASTeam component
- trigger arena exit clean up actions for disconnecting clients before they are disconnected (requires MovingBlocks/Terasology#5077)
  • Loading branch information
jdrueckert committed Nov 6, 2022
1 parent 171b29a commit 25b7d6e
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2022 The Terasology Foundation
// SPDX-License-Identifier: Apache-2.0

package org.terasology.module.lightandshadow.events;

import org.terasology.engine.entitySystem.entity.EntityRef;
import org.terasology.gestalt.entitysystem.event.Event;

public class PlayerExitedArenaEvent implements Event {
private final EntityRef player;

public PlayerExitedArenaEvent(EntityRef player) {
this.player = player;
}

public EntityRef getPlayer() {
return player;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.terasology.input.ButtonState;
import org.terasology.module.inventory.input.InventoryButton;
import org.terasology.module.lightandshadow.LASUtils;
import org.terasology.module.lightandshadow.events.PlayerExitedArenaEvent;
import org.terasology.module.lightandshadow.phases.OnPreGamePhaseStartedEvent;
import org.terasology.notifications.events.ExpireNotificationEvent;
import org.terasology.notifications.events.ShowNotificationEvent;
Expand All @@ -43,6 +44,11 @@ public void onPregameStart(OnPreGamePhaseStartedEvent event, EntityRef entity) {
entity.upsertComponent(AllowShopScreenComponent.class, c -> c.orElse(new AllowShopScreenComponent()));
}

@ReceiveEvent
public void onArenaExit(PlayerExitedArenaEvent event, EntityRef entity) {
entity.removeComponent(AllowShopScreenComponent.class);
}

/**
* Handles the button event if in-game shop is enabled.
* Needs to have a higher priority than {@link MarketUiClientSystem#onToggleInventory(InventoryButton, EntityRef)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package org.terasology.module.lightandshadow.systems;

import org.joml.Vector3f;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.economy.components.CurrencyStorageComponent;
import org.terasology.economy.events.WalletUpdatedEvent;
import org.terasology.engine.entitySystem.entity.EntityRef;
Expand All @@ -12,13 +14,18 @@
import org.terasology.engine.entitySystem.systems.RegisterSystem;
import org.terasology.engine.logic.characters.CharacterTeleportEvent;
import org.terasology.engine.logic.players.event.OnPlayerSpawnedEvent;
import org.terasology.engine.network.ClientComponent;
import org.terasology.engine.registry.In;
import org.terasology.engine.world.sun.CelestialSystem;
import org.terasology.gestalt.entitysystem.event.ReceiveEvent;
import org.terasology.module.inventory.components.InventoryComponent;
import org.terasology.module.inventory.events.RemoveItemAction;
import org.terasology.module.inventory.systems.InventoryManager;
import org.terasology.module.lightandshadow.LASUtils;
import org.terasology.module.lightandshadow.events.PlayerExitedArenaEvent;
import org.terasology.module.lightandshadow.phases.Phase;
import org.terasology.module.lightandshadow.phases.SwitchToPhaseEvent;
import org.terasology.module.lightandshadow.phases.authority.PhaseSystem;

@RegisterSystem
public class LASSystem extends BaseComponentSystem {
Expand All @@ -28,6 +35,12 @@ public class LASSystem extends BaseComponentSystem {
private CelestialSystem celestialSystem;
@In
private GameEntitySystem gameEntitySystem;
@In
private PhaseSystem phaseSystem;
@In
private TeamSystem teamSystem;

private static final Logger logger = LoggerFactory.getLogger(LASSystem.class);

/**
* Gives an empty inventory to a player in the lobby to prevent fight's in the lobby and gives the player some funds.
Expand All @@ -45,6 +58,28 @@ public void onPlayerSpawn(OnPlayerSpawnedEvent event, EntityRef player, Inventor
player.send(new CharacterTeleportEvent(new Vector3f(LASUtils.FLOATING_PLATFORM_POSITION).add(0, 1, 0)));
}

/**
* Follow-up actions necessary when a player leaves the arena, either by porting back to the platform
* or by disconnecting from the server.
* These action are required to verify the current game state and update the phase accordingly if necessary.
*/
@ReceiveEvent
public void onArenaExit(PlayerExitedArenaEvent event, EntityRef player) {
// if in game phase: verify that game start condition still met
Phase currentPhase = phaseSystem.getCurrentPhase();
if ((currentPhase == Phase.IN_GAME || currentPhase == Phase.COUNTDOWN) && !teamSystem.isMinSizeTeams()) {
logger.debug("Starting condition no longer met, switching from phase {} to PRE_GAME", currentPhase);
gameEntitySystem.getGameEntity().send(new SwitchToPhaseEvent(Phase.PRE_GAME));
}

// if the player teleporting was the last one still in the arena
// switch back to idle phase
if (teamSystem.getTeamSize(LASUtils.BLACK_TEAM) == 0 && teamSystem.getTeamSize(LASUtils.RED_TEAM) == 0) {
logger.debug("No players left in arena, switching to IDLE phase");
gameEntitySystem.getGameEntity().send(new SwitchToPhaseEvent(Phase.IDLE));
}
}

@Override
public void initialise() {
if (!celestialSystem.isSunHalted()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import org.slf4j.LoggerFactory;
import org.terasology.engine.entitySystem.entity.EntityRef;
import org.terasology.engine.entitySystem.entity.lifecycleEvents.OnChangedComponent;
import org.terasology.engine.entitySystem.event.EventPriority;
import org.terasology.engine.entitySystem.event.Priority;
import org.terasology.engine.entitySystem.systems.BaseComponentSystem;
import org.terasology.engine.entitySystem.systems.RegisterMode;
import org.terasology.engine.entitySystem.systems.RegisterSystem;
Expand All @@ -18,6 +20,7 @@
import org.terasology.module.lightandshadow.LASUtils;
import org.terasology.module.lightandshadow.components.LASConfigComponent;
import org.terasology.module.lightandshadow.components.LASTeamStatsComponent;
import org.terasology.module.lightandshadow.events.PlayerExitedArenaEvent;

@RegisterSystem(RegisterMode.AUTHORITY)
@Share(value = TeamSystem.class)
Expand All @@ -34,6 +37,16 @@ public void onTeamChange(OnChangedComponent event, EntityRef entity) {
entity.getComponent(LASTeamComponent.class).team);
}

@Priority(EventPriority.PRIORITY_HIGH)
@ReceiveEvent(components = LASTeamComponent.class)
public void onArenaExit(PlayerExitedArenaEvent event, EntityRef player) {
// players exiting the arena (e.g. by teleporting to platform or disconnecting from the game)
// should be removed from the playing teams
LASTeamComponent lasTeamComponent = player.getComponent(LASTeamComponent.class);
lasTeamComponent.team = LASUtils.WHITE_TEAM;
player.addOrSaveComponent(lasTeamComponent);
}

public boolean isBalancedTeams(String targetTeam) {
gameEntitySystem.updateTeamStats();
EntityRef gameEntity = gameEntitySystem.getGameEntity();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.terasology.engine.logic.permission.PermissionManager;
import org.terasology.engine.logic.players.SetDirectionEvent;
import org.terasology.engine.network.ClientComponent;
import org.terasology.engine.network.events.DisconnectedEvent;
import org.terasology.engine.network.events.BeforeDisconnectEvent;
import org.terasology.engine.registry.In;
import org.terasology.engine.utilities.Assets;
import org.terasology.gestalt.entitysystem.event.Event;
Expand All @@ -31,6 +31,7 @@
import org.terasology.module.inventory.events.RequestInventoryEvent;
import org.terasology.module.lightandshadow.LASUtils;
import org.terasology.module.lightandshadow.components.LASConfigComponent;
import org.terasology.module.lightandshadow.events.PlayerExitedArenaEvent;
import org.terasology.module.lightandshadow.events.TimerEvent;
import org.terasology.module.lightandshadow.phases.Phase;
import org.terasology.module.lightandshadow.phases.SwitchToPhaseEvent;
Expand All @@ -40,8 +41,8 @@
import java.util.function.Supplier;

/**
* Teleports players to play arena once they chose their team.
* It also sends events to change players skins and hud based on team they have chosen.
* Teleports players to play arena once they chose their team. It also sends events to change players skins and hud based on team they have
* chosen.
*
* @see ClientSkinSystem
*/
Expand All @@ -64,9 +65,8 @@ public class TeleporterSystem extends BaseComponentSystem {
private final Random random = new Random();

/**
* Depending on which teleporter the player chooses, they are set to that team
* and teleported to that base
* Assumption: there are two teleporters, one for the red, one for the black team
* Depending on which teleporter the player chooses, they are set to that team and teleported to that base Assumption: there are two
* teleporters, one for the red, one for the black team
*
* @param event
* @param entity
Expand Down Expand Up @@ -127,44 +127,19 @@ public String teleportToPlatform(@Sender EntityRef sender) {
LASTeamComponent senderTeam = clientComp.character.getComponent(LASTeamComponent.class);
if (senderTeam != null && (senderTeam.team.equals(LASUtils.RED_TEAM) || senderTeam.team.equals(LASUtils.BLACK_TEAM))) {
// spectators (white team) are not relevant for arena exit actions
performArenaExitActions(clientComp);
clientComp.character.send(new PlayerExitedArenaEvent(sender));
}
clientComp.character.send(new CharacterTeleportEvent(new Vector3f(LASUtils.FLOATING_PLATFORM_POSITION).add(0, 1, 0)));
return "Teleporting you to the platform.";
}

@ReceiveEvent(components = ClientComponent.class)
public void onPlayerDisconnect(DisconnectedEvent event, EntityRef entity) {
public void onPlayerDisconnect(BeforeDisconnectEvent event, EntityRef entity) {
ClientComponent clientComp = entity.getComponent(ClientComponent.class);
LASTeamComponent senderTeam = clientComp.character.getComponent(LASTeamComponent.class);
if (senderTeam != null && (senderTeam.team.equals(LASUtils.RED_TEAM) || senderTeam.team.equals(LASUtils.BLACK_TEAM))) {
// spectators (white team) are not relevant for arena exit actions
performArenaExitActions(clientComp);
}
}

/**
* Follow-up actions necessary when a player leaves the arena, either by porting back to the platform
* or by disconnecting from the server.
* These action are required to verify the current game state and update the phase accordingly if necessary.
*/
private void performArenaExitActions(ClientComponent clientComp) {
// players teleporting back to platform should be removed from the playing teams
// white team (spectator) members are allowed to teleport without losing their team
clientComp.character.removeComponent(LASTeamComponent.class);

// if in game phase: verify that game start condition still met
Phase currentPhase = phaseSystem.getCurrentPhase();
if ((currentPhase == Phase.IN_GAME || currentPhase == Phase.COUNTDOWN) && !teamSystem.isMinSizeTeams()) {
logger.debug("Starting condition no longer met, switching from phase {} to PRE_GAME", currentPhase);
gameEntitySystem.getGameEntity().send(new SwitchToPhaseEvent(Phase.PRE_GAME));
}

// if the player teleporting was the last one still in the arena
// switch back to idle phase
if (teamSystem.getTeamSize(LASUtils.BLACK_TEAM) == 0 && teamSystem.getTeamSize(LASUtils.RED_TEAM) == 0) {
logger.debug("No players left in arena, switching to IDLE phase");
gameEntitySystem.getGameEntity().send(new SwitchToPhaseEvent(Phase.IDLE));
teleportToPlatform(entity);
}
}
}

0 comments on commit 25b7d6e

Please sign in to comment.