Skip to content

Commit

Permalink
Attempt to implement item giving to NPCs (untested)
Browse files Browse the repository at this point in the history
  • Loading branch information
KingRainbow44 committed Jul 31, 2023
1 parent a4ad781 commit b82567d
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 49 deletions.
61 changes: 21 additions & 40 deletions src/main/java/emu/grasscutter/data/GameData.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,33 @@
import emu.grasscutter.data.binout.*;
import emu.grasscutter.data.binout.config.*;
import emu.grasscutter.data.binout.routes.Route;
import emu.grasscutter.data.custom.TrialAvatarActivityCustomData;
import emu.grasscutter.data.custom.TrialAvatarCustomData;
import emu.grasscutter.data.custom.*;
import emu.grasscutter.data.excels.*;
import emu.grasscutter.data.excels.achievement.AchievementData;
import emu.grasscutter.data.excels.achievement.AchievementGoalData;
import emu.grasscutter.data.excels.activity.ActivityCondExcelConfigData;
import emu.grasscutter.data.excels.activity.ActivityData;
import emu.grasscutter.data.excels.activity.ActivityShopData;
import emu.grasscutter.data.excels.activity.ActivityWatcherData;
import emu.grasscutter.data.excels.achievement.*;
import emu.grasscutter.data.excels.activity.*;
import emu.grasscutter.data.excels.avatar.*;
import emu.grasscutter.data.excels.codex.*;
import emu.grasscutter.data.excels.dungeon.*;
import emu.grasscutter.data.excels.monster.MonsterCurveData;
import emu.grasscutter.data.excels.monster.MonsterData;
import emu.grasscutter.data.excels.monster.MonsterDescribeData;
import emu.grasscutter.data.excels.monster.MonsterSpecialNameData;
import emu.grasscutter.data.excels.quest.QuestData;
import emu.grasscutter.data.excels.quest.QuestGlobalVarData;
import emu.grasscutter.data.excels.reliquary.ReliquaryAffixData;
import emu.grasscutter.data.excels.reliquary.ReliquaryLevelData;
import emu.grasscutter.data.excels.reliquary.ReliquaryMainPropData;
import emu.grasscutter.data.excels.reliquary.ReliquarySetData;
import emu.grasscutter.data.excels.tower.TowerFloorData;
import emu.grasscutter.data.excels.tower.TowerLevelData;
import emu.grasscutter.data.excels.tower.TowerScheduleData;
import emu.grasscutter.data.excels.giving.*;
import emu.grasscutter.data.excels.monster.*;
import emu.grasscutter.data.excels.quest.*;
import emu.grasscutter.data.excels.reliquary.*;
import emu.grasscutter.data.excels.tower.*;
import emu.grasscutter.data.excels.trial.*;
import emu.grasscutter.data.excels.weapon.WeaponCurveData;
import emu.grasscutter.data.excels.weapon.WeaponLevelData;
import emu.grasscutter.data.excels.weapon.WeaponPromoteData;
import emu.grasscutter.data.excels.world.WeatherData;
import emu.grasscutter.data.excels.world.WorldAreaData;
import emu.grasscutter.data.excels.world.WorldLevelData;
import emu.grasscutter.data.server.ActivityCondGroup;
import emu.grasscutter.data.server.DropSubfieldMapping;
import emu.grasscutter.data.server.DropTableExcelConfigData;
import emu.grasscutter.data.server.GadgetMapping;
import emu.grasscutter.data.server.MonsterMapping;
import emu.grasscutter.data.server.SubfieldMapping;
import emu.grasscutter.data.excels.weapon.*;
import emu.grasscutter.data.excels.world.*;
import emu.grasscutter.data.server.*;
import emu.grasscutter.game.dungeons.DungeonDropEntry;
import emu.grasscutter.game.quest.QuestEncryptionKey;
import emu.grasscutter.game.quest.RewindData;
import emu.grasscutter.game.quest.TeleportData;
import emu.grasscutter.game.quest.*;
import emu.grasscutter.game.quest.enums.QuestCond;
import emu.grasscutter.game.world.GroupReplacementData;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.*;
import lombok.*;

