From c94d54c1f622a0ff5c5e7c308da6643805292498 Mon Sep 17 00:00:00 2001 From: Mayant Mukul Date: Tue, 6 Aug 2019 15:59:18 +0530 Subject: [PATCH 1/6] Add basic fetch quests --- assets/prefabs/quests/card.prefab | 32 +++++ module.txt | 3 +- .../quests/FetchQuestSystem.java | 114 ++++++++++++++++++ .../metalrenegades/quests/TaskOverlay.java | 32 +++++ 4 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 assets/prefabs/quests/card.prefab create mode 100644 src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java create mode 100644 src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java diff --git a/assets/prefabs/quests/card.prefab b/assets/prefabs/quests/card.prefab new file mode 100644 index 00000000..c7362384 --- /dev/null +++ b/assets/prefabs/quests/card.prefab @@ -0,0 +1,32 @@ +{ + "DisplayName" : { + "name" : "Quest Card" + }, + "Item" : { + "icon" : "Tasks:icons#Questing", + "usage" : "ON_USER", + "consumedOnUse" : true + }, + "Quest" : { + "shortName" : "FetchQuest", + "description" : "Bring me some meat!", + "tasks" : [ + { + "id" : "collectMeat", + "type" : "CollectBlocksTask", + "data" : { + "itemId" : "block:core:Dirt", + "amount" : 3 + } + }, + { + "id" : "returnHome", + "type" : "GoToBeaconTask", + "dependsOn" : "collectMeat", + "data" : { + "beaconId" : "homeBeacon" + } + } + ] + } +} diff --git a/module.txt b/module.txt index 8186f937..3f26e751 100644 --- a/module.txt +++ b/module.txt @@ -15,7 +15,8 @@ {"id" : "CombatSystem", "minVersion" : "0.1.1"}, {"id" : "WildAnimals", "minVersion" : "0.2.0"}, {"id" : "Dialogs", "minVersion" : "0.1.0"}, - {"id": "Hunger", "minVersion": "1.0.1"} + {"id" : "Hunger", "minVersion": "1.0.1"}, + {"id" : "Tasks", "minVersion": "0.2.0"} ], "serverSideOnly" : false, "isGameplay" : true, diff --git a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java new file mode 100644 index 00000000..52086458 --- /dev/null +++ b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java @@ -0,0 +1,114 @@ +/* + * Copyright 2019 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.metalrenegades.quests; + +import org.terasology.dynamicCities.buildings.GenericBuildingComponent; +import org.terasology.dynamicCities.buildings.components.DynParcelRefComponent; +import org.terasology.dynamicCities.buildings.components.SettlementRefComponent; +import org.terasology.dynamicCities.construction.events.BuildingEntitySpawnedEvent; +import org.terasology.dynamicCities.parcels.DynParcel; +import org.terasology.entitySystem.entity.EntityManager; +import org.terasology.entitySystem.entity.EntityRef; +import org.terasology.entitySystem.event.ReceiveEvent; +import org.terasology.entitySystem.prefab.Prefab; +import org.terasology.entitySystem.systems.BaseComponentSystem; +import org.terasology.entitySystem.systems.RegisterMode; +import org.terasology.entitySystem.systems.RegisterSystem; +import org.terasology.logic.location.LocationComponent; +import org.terasology.logic.nameTags.NameTagComponent; +import org.terasology.math.geom.Rect2i; +import org.terasology.math.geom.Vector3f; +import org.terasology.registry.In; +import org.terasology.rendering.nui.Color; +import org.terasology.tasks.components.QuestListComponent; +import org.terasology.tasks.components.QuestSourceComponent; +import org.terasology.tasks.events.BeforeQuestEvent; +import org.terasology.tasks.events.StartTaskEvent; +import org.terasology.utilities.Assets; + +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; + +@RegisterSystem(RegisterMode.CLIENT) +public class FetchQuestSystem extends BaseComponentSystem { + + @In + private EntityManager entityManager; + + private EntityRef activeQuestEntity; + + private final String HOME_TASK_ID = "returnHome"; + private final String FETCH_QUEST_ID = "FetchQuest"; + + @ReceiveEvent(components = GenericBuildingComponent.class) + public void onMarketPlaceSpawn(BuildingEntitySpawnedEvent event, EntityRef entityRef) { + GenericBuildingComponent genericBuildingComponent = entityRef.getComponent(GenericBuildingComponent.class); + if (genericBuildingComponent.name.equals("marketplace")) { + DynParcel dynParcel = entityRef.getComponent(DynParcelRefComponent.class).dynParcel; + + Optional questPointOptional = Assets.getPrefab("Tasks:QuestPoint"); + if (questPointOptional.isPresent()) { + Rect2i rect2i = dynParcel.shape; + Vector3f spawnPosition = new Vector3f(rect2i.minX() + rect2i.sizeX() / 2, dynParcel.getHeight() + 10, rect2i.minY() + rect2i.sizeY() / 2); + EntityRef questPoint = entityManager.create(questPointOptional.get(), spawnPosition); + SettlementRefComponent settlementRefComponent = entityRef.getComponent(SettlementRefComponent.class); + questPoint.addComponent(settlementRefComponent); + + // Prepare the QuestListComponent + QuestListComponent questListComponent = new QuestListComponent(); + questListComponent.questItems = new ArrayList<>(); + questListComponent.questItems.add("card"); + questPoint.addComponent(questListComponent); + + + // Prepare the NameTagComponent + NameTagComponent nameTagComponent = new NameTagComponent(); + nameTagComponent.text = "Quest"; + nameTagComponent.textColor = Color.YELLOW; + nameTagComponent.scale = 2; + nameTagComponent.yOffset = 2; + questPoint.addComponent(nameTagComponent); + + + // Prepare the LocationComponent + LocationComponent locationComponent = new LocationComponent(); + locationComponent.setWorldPosition(spawnPosition); + questPoint.addOrSaveComponent(locationComponent); + } + } + } + + @ReceiveEvent + public void onQuestActivated(BeforeQuestEvent event, EntityRef questItem) { + activeQuestEntity = questItem.getComponent(QuestSourceComponent.class).source; + } + + @ReceiveEvent + public void onReturnTaskInitiated(StartTaskEvent event, EntityRef entityRef) { + if (!Objects.equals(event.getQuest().getShortName(), FETCH_QUEST_ID) + || !Objects.equals(event.getTask().getId(), HOME_TASK_ID)) { + return; + } + + LocationComponent locationComponent = activeQuestEntity.getComponent(LocationComponent.class); + Optional beaconOptional = Assets.getPrefab("Tasks:BeaconMark"); + if (beaconOptional.isPresent()) { + EntityRef beacon = entityManager.create(beaconOptional.get(), locationComponent.getWorldPosition()); + activeQuestEntity.destroy(); + } + } +} diff --git a/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java b/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java new file mode 100644 index 00000000..c30096fa --- /dev/null +++ b/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.metalrenegades.quests; + +import org.terasology.math.geom.Rect2f; +import org.terasology.minimap.overlays.MinimapOverlay; +import org.terasology.rendering.nui.Canvas; + +public class TaskOverlay implements MinimapOverlay { + @Override + public void render(Canvas canvas, Rect2f worldRect) { + // TODO + } + + @Override + public int getZOrder() { + return 0; + } +} From 1b7e25107b4179fb9cb1ad0e207731e3a3aad5c4 Mon Sep 17 00:00:00 2001 From: Mayant Mukul Date: Thu, 8 Aug 2019 14:16:23 +0530 Subject: [PATCH 2/6] Destroy beacon on quest complete --- .../quests/FetchQuestSystem.java | 82 ++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java index 52086458..04f261b5 100644 --- a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java +++ b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java @@ -27,32 +27,56 @@ import org.terasology.entitySystem.systems.BaseComponentSystem; import org.terasology.entitySystem.systems.RegisterMode; import org.terasology.entitySystem.systems.RegisterSystem; +import org.terasology.logic.inventory.InventoryManager; import org.terasology.logic.location.LocationComponent; import org.terasology.logic.nameTags.NameTagComponent; import org.terasology.math.geom.Rect2i; import org.terasology.math.geom.Vector3f; +import org.terasology.metalrenegades.economy.systems.CurrencyManagementSystem; +import org.terasology.network.ClientComponent; +import org.terasology.protobuf.EntityData; import org.terasology.registry.In; import org.terasology.rendering.nui.Color; +import org.terasology.tasks.CollectBlocksTask; +import org.terasology.tasks.Task; +import org.terasology.tasks.components.QuestComponent; import org.terasology.tasks.components.QuestListComponent; import org.terasology.tasks.components.QuestSourceComponent; import org.terasology.tasks.events.BeforeQuestEvent; +import org.terasology.tasks.events.QuestCompleteEvent; import org.terasology.tasks.events.StartTaskEvent; import org.terasology.utilities.Assets; +import sun.text.resources.et.FormatData_et; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; -@RegisterSystem(RegisterMode.CLIENT) +@RegisterSystem(RegisterMode.AUTHORITY) public class FetchQuestSystem extends BaseComponentSystem { @In private EntityManager entityManager; + @In + private CurrencyManagementSystem currencyManagementSystem; + + @In + private InventoryManager inventoryManager; + private EntityRef activeQuestEntity; + private List fetchedItems = new ArrayList<>(); private final String HOME_TASK_ID = "returnHome"; private final String FETCH_QUEST_ID = "FetchQuest"; + private final int REWARD = 50; + + @Override + public void postBegin() { + activeQuestEntity = EntityRef.NULL; + } @ReceiveEvent(components = GenericBuildingComponent.class) public void onMarketPlaceSpawn(BuildingEntitySpawnedEvent event, EntityRef entityRef) { @@ -95,6 +119,15 @@ public void onMarketPlaceSpawn(BuildingEntitySpawnedEvent event, EntityRef entit @ReceiveEvent public void onQuestActivated(BeforeQuestEvent event, EntityRef questItem) { activeQuestEntity = questItem.getComponent(QuestSourceComponent.class).source; + + QuestComponent questComponent = questItem.getComponent(QuestComponent.class); + List tasks = questComponent.tasks; + fetchedItems = tasks.stream() + .filter(task -> task instanceof CollectBlocksTask) + .map(task -> new FetchedItem( + ((CollectBlocksTask) task).getItemId(), + ((CollectBlocksTask) task).getTargetAmount() + )).collect(Collectors.toList()); } @ReceiveEvent @@ -109,6 +142,53 @@ public void onReturnTaskInitiated(StartTaskEvent event, EntityRef entityRef) { if (beaconOptional.isPresent()) { EntityRef beacon = entityManager.create(beaconOptional.get(), locationComponent.getWorldPosition()); activeQuestEntity.destroy(); + activeQuestEntity = beacon; + } + } + + @ReceiveEvent + public void onQuestComplete(QuestCompleteEvent event, EntityRef client) { + if (event.isSuccess()) { + // Remove items from inventory +// removeItems(client); + + // Destroy the beacon + activeQuestEntity.destroy(); + + // Pay the player + currencyManagementSystem.changeWallet(REWARD); + } + } + + private void removeItems(EntityRef client) { +// ClientComponent component = client.getComponent(ClientComponent.class); +// EntityRef character = component.character; +// EntityRef item = EntityRef.NULL; +// +// try { +// for (int i = 0; i < inventoryManager.getNumSlots(character); i++) { +// EntityRef current = inventoryManager.getItemInSlot(character, i); +// if (!EntityRef.NULL.equals(current)) { +// item = current; +// break; +// } +// } +// inventoryManager.removeItem(localPlayer.getCharacterEntity(), EntityRef.NULL, item, true, 1); +// } catch (Exception e) { +//// logger.error("Could not create entity from {}. Exception: {}", name, e.getMessage()); +// } + } + + class FetchedItem { + public String itemId; + public int amount; + + public FetchedItem(String itemId, int amount) { + this.itemId = itemId; + this.amount = amount; + } + + public FetchedItem() { } } } From 0ada8d5805d44f399c7dfcf2c953a9d8a437cf9f Mon Sep 17 00:00:00 2001 From: Mayant Mukul Date: Thu, 8 Aug 2019 14:49:22 +0530 Subject: [PATCH 3/6] Move the quest point inside the church --- .../metalrenegades/quests/FetchQuestSystem.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java index 04f261b5..62b6f63b 100644 --- a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java +++ b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java @@ -79,15 +79,15 @@ public void postBegin() { } @ReceiveEvent(components = GenericBuildingComponent.class) - public void onMarketPlaceSpawn(BuildingEntitySpawnedEvent event, EntityRef entityRef) { + public void onChurchSpawn(BuildingEntitySpawnedEvent event, EntityRef entityRef) { GenericBuildingComponent genericBuildingComponent = entityRef.getComponent(GenericBuildingComponent.class); - if (genericBuildingComponent.name.equals("marketplace")) { + if (genericBuildingComponent.name.equals("simplechurch")) { DynParcel dynParcel = entityRef.getComponent(DynParcelRefComponent.class).dynParcel; Optional questPointOptional = Assets.getPrefab("Tasks:QuestPoint"); if (questPointOptional.isPresent()) { Rect2i rect2i = dynParcel.shape; - Vector3f spawnPosition = new Vector3f(rect2i.minX() + rect2i.sizeX() / 2, dynParcel.getHeight() + 10, rect2i.minY() + rect2i.sizeY() / 2); + Vector3f spawnPosition = new Vector3f(rect2i.minX() + rect2i.sizeX() / 2, dynParcel.getHeight() + 3, rect2i.minY() + rect2i.sizeY() / 2); EntityRef questPoint = entityManager.create(questPointOptional.get(), spawnPosition); SettlementRefComponent settlementRefComponent = entityRef.getComponent(SettlementRefComponent.class); questPoint.addComponent(settlementRefComponent); @@ -149,7 +149,7 @@ public void onReturnTaskInitiated(StartTaskEvent event, EntityRef entityRef) { @ReceiveEvent public void onQuestComplete(QuestCompleteEvent event, EntityRef client) { if (event.isSuccess()) { - // Remove items from inventory + // TODO: Remove items from inventory when quest is complete // removeItems(client); // Destroy the beacon From 114310f14cc3b1770e8248b5362d35d39bc7b136 Mon Sep 17 00:00:00 2001 From: Mayant Mukul Date: Thu, 8 Aug 2019 15:21:44 +0530 Subject: [PATCH 4/6] Modify quest to bring meat instead of dirt --- assets/prefabs/quests/card.prefab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/prefabs/quests/card.prefab b/assets/prefabs/quests/card.prefab index c7362384..0a2498da 100644 --- a/assets/prefabs/quests/card.prefab +++ b/assets/prefabs/quests/card.prefab @@ -15,8 +15,8 @@ "id" : "collectMeat", "type" : "CollectBlocksTask", "data" : { - "itemId" : "block:core:Dirt", - "amount" : 3 + "itemId" : "WildAnimals:Meat", + "amount" : 2 } }, { From f9b336f015829ee141641b572c5149d5b855a061 Mon Sep 17 00:00:00 2001 From: Mayant Mukul Date: Thu, 8 Aug 2019 16:59:53 +0530 Subject: [PATCH 5/6] Remove quest items from inventory on completion --- .../quests/FetchQuestSystem.java | 70 ++++++++----------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java index 62b6f63b..4d5751a3 100644 --- a/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java +++ b/src/main/java/org/terasology/metalrenegades/quests/FetchQuestSystem.java @@ -45,11 +45,14 @@ import org.terasology.tasks.events.BeforeQuestEvent; import org.terasology.tasks.events.QuestCompleteEvent; import org.terasology.tasks.events.StartTaskEvent; +import org.terasology.tasks.systems.QuestSystem; import org.terasology.utilities.Assets; import sun.text.resources.et.FormatData_et; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -66,11 +69,15 @@ public class FetchQuestSystem extends BaseComponentSystem { @In private InventoryManager inventoryManager; + @In + private QuestSystem questSystem; + private EntityRef activeQuestEntity; - private List fetchedItems = new ArrayList<>(); + private Map amounts = new HashMap<>(); private final String HOME_TASK_ID = "returnHome"; private final String FETCH_QUEST_ID = "FetchQuest"; + private final String ITEM_ID = "WildAnimals:Meat"; private final int REWARD = 50; @Override @@ -87,7 +94,7 @@ public void onChurchSpawn(BuildingEntitySpawnedEvent event, EntityRef entityRef) Optional questPointOptional = Assets.getPrefab("Tasks:QuestPoint"); if (questPointOptional.isPresent()) { Rect2i rect2i = dynParcel.shape; - Vector3f spawnPosition = new Vector3f(rect2i.minX() + rect2i.sizeX() / 2, dynParcel.getHeight() + 3, rect2i.minY() + rect2i.sizeY() / 2); + Vector3f spawnPosition = new Vector3f(rect2i.minX() + rect2i.sizeX() / 2, dynParcel.getHeight() + 2, rect2i.minY() + rect2i.sizeY() / 2); EntityRef questPoint = entityManager.create(questPointOptional.get(), spawnPosition); SettlementRefComponent settlementRefComponent = entityRef.getComponent(SettlementRefComponent.class); questPoint.addComponent(settlementRefComponent); @@ -122,12 +129,11 @@ public void onQuestActivated(BeforeQuestEvent event, EntityRef questItem) { QuestComponent questComponent = questItem.getComponent(QuestComponent.class); List tasks = questComponent.tasks; - fetchedItems = tasks.stream() - .filter(task -> task instanceof CollectBlocksTask) - .map(task -> new FetchedItem( - ((CollectBlocksTask) task).getItemId(), - ((CollectBlocksTask) task).getTargetAmount() - )).collect(Collectors.toList()); + for (Task t : tasks) { + if (t instanceof CollectBlocksTask) { + amounts.put(((CollectBlocksTask) t).getItemId(), ((CollectBlocksTask) t).getTargetAmount()); + } + } } @ReceiveEvent @@ -149,46 +155,28 @@ public void onReturnTaskInitiated(StartTaskEvent event, EntityRef entityRef) { @ReceiveEvent public void onQuestComplete(QuestCompleteEvent event, EntityRef client) { if (event.isSuccess()) { - // TODO: Remove items from inventory when quest is complete -// removeItems(client); + // Remove items from inventory + ClientComponent component = client.getComponent(ClientComponent.class); + EntityRef character = component.character; + EntityRef item = EntityRef.NULL; + + for (int i = 0; i < inventoryManager.getNumSlots(character); i++) { + EntityRef current = inventoryManager.getItemInSlot(character, i); + if (!EntityRef.NULL.equals(current) && ITEM_ID.equalsIgnoreCase(current.getParentPrefab().getName())) { + item = current; + break; + } + } + inventoryManager.removeItem(character, EntityRef.NULL, item, true, amounts.getOrDefault(ITEM_ID, 0)); // Destroy the beacon activeQuestEntity.destroy(); // Pay the player currencyManagementSystem.changeWallet(REWARD); - } - } - - private void removeItems(EntityRef client) { -// ClientComponent component = client.getComponent(ClientComponent.class); -// EntityRef character = component.character; -// EntityRef item = EntityRef.NULL; -// -// try { -// for (int i = 0; i < inventoryManager.getNumSlots(character); i++) { -// EntityRef current = inventoryManager.getItemInSlot(character, i); -// if (!EntityRef.NULL.equals(current)) { -// item = current; -// break; -// } -// } -// inventoryManager.removeItem(localPlayer.getCharacterEntity(), EntityRef.NULL, item, true, 1); -// } catch (Exception e) { -//// logger.error("Could not create entity from {}. Exception: {}", name, e.getMessage()); -// } - } - - class FetchedItem { - public String itemId; - public int amount; - - public FetchedItem(String itemId, int amount) { - this.itemId = itemId; - this.amount = amount; - } - public FetchedItem() { + // remove the quest + questSystem.removeQuest(event.getQuest(), true); } } } From da02a38b6575a380d4607acb9a703db8efb04d2e Mon Sep 17 00:00:00 2001 From: Mayant Mukul Date: Fri, 9 Aug 2019 16:16:12 +0530 Subject: [PATCH 6/6] Add TaskOverlay --- assets/textures/beaconIcon.png | Bin 0 -> 624 bytes .../quests/AddBeaconOverlayEvent.java | 33 +++++++ .../quests/DestroyActiveEntityEvent.java | 24 +++++ .../quests/FetchQuestSystem.java | 25 +++-- .../quests/RemoveBeaconOverlayEvent.java | 30 ++++++ .../metalrenegades/quests/TaskOverlay.java | 76 ++++++++++++++- .../quests/TaskOverlaySystem.java | 89 ++++++++++++++++++ 7 files changed, 270 insertions(+), 7 deletions(-) create mode 100644 assets/textures/beaconIcon.png create mode 100644 src/main/java/org/terasology/metalrenegades/quests/AddBeaconOverlayEvent.java create mode 100644 src/main/java/org/terasology/metalrenegades/quests/DestroyActiveEntityEvent.java create mode 100644 src/main/java/org/terasology/metalrenegades/quests/RemoveBeaconOverlayEvent.java create mode 100644 src/main/java/org/terasology/metalrenegades/quests/TaskOverlaySystem.java diff --git a/assets/textures/beaconIcon.png b/assets/textures/beaconIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..f9071bc983dbd6fe622dece4ea361e47e6fe3f72 GIT binary patch literal 624 zcmV-$0+0QPP)EX>4Tx04R}tkv&MmKp2MKriw)?4t9{@kfAzR5ET(zq>4qbP}&NuI+$Gg2TdB1 z6cv5D_F)!biJ5vLy_kXL__~LW?{`t23_a=v{OB);h=O1CXI!E#CkK zhrno&ve!M{9q8=azcsD?{Q#e9a=G1EcLD$a00v@9M??Un0Hpw>IE!O-00009a7bBm z001r{001r{0eGc9b^rhX2XskIMF-;u2n+=Yq;VA|0000PbVXQnLvL+uWo~o;Lvm$d zbY)~9cWHEJAV*0}P*;Ht7XSbNMoC0LR5;6HV88>OJ$t6cKmafikiYrt*|YzY7{EZO z3q}nX83xc6{Qv*|%>V!Yx8PI5NFX!8@&S{Sl+=H+!vL3NssI3G7ZpK4H`MF^0000< KMNUMnLSTX amounts = new HashMap<>(); @@ -150,6 +154,8 @@ public void onReturnTaskInitiated(StartTaskEvent event, EntityRef entityRef) { activeQuestEntity.destroy(); activeQuestEntity = beacon; } + + localPlayer.getCharacterEntity().send(new AddBeaconOverlayEvent(activeQuestEntity)); } @ReceiveEvent @@ -169,14 +175,21 @@ public void onQuestComplete(QuestCompleteEvent event, EntityRef client) { } inventoryManager.removeItem(character, EntityRef.NULL, item, true, amounts.getOrDefault(ITEM_ID, 0)); - // Destroy the beacon - activeQuestEntity.destroy(); - // Pay the player currencyManagementSystem.changeWallet(REWARD); + // Remove the minmap overlay + localPlayer.getCharacterEntity().send(new RemoveBeaconOverlayEvent(activeQuestEntity)); + // remove the quest questSystem.removeQuest(event.getQuest(), true); + +// activeQuestEntity.destroy(); } } + + @ReceiveEvent + public void onDestroyActiveEntityEvent(DestroyActiveEntityEvent event, EntityRef character) { + activeQuestEntity.destroy(); + } } diff --git a/src/main/java/org/terasology/metalrenegades/quests/RemoveBeaconOverlayEvent.java b/src/main/java/org/terasology/metalrenegades/quests/RemoveBeaconOverlayEvent.java new file mode 100644 index 00000000..3a204641 --- /dev/null +++ b/src/main/java/org/terasology/metalrenegades/quests/RemoveBeaconOverlayEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright 2019 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.metalrenegades.quests; + +import org.terasology.entitySystem.entity.EntityRef; +import org.terasology.entitySystem.event.Event; + +/** + * Removes the beacon overlay from the minimap + */ +public class RemoveBeaconOverlayEvent implements Event { + public EntityRef beaconEntity; + + public RemoveBeaconOverlayEvent(EntityRef beaconEntity) { + this.beaconEntity = beaconEntity; + } +} diff --git a/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java b/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java index c30096fa..1ee3ff80 100644 --- a/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java +++ b/src/main/java/org/terasology/metalrenegades/quests/TaskOverlay.java @@ -15,18 +15,92 @@ */ package org.terasology.metalrenegades.quests; +import org.terasology.entitySystem.entity.EntityRef; +import org.terasology.logic.location.LocationComponent; import org.terasology.math.geom.Rect2f; +import org.terasology.math.geom.Rect2fTransformer; +import org.terasology.math.geom.Rect2i; +import org.terasology.math.geom.Vector2f; +import org.terasology.math.geom.Vector2i; +import org.terasology.math.geom.Vector3f; import org.terasology.minimap.overlays.MinimapOverlay; +import org.terasology.rendering.assets.texture.Texture; import org.terasology.rendering.nui.Canvas; +import org.terasology.utilities.Assets; +import java.util.Optional; + +/** + * A minimap overlay to mark the home beacon for the meat quest + */ public class TaskOverlay implements MinimapOverlay { + + private final int ICON_SIZE = 24; + private EntityRef beaconEntity; + + public TaskOverlay(EntityRef beaconEntity) { + this.beaconEntity = beaconEntity; + } + @Override public void render(Canvas canvas, Rect2f worldRect) { - // TODO + Rect2f screenRect = Rect2f.createFromMinAndSize( + new Vector2f(canvas.getRegion().minX(), canvas.getRegion().minY()), + new Vector2f(canvas.getRegion().maxX(), canvas.getRegion().maxY()) + ); + + Rect2fTransformer transformer = new Rect2fTransformer(worldRect, screenRect); + + Vector3f localPosition = beaconEntity.getComponent(LocationComponent.class).getWorldPosition(); + Vector2f mapPoint = transformer.apply(localPosition.x, localPosition.y); + + Vector2i min = clamp(mapPoint, screenRect); + Rect2i region = Rect2i.createFromMinAndSize(min.x, min.y, ICON_SIZE, ICON_SIZE); + + Optional icon = Assets.getTexture("MetalRenegades:beaconIcon"); + icon.ifPresent(texture -> canvas.drawTexture(texture, region)); } @Override public int getZOrder() { return 0; } + + public EntityRef getBeaconEntity() { + return beaconEntity; + } + + /** + * Constrains a point to a specified region. Works like a vector clamp. + * + * @param point: the coordinates of the point to be clamped + * @param box: limits + * @return new clamped coordinates of point + */ + private Vector2i clamp(Vector2f point, Rect2f box) { + float x; + float y; + Rect2f iconRegion = Rect2f.createFromMinAndSize(point.x, point.y, ICON_SIZE, ICON_SIZE); + + if (box.contains(iconRegion)) { + return new Vector2i(point.x, point.y); + } else { + if (iconRegion.maxX() >= box.maxX()) { + x = (int) box.maxX() - ICON_SIZE; + } else if (iconRegion.minX() <= box.minX()) { + x = (int) box.minX(); + } else { + x = point.x; + } + + if (iconRegion.maxY() >= box.maxY()) { + y = (int) box.maxY() - ICON_SIZE; + } else if (iconRegion.minY() <= box.minY()) { + y = (int) box.minY(); + } else { + y = point.y; + } + } + return new Vector2i(x, y); + } } diff --git a/src/main/java/org/terasology/metalrenegades/quests/TaskOverlaySystem.java b/src/main/java/org/terasology/metalrenegades/quests/TaskOverlaySystem.java new file mode 100644 index 00000000..20c981e3 --- /dev/null +++ b/src/main/java/org/terasology/metalrenegades/quests/TaskOverlaySystem.java @@ -0,0 +1,89 @@ +/* + * Copyright 2019 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.metalrenegades.quests; + +import org.terasology.entitySystem.entity.EntityManager; +import org.terasology.entitySystem.entity.EntityRef; +import org.terasology.entitySystem.event.ReceiveEvent; +import org.terasology.entitySystem.systems.BaseComponentSystem; +import org.terasology.entitySystem.systems.RegisterMode; +import org.terasology.entitySystem.systems.RegisterSystem; +import org.terasology.logic.players.LocalPlayer; +import org.terasology.logic.players.MinimapSystem; +import org.terasology.network.ClientComponent; +import org.terasology.network.NetworkMode; +import org.terasology.network.NetworkSystem; +import org.terasology.registry.In; + +/** + * Manages the beacon minimap overlay + */ +@RegisterSystem(RegisterMode.CLIENT) +public class TaskOverlaySystem extends BaseComponentSystem { + + @In + private NetworkSystem networkSystem; + + @In + private EntityManager entityManager; + + @In + private MinimapSystem minimapSystem; + + @In + private LocalPlayer localPlayer; + + private TaskOverlay overlay; + private EntityRef clientEntity; + private boolean isOverlayAdded = false; + + @Override + public void initialise() { + if (networkSystem.getMode() == NetworkMode.CLIENT) { + clientEntity = networkSystem.getServer().getClientEntity(); + } + } + + @ReceiveEvent + public void onAddBeaconOverlayEvent(AddBeaconOverlayEvent event, EntityRef character) { + overlay = new TaskOverlay(event.beaconEntity); + + if (networkSystem.getMode() == NetworkMode.NONE) { + minimapSystem.addOverlay(overlay); + isOverlayAdded = true; + } + + if (networkSystem.getMode() == NetworkMode.CLIENT) { + if (clientEntity.getComponent(ClientComponent.class).character.getId() == character.getId() && !isOverlayAdded) { + minimapSystem.addOverlay(overlay); + isOverlayAdded = true; + } + } + + if (networkSystem.getMode() == NetworkMode.DEDICATED_SERVER && !isOverlayAdded) { + if (localPlayer.getCharacterEntity() == character) { + minimapSystem.addOverlay(overlay); + } + } + } + + @ReceiveEvent + public void onRemoveBeaconOverlayEvent(RemoveBeaconOverlayEvent event, EntityRef character) { + minimapSystem.removeOverlay(overlay); + isOverlayAdded = false; + character.send(new DestroyActiveEntityEvent()); + } +}