From 75f8945f9fb384fea3dd334571e22e9456975195 Mon Sep 17 00:00:00 2001 From: Josephine Rueckert Date: Sat, 4 Dec 2021 14:00:10 +0100 Subject: [PATCH] chore: update shop with economy, add notification --- module.txt | 5 ++ .../gooeyDefence/economy/ShopManager.java | 78 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/module.txt b/module.txt index 36603f1..eaabea4 100644 --- a/module.txt +++ b/module.txt @@ -28,6 +28,11 @@ { "id": "Inventory", "minVersion": "1.1.0" + }, + { + "id": "Notifications", + "minVersion": "0.1.0", + "maxVersion": "0.3.0" } ], "serverSideOnly": false, diff --git a/src/main/java/org/terasology/gooeyDefence/economy/ShopManager.java b/src/main/java/org/terasology/gooeyDefence/economy/ShopManager.java index c5abb50..1313009 100644 --- a/src/main/java/org/terasology/gooeyDefence/economy/ShopManager.java +++ b/src/main/java/org/terasology/gooeyDefence/economy/ShopManager.java @@ -2,10 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 package org.terasology.gooeyDefence.economy; +import org.terasology.economy.components.AllowShopScreenComponent; import org.terasology.economy.components.CurrencyStorageComponent; import org.terasology.economy.events.WalletUpdatedEvent; +import org.terasology.economy.ui.MarketUiClientSystem; +import org.terasology.engine.core.SimpleUri; +import org.terasology.engine.entitySystem.entity.lifecycleEvents.OnAddedComponent; import org.terasology.engine.entitySystem.event.EventPriority; +import org.terasology.engine.input.InputSystem; import org.terasology.engine.logic.players.event.OnPlayerSpawnedEvent; +import org.terasology.engine.network.ClientComponent; +import org.terasology.engine.network.events.ConnectedEvent; +import org.terasology.engine.unicode.EnclosedAlphanumerics; import org.terasology.gestalt.assets.management.AssetManager; import org.terasology.engine.entitySystem.entity.EntityManager; import org.terasology.engine.entitySystem.entity.EntityRef; @@ -13,11 +21,19 @@ import org.terasology.engine.entitySystem.prefab.Prefab; import org.terasology.engine.entitySystem.systems.BaseComponentSystem; import org.terasology.engine.entitySystem.systems.RegisterSystem; +import org.terasology.input.ButtonState; +import org.terasology.input.Input; import org.terasology.module.inventory.components.InventoryComponent; import org.terasology.engine.logic.players.LocalPlayer; import org.terasology.engine.registry.In; import org.terasology.gooeyDefence.DefenceUris; import org.terasology.gooeyDefence.events.OnFieldReset; +import org.terasology.module.inventory.input.InventoryButton; +import org.terasology.notifications.events.ExpireNotificationEvent; +import org.terasology.notifications.events.ShowNotificationEvent; +import org.terasology.notifications.model.Notification; +import org.terasology.nui.Color; +import org.terasology.nui.FontColor; import java.util.Optional; @@ -26,6 +42,10 @@ */ @RegisterSystem public class ShopManager extends BaseComponentSystem { + private static final String NOTIFICATION_ID = "GooeyDefence:firstTime"; + + @In + private InputSystem inputSystem; @In private AssetManager assetManager; @In @@ -35,11 +55,15 @@ public class ShopManager extends BaseComponentSystem { @ReceiveEvent(priority = EventPriority.PRIORITY_LOW) public void onPlayerJoin(OnPlayerSpawnedEvent onPlayerSpawnedEvent, EntityRef player, CurrencyStorageComponent currencyStorageComponent) { + // Fill player's wallet CurrencyStorageComponent component = assetManager.getAsset(DefenceUris.PLAYER, Prefab.class) .map(prefab -> prefab.getComponent(CurrencyStorageComponent.class)) .orElse(new CurrencyStorageComponent()); player.addOrSaveComponent(component); player.send(new WalletUpdatedEvent(component.amount)); + + // Ensure that the client has the {@link AllowShopScreenComponent} such that they can use the in-game shop from the Economy module. + localPlayer.getClientEntity().upsertComponent(AllowShopScreenComponent.class, c -> c.orElse(new AllowShopScreenComponent())); } @ReceiveEvent @@ -75,4 +99,58 @@ private void cleanUpMoney() { } } } + + /** + * Handles the button event if in-game shop is enabled. + * Needs to have a higher priority than {@link MarketUiClientSystem#onToggleInventory(InventoryButton, EntityRef)} + * to receive the {@link InventoryButton} event before it is consumed. + * + * @param event the help button event. + * @param entity the entity to display the help screen to. + */ + @ReceiveEvent(components = {ClientComponent.class, AllowShopScreenComponent.class}, priority = EventPriority.PRIORITY_CRITICAL) + public void onInGameShopButton(InventoryButton event, EntityRef entity) { + if (event.getState() == ButtonState.DOWN) { + entity.send(new ExpireNotificationEvent(NOTIFICATION_ID)); + } + } + + /** + * Get a formatted representation of the primary {@link Input} associated with the given button binding. + * + * If the display name of the primary bound key is a single character this representation will be the encircled + * character. Otherwise the full display name is used. The bound key will be printed in yellow. + * + * If no key binding was found the text "n/a" in red color is returned. + * + * @param button the URI of a bindable button + * @return a formatted text to be used as representation for the player + */ + //TODO: put this in a common place? Duplicated in Dialogs, EventualSkills, and InGameHelp + private String getActivationKey(SimpleUri button) { + return inputSystem.getInputsForBindButton(button).stream() + .findFirst() + .map(Input::getDisplayName) + .map(key -> { + if (key.length() == 1) { + // print the key in yellow within a circle + int off = key.charAt(0) - 'A'; + char code = (char) (EnclosedAlphanumerics.CIRCLED_LATIN_CAPITAL_LETTER_A + off); + return String.valueOf(code); + } else { + return key; + } + }) + .map(key -> FontColor.getColored(key, Color.yellow)) + .orElse(FontColor.getColored("n/a", Color.red)); + } + + @ReceiveEvent(components = AllowShopScreenComponent.class) + public void onShopComponentAdded(OnAddedComponent event, EntityRef entity) { + Notification notification = new Notification(NOTIFICATION_ID, + "Shut Up and Take My Money!", + "Press " + getActivationKey(new SimpleUri("Inventory:inventory")) + " to buy tower parts", + "Economy:GoldCoin"); + localPlayer.getClientEntity().send(new ShowNotificationEvent(notification)); + } }