import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.util.*;
import javax.annotation.Nullable;
import lombok.Getter;
import lombok.Setter;
import lombok.val;

@SuppressWarnings({"unused", "MismatchedQueryAndUpdateOfCollection"})
public final class GameData {
Expand Down Expand Up @@ -266,6 +241,12 @@ public final class GameData {
@Getter
private static final Int2ObjectMap<GatherData> gatherDataMap = new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<GivingData> givingDataMap = new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<GivingGroupData> givingGroupDataMap = new Int2ObjectOpenHashMap<>();

@Getter
@Deprecated // This is to prevent people from using this map. This is for the resource loader
// only!
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/emu/grasscutter/data/excels/giving/GivingData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package emu.grasscutter.data.excels.giving;

import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.*;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.game.inventory.BagTab;
import lombok.*;

import java.util.List;

@Data
@EqualsAndHashCode(callSuper = false)
@ResourceType(name = "GivingExcelConfigData.json")
public final class GivingData extends GameResource {
@SerializedName(value = "id", alternate = "Id")
private int id;
private int talkId;
private int mistakeTalkId;

private BagTab tab;
private GiveMethod givingMethod;

private List<ItemParamData> exactItems;
private int exactFinishTalkId;

private List<Integer> givingGroupIds;
private int givingGroupCount;

private boolean isRemoveItem;
private GiveType giveType;

public enum GiveMethod {
@SerializedName("GIVING_METHOD_EXACT") EXACT,
@SerializedName("GIVING_METHOD_GROUP") GROUP,
@SerializedName("GIVING_METHOD_VAGUE_GROUP") GROUP_VAGUE
}

public enum GiveType {
@SerializedName("GIVING_TYPE_QUEST") QUEST,
@SerializedName("GIVING_TYPE_GROUP") GROUP
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package emu.grasscutter.data.excels.giving;

import com.google.gson.annotations.SerializedName;
import emu.grasscutter.data.*;
import lombok.*;

import java.util.List;

@Data
@EqualsAndHashCode(callSuper = false)
@ResourceType(name = "GivingGroupExcelConfigData.json")
public final class GivingGroupData extends GameResource {
@SerializedName(value = "id", alternate = "Id")
private int id;

@SerializedName(value = "itemIds", alternate = "ItemIds")
private List<Integer> itemIds;

private int finishTalkId;
private int mistakeTalkId;
}
55 changes: 55 additions & 0 deletions src/main/java/emu/grasscutter/game/inventory/BagTab.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package emu.grasscutter.game.inventory;

import it.unimi.dsi.fastutil.ints.*;
import lombok.*;

import java.util.*;
import java.util.stream.Stream;

@RequiredArgsConstructor
public enum BagTab {
TAB_NONE(0),
TAB_WEAPON(1),
TAB_EQUIP(2),
TAB_AVATAR(3),
TAB_FOOD(4),
TAB_MATERIAL(5),
TAB_QUEST(6),
TAB_CONSUME(7),
TAB_WIDGET(8),
TAB_HOMEWORLD(9);

private static final Int2ObjectMap<BagTab> map = new Int2ObjectOpenHashMap<>();
private static final Map<String, BagTab> stringMap = new HashMap<>();

static {
Stream.of(BagTab.values())
.forEach(
entry -> {
map.put(entry.getValue(), entry);
stringMap.put(entry.name(), entry);
});
}

@Getter private final int value;

/**
* Fetches the bag tab by its value.
*
* @param value The name of the bag tab.
* @return The bag tab.
*/
public static BagTab getTypeByValue(int value) {
return map.getOrDefault(value, TAB_NONE);
}

/**
* Fetches the bag tab by its name.
*
* @param name The name of the bag tab.
* @return The bag tab.
*/
public static BagTab getTypeByName(String name) {
return stringMap.getOrDefault(name, TAB_NONE);
}
}
62 changes: 60 additions & 2 deletions src/main/java/emu/grasscutter/game/inventory/Inventory.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package emu.grasscutter.game.inventory;

import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS;

import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
Expand All @@ -17,8 +15,11 @@
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.longs.*;

import java.util.*;

import static emu.grasscutter.config.Configuration.INVENTORY_LIMITS;

public class Inventory extends BasePlayerManager implements Iterable<GameItem> {
private final Long2ObjectMap<GameItem> store;
private final Int2ObjectMap<InventoryTab> inventoryTypes;
Expand Down Expand Up @@ -150,6 +151,52 @@ public void addItems(Collection<GameItem> items, ActionReason reason) {
getPlayer().sendPacket(new PacketStoreItemChangeNotify(changedItems));
}

/**
* Checks to see if the player has the item in their inventory.
* This will succeed if the player has at least the minimum count of the item.
*
* @param itemGuid The item id to check for.
* @param minCount The minimum count of the item to check for.
* @return True if the player has the item, false otherwise.
*/
public boolean hasItem(long itemGuid, int minCount) {
return hasItem(itemGuid, minCount, false);
}

/**
* Checks to see if the player has the item in their inventory.
*
* @param itemGuid The item id to check for.
* @param count The count of the item to check for.
* @param enforce If true, the player must have the exact amount.
* If false, the player must have at least the amount.
* @return True if the player has the item, false otherwise.
*/
public boolean hasItem(long itemGuid, int count, boolean enforce) {
var item = this.getItemByGuid(itemGuid);
if (item == null) return false;

return enforce ?
item.getCount() == count :
item.getCount() >= count;
}

/**
* Checks to see if the player has the item in their inventory.
* This is exact.
*
* @param items A map of item game IDs to their count.
* @return True if the player has the items, false otherwise.
*/
public boolean hasAllItems(Map<Long, Integer> items) {
for (var item : items.entrySet()) {
if (!this.hasItem(item.getKey(), item.getValue(), true))
return false;
}

return true;
}

private void triggerAddItemEvents(GameItem result) {
try {
getPlayer()
Expand Down Expand Up @@ -434,6 +481,17 @@ public void removeItems(List<GameItem> items) {
}
}

/**
* Performs a bulk delete of items.
*
* @param items A map of item game IDs to the amount of items to remove.
*/
public void removeItems(Map<Long, Integer> items) {
for (var entry : items.entrySet()) {
this.removeItem(entry.getKey(), entry.getValue());
}
}

public boolean removeItem(long guid) {
return removeItem(guid, 1);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/emu/grasscutter/game/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public class Player implements PlayerHook, FieldFetch {
@Getter private transient FriendsList friendsList;
@Getter private transient MailHandler mailHandler;
@Getter private transient AbilityManager abilityManager;
@Getter @Setter private transient QuestManager questManager;
@Getter private transient QuestManager questManager;
@Getter private transient TowerManager towerManager;
@Getter private transient SotSManager sotsManager;
@Getter private transient MapMarksManager mapMarksManager;
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/emu/grasscutter/game/quest/QuestManager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package emu.grasscutter.game.quest;

import dev.morphia.annotations.Transient;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.MainQuestData;
Expand Down Expand Up @@ -31,10 +30,13 @@
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
import static emu.grasscutter.config.Configuration.SERVER;

public class QuestManager extends BasePlayerManager {
public final class QuestManager extends BasePlayerManager {
@Getter private final Player player;

@Getter private final Int2ObjectMap<GameMainQuest> mainQuests;
@Transient @Getter private final List<Integer> loggedQuests;
@Getter private final List<Integer> loggedQuests;

@Getter private final List<Integer> activeGivings = new ArrayList<>();

private long lastHourCheck = 0;
private long lastDayCheck = 0;
Expand All @@ -45,6 +47,7 @@ public class QuestManager extends BasePlayerManager {
60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000),
FastThreadLocalThread::new, new ThreadPoolExecutor.AbortPolicy());
}

/*
On SetPlayerBornDataReq, the server sends FinishedParentQuestNotify, with this exact
parentQuestList. Captured on Game version 2.7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public enum QuestContent implements QuestTrigger {
QUEST_CONTENT_ADD_QUEST_PROGRESS(24),
QUEST_CONTENT_INTERACT_GADGET(25),
QUEST_CONTENT_DAILY_TASK_COMP_FINISH(26), // missing, currently unused
QUEST_CONTENT_FINISH_ITEM_GIVING(27), // missing, finish
QUEST_CONTENT_FINISH_ITEM_GIVING(27),
QUEST_CONTENT_SKILL(107),
QUEST_CONTENT_CITY_LEVEL_UP(109), // missing, finish
QUEST_CONTENT_PATTERN_GROUP_CLEAR_MONSTER(110), // missing, finish, for random quests
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/emu/grasscutter/game/quest/enums/QuestExec.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public enum QuestExec implements QuestTrigger {
QUEST_EXEC_CREATE_PATTERN_GROUP(25), // missing, used for random quests
QUEST_EXEC_REMOVE_PATTERN_GROUP(26), // missing, used for random quests
QUEST_EXEC_REFRESH_GROUP_SUITE_RANDOM(27), // missing
QUEST_EXEC_ACTIVE_ITEM_GIVING(28), // missing
QUEST_EXEC_ACTIVE_ITEM_GIVING(28),
QUEST_EXEC_DEL_ALL_SPECIFIC_PACK_ITEM(29), // missing
QUEST_EXEC_ROLLBACK_PARENT_QUEST(30),
QUEST_EXEC_LOCK_AVATAR_TEAM(31), // missing
Expand Down Expand Up @@ -71,7 +71,7 @@ public enum QuestExec implements QuestTrigger {
QUEST_EXEC_MODIFY_CLIMATE_AREA(60), // missing
QUEST_EXEC_GRANT_TRIAL_AVATAR_AND_LOCK_TEAM(61), // missing
QUEST_EXEC_CHANGE_MAP_AREA_STATE(62), // missing
QUEST_EXEC_DEACTIVE_ITEM_GIVING(63), // missing
QUEST_EXEC_DEACTIVE_ITEM_GIVING(63),
QUEST_EXEC_CHANGE_SCENE_LEVEL_TAG(64), // missing
QUEST_EXEC_UNLOCK_PLAYER_WORLD_SCENE(65), // missing
QUEST_EXEC_LOCK_PLAYER_WORLD_SCENE(66), // missing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package emu.grasscutter.game.quest.exec;

import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.excels.quest.QuestData.QuestExecParam;
import emu.grasscutter.game.quest.*;
import emu.grasscutter.game.quest.enums.QuestExec;
import emu.grasscutter.game.quest.handlers.QuestExecHandler;

@QuestValueExec(QuestExec.QUEST_EXEC_ACTIVE_ITEM_GIVING)
public final class ExecActiveItemGiving extends QuestExecHandler {
@Override
public boolean execute(GameQuest quest, QuestExecParam condition, String... paramStr) {
var questManager = quest.getOwner().getQuestManager();
var activeGivings = questManager.getActiveGivings();

var givingId = Integer.parseInt(condition.getParam()[0]);
if (activeGivings.contains(givingId)) {
Grasscutter.getLogger().debug("Quest {} attempted to add give action {} twice.",
quest.getSubQuestId(), givingId);
return false;
} else {
activeGivings.add(givingId);
return true;
}
}
}
Loading

0 comments on commit b82567d

Please sign in to comment.