diff --git a/src/main/java/kamkeel/npcs/command/QuestCategoryCommand.java b/src/main/java/kamkeel/npcs/command/QuestCategoryCommand.java index f33d3626b..27eb0efb8 100644 --- a/src/main/java/kamkeel/npcs/command/QuestCategoryCommand.java +++ b/src/main/java/kamkeel/npcs/command/QuestCategoryCommand.java @@ -99,7 +99,9 @@ public class QuestCategoryCommand extends CommandKamkeelBase { playerdata.questData.finishedQuests.put(quest.id, completeTime); } - if (ConfigMain.ProfilesEnabled && playerdata.player != null && quest.profileOptions.enableOptions && quest.profileOptions.completeControl == EnumProfileSync.Shared) + if (ConfigMain.ProfilesEnabled && playerdata.player != null && quest.profileOptions.enableOptions + && (quest.profileOptions.completeControl == EnumProfileSync.Shared + || quest.profileOptions.cooldownControl == EnumProfileSync.Shared)) ProfileController.Instance.shareQuestCompletion(playerdata.player, quest.id, completeTime); ; diff --git a/src/main/java/kamkeel/npcs/command/QuestCommand.java b/src/main/java/kamkeel/npcs/command/QuestCommand.java index 0a6cb5edf..5ccbe5319 100644 --- a/src/main/java/kamkeel/npcs/command/QuestCommand.java +++ b/src/main/java/kamkeel/npcs/command/QuestCommand.java @@ -115,7 +115,9 @@ public class QuestCommand extends CommandKamkeelBase { playerdata.questData.finishedQuests.put(quest.id, completeTime); } - if (ConfigMain.ProfilesEnabled && playerdata.player != null && quest.profileOptions.enableOptions && quest.profileOptions.completeControl == EnumProfileSync.Shared) + if (ConfigMain.ProfilesEnabled && playerdata.player != null && quest.profileOptions.enableOptions + && (quest.profileOptions.completeControl == EnumProfileSync.Shared + || quest.profileOptions.cooldownControl == EnumProfileSync.Shared)) ProfileController.Instance.shareQuestCompletion(playerdata.player, quest.id, completeTime); playerdata.save(); diff --git a/src/main/java/kamkeel/npcs/controllers/ProfileController.java b/src/main/java/kamkeel/npcs/controllers/ProfileController.java index f7ac06bb1..fcb3436af 100644 --- a/src/main/java/kamkeel/npcs/controllers/ProfileController.java +++ b/src/main/java/kamkeel/npcs/controllers/ProfileController.java @@ -523,6 +523,7 @@ public class ProfileController implements IProfileHandler { // overwrite the destination slot with stale data. saveSlotData(profile.player, profile, prevSlot); loadSlotData(profile.player, profile, newSlotId); + syncSharedQuestsToPlayer(profile.player); EventHooks.onProfileChange(handler, scriptPlayer, profile, newSlotId, prevSlot, true); } else { @@ -860,6 +861,9 @@ public class ProfileController implements IProfileHandler { } } + // Update the profile cache + profile.sharedQuestTimestamps = universalFinished; + // Push the universal shared completion times into every slot. for (ISlot slot : profile.getSlots().values()) { IPlayerData data = getSlotPlayerData(player, slot.getId()); @@ -872,21 +876,29 @@ public class ProfileController implements IProfileHandler { } } + public void syncSharedQuestsToPlayer(EntityPlayer player) { + Profile profile = getProfile(player); + if (profile == null || profile.sharedQuestTimestamps.isEmpty()) { + return; + } + PlayerQuestData questData = PlayerData.get(player).questData; + for (Map.Entry entry : profile.sharedQuestTimestamps.entrySet()) { + Long existing = questData.finishedQuests.get(entry.getKey()); + if (existing == null || entry.getValue() > existing) { + questData.finishedQuests.put(entry.getKey(), entry.getValue()); + } + } + } + public void shareQuestCompletion(EntityPlayer player, int questId, long completeTime) { Profile profile = getProfile(player); if (profile == null) { return; } - for (ISlot slot : profile.getSlots().values()) { - IPlayerData playerData = getSlotPlayerData(player, slot.getId()); - if (playerData != null) { - PlayerQuestData questData = (PlayerQuestData) playerData.getQuestData(); - Long existing = questData.finishedQuests.get(questId); - if (existing == null || completeTime > existing) { - questData.finishedQuests.put(questId, completeTime); - } - playerData.save(); - } + + Long existing = profile.sharedQuestTimestamps.get(questId); + if (existing == null || completeTime > existing) { + profile.sharedQuestTimestamps.put(questId, completeTime); } save(player, profile); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java b/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java index 04ce9b66c..002fdb52f 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java +++ b/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java @@ -2,6 +2,7 @@ package kamkeel.npcs.controllers.data.profile; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import noppes.npcs.NoppesUtilServer; import noppes.npcs.api.entity.IPlayer; import noppes.npcs.api.handler.data.IProfile; @@ -15,6 +16,7 @@ public class Profile implements IProfile { public EntityPlayer player; public int currentSlotId; private final Map slots = new HashMap<>(); + public Map sharedQuestTimestamps = new HashMap<>(); private boolean locked = false; public Profile(EntityPlayer player, NBTTagCompound compound) { @@ -39,6 +41,14 @@ public class Profile implements IProfile { } } } + + if (compound.hasKey("SharedQuestTimestamps")) { + NBTTagList list = compound.getTagList("SharedQuestTimestamps", 10); + for (int i = 0; i < list.tagCount(); i++) { + NBTTagCompound entry = list.getCompoundTagAt(i); + sharedQuestTimestamps.put(entry.getInteger("Quest"), entry.getLong("Date")); + } + } } public Profile(EntityPlayer player) { @@ -88,6 +98,16 @@ public class Profile implements IProfile { slotsCompound.setTag(String.valueOf(entry.getKey()), entry.getValue().toNBT()); } compound.setTag("Slots", slotsCompound); + + NBTTagList questList = new NBTTagList(); + for (Map.Entry entry : sharedQuestTimestamps.entrySet()) { + NBTTagCompound questEntry = new NBTTagCompound(); + questEntry.setInteger("Quest", entry.getKey()); + questEntry.setLong("Date", entry.getValue()); + questList.appendTag(questEntry); + } + compound.setTag("SharedQuestTimestamps", questList); + return compound; } } diff --git a/src/main/java/noppes/npcs/controllers/PlayerQuestController.java b/src/main/java/noppes/npcs/controllers/PlayerQuestController.java index 7b99f40d8..288c24f79 100644 --- a/src/main/java/noppes/npcs/controllers/PlayerQuestController.java +++ b/src/main/java/noppes/npcs/controllers/PlayerQuestController.java @@ -1,6 +1,7 @@ package noppes.npcs.controllers; import kamkeel.npcs.controllers.ProfileController; +import kamkeel.npcs.controllers.data.profile.Profile; import kamkeel.npcs.network.packets.data.AchievementPacket; import kamkeel.npcs.network.packets.data.ChatAlertPacket; import net.minecraft.entity.player.EntityPlayer; @@ -91,7 +92,9 @@ public class PlayerQuestController { questData.finishedQuests.put(quest.id, completeTime); } - if (ConfigMain.ProfilesEnabled && quest.profileOptions.enableOptions && quest.profileOptions.completeControl == EnumProfileSync.Shared) + if (ConfigMain.ProfilesEnabled && quest.profileOptions.enableOptions + && (quest.profileOptions.completeControl == EnumProfileSync.Shared + || quest.profileOptions.cooldownControl == EnumProfileSync.Shared)) ProfileController.Instance.shareQuestCompletion(player, quest.id, completeTime); } @@ -125,27 +128,29 @@ public class PlayerQuestController { if (data.activeQuests.containsKey(quest.id)) return false; - if (!data.finishedQuests.containsKey(quest.id) || quest.repeat == EnumQuestRepeat.REPEATABLE) + boolean finishedLocally = data.finishedQuests.containsKey(quest.id); + boolean completedShared = false; + boolean hasCooldownShared = false; + if (ConfigMain.ProfilesEnabled && quest.profileOptions.enableOptions) { + Profile profile = ProfileController.Instance.getProfile(player); + if (profile != null && profile.sharedQuestTimestamps.containsKey(quest.id)) { + if (quest.profileOptions.completeControl == EnumProfileSync.Shared) + completedShared = true; + if (quest.profileOptions.cooldownControl == EnumProfileSync.Shared) + hasCooldownShared = true; + } + } + + boolean isFinished = finishedLocally || completedShared; + + if (!isFinished && !hasCooldownShared) + return true; + if (quest.repeat == EnumQuestRepeat.REPEATABLE) return true; if (quest.repeat == EnumQuestRepeat.NONE) - return false; + return !isFinished; - long questTime = data.finishedQuests.get(quest.id); - - if (quest.repeat == EnumQuestRepeat.MCDAILY) { - return player.worldObj.getTotalWorldTime() - questTime >= 24000; - } else if (quest.repeat == EnumQuestRepeat.MCWEEKLY) { - return player.worldObj.getTotalWorldTime() - questTime >= 168000; - } else if (quest.repeat == EnumQuestRepeat.MCCUSTOM) { - return player.worldObj.getTotalWorldTime() - questTime >= quest.customCooldown; - } else if (quest.repeat == EnumQuestRepeat.RLDAILY) { - return System.currentTimeMillis() - questTime >= 86400000; - } else if (quest.repeat == EnumQuestRepeat.RLWEEKLY) { - return System.currentTimeMillis() - questTime >= 604800000; - } else if (quest.repeat == EnumQuestRepeat.RLCUSTOM) { - return System.currentTimeMillis() - questTime >= quest.customCooldown; - } - return false; + return quest.getTimeUntilRepeat(player) <= 0; } public static Vector getActiveQuests(EntityPlayer player) { diff --git a/src/main/java/noppes/npcs/controllers/QuestController.java b/src/main/java/noppes/npcs/controllers/QuestController.java index 72688b7e5..e9b403ee7 100644 --- a/src/main/java/noppes/npcs/controllers/QuestController.java +++ b/src/main/java/noppes/npcs/controllers/QuestController.java @@ -80,7 +80,9 @@ public class QuestController implements IQuestHandler { ite.remove(); } else { quests.put(id, quest); - if (quest.profileOptions.enableOptions && quest.profileOptions.completeControl == EnumProfileSync.Shared) { + if (quest.profileOptions.enableOptions + && (quest.profileOptions.completeControl == EnumProfileSync.Shared + || quest.profileOptions.cooldownControl == EnumProfileSync.Shared)) { sharedQuests.put(id, quest); } } @@ -225,7 +227,9 @@ public class QuestController implements IQuestHandler { category.quests.put(quest.id, quest); sharedQuests.remove(quest.id); - if (quest.profileOptions.enableOptions && quest.profileOptions.completeControl == EnumProfileSync.Shared) { + if (quest.profileOptions.enableOptions + && (quest.profileOptions.completeControl == EnumProfileSync.Shared + || quest.profileOptions.cooldownControl == EnumProfileSync.Shared)) { sharedQuests.put(quest.id, quest); } diff --git a/src/main/java/noppes/npcs/controllers/data/Quest.java b/src/main/java/noppes/npcs/controllers/data/Quest.java index 1f9097d8a..c2b9ac397 100644 --- a/src/main/java/noppes/npcs/controllers/data/Quest.java +++ b/src/main/java/noppes/npcs/controllers/data/Quest.java @@ -178,19 +178,50 @@ public class Quest implements ICompatibilty, IQuest { public long getTimeUntilRepeat(EntityPlayer player) { if (ConfigMain.ProfilesEnabled && profileOptions.enableOptions && profileOptions.cooldownControl == EnumProfileSync.Shared) { Profile profile = ProfileController.Instance.getProfile(player); - IPlayer iPlayer = NoppesUtilServer.getIPlayer(player); - long timeRemaining = 0L; - for (ISlot slot : profile.getSlots().values()) { - IPlayerData playerData = ProfileController.Instance.getSlotPlayerData(iPlayer, slot.getId()); - IPlayerQuestData iPlayerQuestData = playerData.getQuestData(); - timeRemaining = Math.max(timeRemaining, getTimeUntilRepeatQuestData(player, iPlayerQuestData)); + if (profile != null) { + Long questTime = profile.sharedQuestTimestamps.get(this.id); + if (questTime == null) return 0L; + return calculateRemainingCooldown(player, questTime); } - return timeRemaining; } IPlayerQuestData questData = PlayerData.get(player).getQuestData(); return getTimeUntilRepeatQuestData(player, questData); } + public long calculateRemainingCooldown(EntityPlayer player, long questTime) { + switch (repeat) { + case MCDAILY: { + long now = player.worldObj.getTotalWorldTime(); + long remainingTicks = questTime + 24000 - now; + return Math.max(0, remainingTicks * 50); + } + case MCWEEKLY: { + long now = player.worldObj.getTotalWorldTime(); + long remainingTicks = questTime + 168000 - now; + return Math.max(0, remainingTicks * 50); + } + case MCCUSTOM: { + long now = player.worldObj.getTotalWorldTime(); + long remainingTicks = questTime + this.customCooldown - now; + return Math.max(0, remainingTicks * 50); + } + case RLDAILY: { + long remainingMillis = questTime + 86400000 - System.currentTimeMillis(); + return Math.max(0, remainingMillis); + } + case RLWEEKLY: { + long remainingMillis = questTime + 604800000 - System.currentTimeMillis(); + return Math.max(0, remainingMillis); + } + case RLCUSTOM: { + long remainingMillis = questTime + this.customCooldown - System.currentTimeMillis(); + return Math.max(0, remainingMillis); + } + default: + return 0L; + } + } + public long getTimeUntilRepeatQuestData(EntityPlayer player, IPlayerQuestData questData) { long questTime = questData.getLastCompletedTime(this.id);