From 39d2b9227d130da604798c6f4c7a92a3a07ab29b Mon Sep 17 00:00:00 2001 From: Kam Date: Tue, 19 Mar 2024 05:09:11 -0400 Subject: [PATCH] Quest Manual + Quest Objective Command Quest Manual allows you to add manual quests that can only be completed via script or command. The command will essentially call the .setProgress or .setPlayerProgress (if the player is within a party) to set the progress for the objectives. --- src/api | 2 +- .../java/kamkeel/command/QuestCommand.java | 96 ++++- .../npcs/client/gui/SubGuiNpcQuest.java | 6 +- .../gui/questtypes/GuiNpcQuestTypeKill.java | 13 +- .../gui/questtypes/GuiNpcQuestTypeManual.java | 87 ++++ .../noppes/npcs/constants/EnumQuestType.java | 2 +- .../noppes/npcs/controllers/data/Quest.java | 9 +- .../java/noppes/npcs/quests/QuestDialog.java | 74 +++- .../java/noppes/npcs/quests/QuestItem.java | 7 +- .../java/noppes/npcs/quests/QuestKill.java | 58 ++- .../noppes/npcs/quests/QuestLocation.java | 41 +- .../java/noppes/npcs/quests/QuestManual.java | 380 ++++++++++++++++++ src/main/java/noppes/npcs/util/ValueUtil.java | 16 + .../assets/customnpcs/lang/en_US.lang | 1 + 14 files changed, 773 insertions(+), 19 deletions(-) create mode 100644 src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeManual.java create mode 100644 src/main/java/noppes/npcs/quests/QuestManual.java diff --git a/src/api b/src/api index 911695647..5d059aea8 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 91169564745665d38d6f013871dda504b3e3a39f +Subproject commit 5d059aea800f572b7268ac679310ebc8b3d13f6c diff --git a/src/main/java/kamkeel/command/QuestCommand.java b/src/main/java/kamkeel/command/QuestCommand.java index 14c0a408f..887b5e47b 100644 --- a/src/main/java/kamkeel/command/QuestCommand.java +++ b/src/main/java/kamkeel/command/QuestCommand.java @@ -1,18 +1,24 @@ package kamkeel.command; +import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; import noppes.npcs.Server; +import noppes.npcs.api.handler.data.IQuestObjective; import noppes.npcs.constants.EnumPacketClient; import noppes.npcs.constants.EnumQuestCompletion; import noppes.npcs.constants.EnumQuestRepeat; import noppes.npcs.controllers.PlayerDataController; import noppes.npcs.controllers.QuestController; import noppes.npcs.controllers.SyncController; +import noppes.npcs.controllers.data.Party; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.controllers.data.Quest; import noppes.npcs.controllers.data.QuestData; +import noppes.npcs.util.ValueUtil; import java.util.Collection; import java.util.List; @@ -168,7 +174,7 @@ public class QuestCommand extends CommandKamkeelBase { Quest quest = QuestController.Instance.quests.get(questid); if (quest == null){ - sendError(sender, String.format("Unknown QuestID")); + sendError(sender, "Unknown QuestID"); return; } @@ -181,6 +187,94 @@ public class QuestCommand extends CommandKamkeelBase { } } + @SubCommand( + desc= "Get/Set objectives for quests progress", + usage = " [objective] [value]" + ) + public void objective(ICommandSender sender, String[] args) throws CommandException { + EntityPlayer player = CommandBase.getPlayer(sender, args[0]); + int questid; + try { + questid = Integer.parseInt(args[1]); + } catch (NumberFormatException ex) { + sendError(sender, "QuestID must be an integer: " + args[1]); + return; + } + + Quest quest = QuestController.Instance.quests.get(questid); + if (quest == null){ + sendError(sender, "Unknown QuestID"); + return; + } + + PlayerData data = PlayerDataController.Instance.getPlayerData(player); + if (data == null){ + sendError(sender, "No PlayerData found for:" + player); + return; + } + + Party party = data.getPlayerParty(); + boolean partyValid = party != null && party.getQuest() != null && party.getQuest().getId() == quest.id; + + if(!partyValid && !data.questData.activeQuests.containsKey(quest.id)) { + sendError(sender, "Player does not have quest active"); + return; + } + + IQuestObjective[] objectives; + if(partyValid) + objectives = quest.questInterface.getPartyObjectives(party); + else + objectives = quest.questInterface.getObjectives(player); + + if(args.length <= 2) { + if(partyValid) + sendResult(sender, "For Party: "); + for(IQuestObjective ob : objectives) { + sendResult(sender, ob.getText()); + } + return; + } + + int objective; + try { + objective = Integer.parseInt(args[2]); + } catch (NumberFormatException ex) { + sendError(sender, "Objective must be an integer. Most often 0, 1 or 2"); + return; + } + + if(objective < 0 || objective >= objectives.length) { + sendError(sender, "Invalid objective number was given"); + return; + } + + if(args.length <= 3) { + sendResult(sender, objectives[objective].getText()); + return; + } + + IQuestObjective object = objectives[objective]; + String s = args[3]; + int value; + try { + value = Integer.parseInt(args[3]); + } catch (NumberFormatException ex) { + sendError(sender, "Value must be an integer"); + return; + } + + if(s.startsWith("-") || s.startsWith("+")) { + value = ValueUtil.CorrectInt(object.getProgress() + value, 0, object.getMaxProgress()); + } + + if(partyValid) + object.setPlayerProgress(player.getCommandSenderName(), value); + else + object.setProgress(value); + sendResult(sender, "Successfully updated progress"); + } + @SubCommand( desc = "Find quest id number by its name", usage = "" diff --git a/src/main/java/noppes/npcs/client/gui/SubGuiNpcQuest.java b/src/main/java/noppes/npcs/client/gui/SubGuiNpcQuest.java index 482b04217..e1c32be0f 100644 --- a/src/main/java/noppes/npcs/client/gui/SubGuiNpcQuest.java +++ b/src/main/java/noppes/npcs/client/gui/SubGuiNpcQuest.java @@ -7,6 +7,7 @@ import noppes.npcs.client.gui.global.GuiNPCManageQuest; import noppes.npcs.client.gui.questtypes.GuiNpcQuestTypeDialog; import noppes.npcs.client.gui.questtypes.GuiNpcQuestTypeKill; import noppes.npcs.client.gui.questtypes.GuiNpcQuestTypeLocation; +import noppes.npcs.client.gui.questtypes.GuiNpcQuestTypeManual; import noppes.npcs.client.gui.select.GuiQuestSelection; import noppes.npcs.client.gui.util.*; import noppes.npcs.constants.*; @@ -57,7 +58,7 @@ public class SubGuiNpcQuest extends SubGuiInterface implements ISubGuiListener, addButton(new GuiNpcButton(11, guiLeft + 303, guiTop + 52, 50, 20, "selectServer.edit")); addLabel(new GuiNpcLabel(6, "gui.type", guiLeft + 180, guiTop + 81)); - addButton(new GuiNpcButton(6, guiLeft + 240, guiTop + 76, 60, 20, new String[]{"quest.item","quest.dialog","quest.kill","quest.location","quest.areakill"},quest.type.ordinal())); + addButton(new GuiNpcButton(6, guiLeft + 240, guiTop + 76, 60, 20, new String[]{"quest.item","quest.dialog","quest.kill","quest.location","quest.areakill","quest.manual"},quest.type.ordinal())); addButton(new GuiNpcButton(7, guiLeft + 303, guiTop + 76,50, 20, "selectServer.edit")); addLabel(new GuiNpcLabel(17, "party.options", guiLeft + 180, guiTop + 135)); @@ -121,6 +122,9 @@ public class SubGuiNpcQuest extends SubGuiInterface implements ISubGuiListener, if(quest.type == EnumQuestType.AreaKill) setSubGui(new GuiNpcQuestTypeKill(npc, quest, this)); + + if(quest.type == EnumQuestType.Manual) + setSubGui(new GuiNpcQuestTypeManual(npc, quest, this)); } if(button.id == 8) { diff --git a/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeKill.java b/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeKill.java index 6112b0c03..19ca84c53 100644 --- a/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeKill.java +++ b/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeKill.java @@ -14,21 +14,22 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.TreeMap; public class GuiNpcQuestTypeKill extends SubGuiInterface implements ITextfieldListener, ICustomScrollListener { private GuiScreen parent; private GuiCustomScroll scroll; - + private QuestKill quest; - + private GuiNpcTextField lastSelected; public GuiNpcQuestTypeKill(EntityNPCInterface npc, Quest q, GuiScreen parent) { this.npc = npc; this.parent = parent; title = "Quest Kill Setup"; - + quest = (QuestKill) q.questInterface; setBackground("largebg.png"); @@ -54,7 +55,7 @@ public class GuiNpcQuestTypeKill extends SubGuiInterface implements ITextfieldLi this.getTextField(i+12).setMinMaxDefault(1, Integer.MAX_VALUE, 1); i++; } - + for(;i < 12; i++){ this.addTextField(new GuiNpcTextField(i, this, fontRendererObj, guiLeft + 4, guiTop + 40 + i * 22, 180, 20, "")); this.addTextField(new GuiNpcTextField(i + 12, this, fontRendererObj, guiLeft + 186, guiTop + 40 + i * 22, 24, 20, "1")); @@ -72,7 +73,7 @@ public class GuiNpcQuestTypeKill extends SubGuiInterface implements ITextfieldLi e.printStackTrace(); } catch (NoSuchMethodException e) { } - } + } if(scroll == null) scroll = new GuiCustomScroll(this,0); scroll.setList(list); @@ -122,7 +123,7 @@ public class GuiNpcQuestTypeKill extends SubGuiInterface implements ITextfieldLi saveTargets(); } private void saveTargets(){ - HashMap map = new HashMap(); + TreeMap map = new TreeMap(); for(int i = 0; i< 12; i++){ String name = getTextField(i).getText(); if(name.isEmpty()) diff --git a/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeManual.java b/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeManual.java new file mode 100644 index 000000000..19f2293bb --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/questtypes/GuiNpcQuestTypeManual.java @@ -0,0 +1,87 @@ +package noppes.npcs.client.gui.questtypes; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import noppes.npcs.client.gui.util.*; +import noppes.npcs.controllers.data.Quest; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.quests.QuestManual; + +import java.util.HashMap; +import java.util.TreeMap; + +public class GuiNpcQuestTypeManual extends SubGuiInterface implements ITextfieldListener +{ + private GuiScreen parent; + + private QuestManual quest; + + private GuiNpcTextField lastSelected; + + public GuiNpcQuestTypeManual(EntityNPCInterface npc, Quest q, GuiScreen parent) { + this.npc = npc; + this.parent = parent; + title = "Quest Manual Setup"; + + quest = (QuestManual) q.questInterface; + + setBackground("menubg.png"); + xSize = 356; + ySize = 216; + closeOnEsc = true; + } + + @Override + public void initGui() { + super.initGui(); + int i = 0; + addLabel(new GuiNpcLabel(0, "You can fill in npc or player names too", guiLeft + 4, guiTop + 50)); + for (String name : quest.manuals.keySet()) { + this.addTextField(new GuiNpcTextField(i, this, fontRendererObj, guiLeft + 4, guiTop + 70 + i * 22, 180, 20, name)); + this.addTextField(new GuiNpcTextField(i + 3, this, fontRendererObj, guiLeft + 186, guiTop + 70 + i * 22, 24, 20, quest.manuals.get(name) + "")); + this.getTextField(i+3).integersOnly = true; + this.getTextField(i+3).setMinMaxDefault(1, Integer.MAX_VALUE, 1); + i++; + } + + for(;i < 3; i++){ + this.addTextField(new GuiNpcTextField(i, this, fontRendererObj, guiLeft + 4, guiTop + 70 + i * 22, 180, 20, "")); + this.addTextField(new GuiNpcTextField(i + 3, this, fontRendererObj, guiLeft + 186, guiTop + 70 + i * 22, 24, 20, "1")); + this.getTextField(i+3).integersOnly = true; + this.getTextField(i+3).setMinMaxDefault(1, Integer.MAX_VALUE, 1); + } + this.addButton(new GuiNpcButton(0, guiLeft + 4, guiTop + 140, 98, 20, "gui.back")); + + } + + @Override + protected void actionPerformed(GuiButton guibutton) { + super.actionPerformed(guibutton); + if (guibutton.id == 0) { + close(); + } + } + + @Override + public void save() { + } + + @Override + public void unFocused(GuiNpcTextField guiNpcTextField) { + if(guiNpcTextField.id < 3) + lastSelected = guiNpcTextField; + + saveTargets(); + } + + private void saveTargets(){ + TreeMap map = new TreeMap(); + for(int i = 0; i< 3; i++){ + String name = getTextField(i).getText(); + if(name.isEmpty()) + continue; + map.put(name, getTextField(i+3).getInteger()); + } + quest.manuals = map; + } +} diff --git a/src/main/java/noppes/npcs/constants/EnumQuestType.java b/src/main/java/noppes/npcs/constants/EnumQuestType.java index 2ca6b0591..315fee0b8 100644 --- a/src/main/java/noppes/npcs/constants/EnumQuestType.java +++ b/src/main/java/noppes/npcs/constants/EnumQuestType.java @@ -1,5 +1,5 @@ package noppes.npcs.constants; public enum EnumQuestType { - Item, Dialog, Kill, Location, AreaKill; + Item, Dialog, Kill, Location, AreaKill, Manual; } diff --git a/src/main/java/noppes/npcs/controllers/data/Quest.java b/src/main/java/noppes/npcs/controllers/data/Quest.java index 5ffb91914..d780ee053 100644 --- a/src/main/java/noppes/npcs/controllers/data/Quest.java +++ b/src/main/java/noppes/npcs/controllers/data/Quest.java @@ -13,9 +13,14 @@ import noppes.npcs.constants.EnumQuestRepeat; import noppes.npcs.constants.EnumQuestType; import noppes.npcs.controllers.PlayerDataController; import noppes.npcs.controllers.QuestController; -import noppes.npcs.quests.*; import noppes.npcs.scripted.CustomNPCsException; import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.quests.QuestDialog; +import noppes.npcs.quests.QuestInterface; +import noppes.npcs.quests.QuestItem; +import noppes.npcs.quests.QuestKill; +import noppes.npcs.quests.QuestLocation; +import noppes.npcs.quests.QuestManual; public class Quest implements ICompatibilty, IQuest { public int version = VersionCompatibility.ModRev; @@ -87,6 +92,8 @@ public class Quest implements ICompatibilty, IQuest { questInterface = new QuestKill(); else if(type == EnumQuestType.Location) questInterface = new QuestLocation(); + else if(type == EnumQuestType.Manual) + questInterface = new QuestManual(); if(questInterface != null) questInterface.questId = id; diff --git a/src/main/java/noppes/npcs/quests/QuestDialog.java b/src/main/java/noppes/npcs/quests/QuestDialog.java index 30e9805ee..7a5e10a57 100644 --- a/src/main/java/noppes/npcs/quests/QuestDialog.java +++ b/src/main/java/noppes/npcs/quests/QuestDialog.java @@ -392,7 +392,79 @@ public class QuestDialog extends QuestInterface implements IQuestDialog { } } - public int getMaxProgress() { + @Override + public void setPlayerProgress(String playerName, int progress) { + if (progress >= 0 && progress <= 1) { + EntityPlayer foundplayer = NoppesUtilServer.getPlayerByName(playerName); + if(foundplayer != null && party == null){ + PlayerData data = PlayerDataController.Instance.getPlayerData(foundplayer); + boolean completed = data.dialogData.dialogsRead.contains(this.dialog.id); + if (progress == 0 && completed) { + data.dialogData.dialogsRead.remove(this.dialog.id); + data.questData.checkQuestCompletion(data, EnumQuestType.values()[1]); + data.updateClient = true; + data.save(); + } + + if (progress == 1 && !completed) { + data.dialogData.dialogsRead.add(this.dialog.id); + data.questData.checkQuestCompletion(data, EnumQuestType.values()[1]); + data.updateClient = true; + data.save(); + } + } else if (foundplayer != null){ + if(party.getObjectiveRequirement() != null){ + EnumPartyObjectives objectives = party.getObjectiveRequirement(); + if(objectives == EnumPartyObjectives.Leader){ + EntityPlayer leaderPlayer = NoppesUtilServer.getPlayer(party.getLeaderUUID()); + PlayerData leaderData; + if(leaderPlayer != null){ + leaderData = PlayerDataController.Instance.getPlayerData(leaderPlayer); + } + else { + leaderData = PlayerDataController.Instance.getPlayerDataCache(party.getLeaderUUID().toString()); + } + if(leaderData == null) + return; + + boolean completed = leaderData.dialogData.dialogsRead.contains(this.dialog.id); + if (progress == 0 && completed) { + leaderData.dialogData.dialogsRead.remove(this.dialog.id); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[1]); + leaderData.updateClient = true; + leaderData.save(); + } + if (progress == 1 && !completed) { + leaderData.dialogData.dialogsRead.add(this.dialog.id); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[1]); + leaderData.updateClient = true; + leaderData.save(); + } + } else { + PlayerData individualData = PlayerDataController.Instance.getPlayerData(foundplayer); + if(individualData != null){ + boolean completed = individualData.dialogData.dialogsRead.contains(this.dialog.id); + if (progress == 0 && completed) { + individualData.dialogData.dialogsRead.remove(this.dialog.id); + individualData.save(); + individualData.updateClient = true; + } + if (progress == 1 && !completed) { + individualData.dialogData.dialogsRead.add(this.dialog.id); + individualData.save(); + individualData.updateClient = true; + } + } + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[1]); + } + } + } + } else { + throw new CustomNPCsException("Progress has to be 0 or 1", new Object[0]); + } + } + + public int getMaxProgress() { return 1; } diff --git a/src/main/java/noppes/npcs/quests/QuestItem.java b/src/main/java/noppes/npcs/quests/QuestItem.java index 90b9c9715..c864adad1 100644 --- a/src/main/java/noppes/npcs/quests/QuestItem.java +++ b/src/main/java/noppes/npcs/quests/QuestItem.java @@ -539,7 +539,12 @@ public class QuestItem extends QuestInterface implements IQuestItem { throw new CustomNPCsException("Cant set the progress of ItemQuests", new Object[0]); } - public int getMaxProgress() { + @Override + public void setPlayerProgress(String playerName, int progress) { + throw new CustomNPCsException("Cant set the progress of ItemQuests", new Object[0]); + } + + public int getMaxProgress() { if(party != null && party.getObjectiveRequirement() != null){ EnumPartyObjectives objectives = party.getObjectiveRequirement(); if(objectives == EnumPartyObjectives.All){ diff --git a/src/main/java/noppes/npcs/quests/QuestKill.java b/src/main/java/noppes/npcs/quests/QuestKill.java index a62a0f58d..1f6f4e3d4 100644 --- a/src/main/java/noppes/npcs/quests/QuestKill.java +++ b/src/main/java/noppes/npcs/quests/QuestKill.java @@ -3,6 +3,7 @@ package noppes.npcs.quests; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.NBTTags; +import noppes.npcs.NoppesUtilServer; import noppes.npcs.api.handler.data.IQuestKill; import noppes.npcs.api.handler.data.IQuestObjective; import noppes.npcs.constants.EnumPartyObjectives; @@ -18,7 +19,7 @@ import noppes.npcs.scripted.CustomNPCsException; import java.util.*; public class QuestKill extends QuestInterface implements IQuestKill { - public HashMap targets = new HashMap(); + public TreeMap targets = new TreeMap(); public int targetType = 0; public String customTargetType = "noppes.npcs.entity.EntityCustomNpc"; @@ -33,10 +34,10 @@ public class QuestKill extends QuestInterface implements IQuestKill { public void readEntityFromNBT(NBTTagCompound compound) { if(!compound.hasKey("QuestKills")) { targets.clear(); - HashMap oldTargets = NBTTags.getStringIntegerMap(compound.getTagList("QuestDialogs", 10)); + TreeMap oldTargets = new TreeMap(NBTTags.getStringIntegerMap(compound.getTagList("QuestDialogs", 10))); targets.putAll(oldTargets); } else { - targets = NBTTags.getStringIntegerMap(compound.getTagList("QuestKills", 10)); + targets = new TreeMap(NBTTags.getStringIntegerMap(compound.getTagList("QuestKills", 10))); } targetType = compound.getInteger("TargetType"); customTargetType = compound.getString("CustomTargetType"); @@ -235,6 +236,7 @@ public class QuestKill extends QuestInterface implements IQuestKill { this.targetType = type; } + public int getTargetType() { return this.targetType; } @@ -339,7 +341,54 @@ public class QuestKill extends QuestInterface implements IQuestKill { } } - public int getMaxProgress() { + @Override + public void setPlayerProgress(String playerName, int progress) { + if (progress >= 0 && progress <= this.amount) { + EntityPlayer foundplayer = NoppesUtilServer.getPlayerByName(playerName); + if(foundplayer != null && party == null){ + PlayerData data = PlayerDataController.Instance.getPlayerData(foundplayer); + PlayerQuestData playerdata = data.questData; + QuestData questdata = (QuestData)playerdata.activeQuests.get(this.parent.questId); + if(questdata != null){ + HashMap killed = this.parent.getKilled(questdata); + if (!killed.containsKey(this.entity) || (Integer)killed.get(this.entity) != progress) { + killed.put(this.entity, progress); + this.parent.setKilled(questdata, killed); + data.questData.checkQuestCompletion(data, EnumQuestType.values()[2]); + data.questData.checkQuestCompletion(data, EnumQuestType.values()[4]); + data.updateClient = true; + data.save(); + } + } + } else if (foundplayer != null){ + QuestData questdata = party.getQuestData(); + if(questdata != null){ + if(questdata.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All){ + HashMap killed = this.parent.getPlayerKilled(questdata, playerName); + if (!killed.containsKey(this.entity) || (Integer)killed.get(this.entity) != progress) { + killed.put(this.entity, progress); + this.parent.setPlayerKilled(questdata, killed, playerName); + } + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[2]); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[4]); + } + else { + HashMap killed = this.parent.getKilled(questdata); + if (!killed.containsKey(this.entity) || (Integer)killed.get(this.entity) != progress) { + killed.put(this.entity, progress); + this.parent.setKilled(questdata, killed); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[2]); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[4]); + } + } + } + } + } else { + throw new CustomNPCsException("Progress has to be between 0 and " + this.amount, new Object[0]); + } + } + + public int getMaxProgress() { return this.amount; } @@ -376,7 +425,6 @@ public class QuestKill extends QuestInterface implements IQuestKill { } } } - return null; } } diff --git a/src/main/java/noppes/npcs/quests/QuestLocation.java b/src/main/java/noppes/npcs/quests/QuestLocation.java index 14b895855..85b09d1c0 100644 --- a/src/main/java/noppes/npcs/quests/QuestLocation.java +++ b/src/main/java/noppes/npcs/quests/QuestLocation.java @@ -4,6 +4,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.StatCollector; import noppes.npcs.NBTTags; +import noppes.npcs.NoppesUtilServer; import noppes.npcs.api.handler.data.IQuestLocation; import noppes.npcs.api.handler.data.IQuestObjective; import noppes.npcs.constants.EnumPartyObjectives; @@ -370,7 +371,45 @@ public class QuestLocation extends QuestInterface implements IQuestLocation { } } - public int getMaxProgress() { + @Override + public void setPlayerProgress(String playerName, int progress) { + if (progress >= 0 && progress <= 1) { + EntityPlayer foundplayer = NoppesUtilServer.getPlayerByName(playerName); + if(foundplayer != null && party == null){ + PlayerData data = PlayerDataController.Instance.getPlayerData(foundplayer); + QuestData questData = (QuestData)data.questData.activeQuests.get(this.parent.questId); + boolean completed = questData.extraData.getBoolean (this.nbtName); + if ((!completed || progress != 1) && (completed || progress != 0)) { + questData.extraData.setBoolean(this.nbtName, progress == 1); + data.questData.checkQuestCompletion(data, EnumQuestType.values()[3]); + data.save(); + data.updateClient = true; + } + } else if (foundplayer != null){ + QuestData questData = party.getQuestData(); + boolean completed = questData.extraData.getBoolean (this.nbtName); + if ((!completed || progress != 1) && (completed || progress != 0)) { + boolean setTo = progress == 1; + questData.extraData.setBoolean(this.nbtName, setTo); + if(questData.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All){ + if(setTo){ + if(!completedPlayers.contains(foundplayer.getCommandSenderName())) + completedPlayers.add(foundplayer.getCommandSenderName()); + } else { + completedPlayers.remove(foundplayer.getCommandSenderName()); + } + String locationKey = "Players" + nbtName; + questData.extraData.setTag(locationKey, NBTTags.nbtStringList(completedPlayers)); + } + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.values()[3]); + } + } + } else { + throw new CustomNPCsException("Progress has to be 0 or 1", new Object[0]); + } + } + + public int getMaxProgress() { return 1; } diff --git a/src/main/java/noppes/npcs/quests/QuestManual.java b/src/main/java/noppes/npcs/quests/QuestManual.java new file mode 100644 index 000000000..b4e680806 --- /dev/null +++ b/src/main/java/noppes/npcs/quests/QuestManual.java @@ -0,0 +1,380 @@ +package noppes.npcs.quests; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; +import noppes.npcs.NBTTags; +import noppes.npcs.NoppesUtilServer; +import noppes.npcs.api.handler.data.IQuestObjective; +import noppes.npcs.constants.EnumPartyObjectives; +import noppes.npcs.constants.EnumQuestType; +import noppes.npcs.controllers.PartyController; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.data.Party; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.controllers.data.PlayerQuestData; +import noppes.npcs.controllers.data.QuestData; +import noppes.npcs.scripted.CustomNPCsException; + +import java.util.*; +import java.util.Map.Entry; + +public class QuestManual extends QuestInterface{ + public TreeMap manuals = new TreeMap(); + + @Override + public void readEntityFromNBT(NBTTagCompound compound) { + manuals = new TreeMap<>(NBTTags.getStringIntegerMap(compound.getTagList("QuestManual", 10))); + } + + @Override + public void writeEntityToNBT(NBTTagCompound compound) { + compound.setTag("QuestManual", NBTTags.nbtStringIntegerMap(manuals)); + } + + @Override + public boolean isCompleted(PlayerData playerData) { + if(playerData == null) + return false; + + QuestData data = playerData.questData.activeQuests.get(questId); + if(data == null) + return false; + HashMap manual = getManual(data); + if (manuals.size() != manual.size()) + return false; + + for (String entity : manuals.keySet()) { + if (!manual.containsKey(entity) || manual.get(entity) < manuals.get(entity)) + return false; + } + + return true; + } + + @Override + public void handleComplete(EntityPlayer player) {} + + @Override + public Vector getQuestLogStatus(EntityPlayer player) { + Vector vec = new Vector(); + PlayerData playerdata = PlayerDataController.Instance.getPlayerData(player); + if (playerdata == null) + return vec; + + QuestData data = playerdata.questData.activeQuests.get(questId); + if (data == null) + return vec; + + HashMap manual = getManual(data); + for (String entity : manuals.keySet()) { + vec.add(entity + ": " + manual.getOrDefault(entity, 0) + "/" + manuals.get(entity)); + } + return vec; + } + + public HashMap getManual(QuestData data) { + return NBTTags.getStringIntegerMap(data.extraData.getTagList("Manual", 10)); + } + + public void setManual(QuestData data, HashMap manual) { + data.extraData.setTag("Manual", NBTTags.nbtStringIntegerMap(manual)); + } + + public HashMap getPlayerManual(QuestData data, String playerName) { + return NBTTags.getStringIntegerMap(data.extraData.getTagList(playerName + "Manual", 10)); + } + public void setPlayerManual(QuestData data, HashMap playerManual, String playerName) { + data.extraData.setTag(playerName + "Manual", NBTTags.nbtStringIntegerMap(playerManual)); + } + + @Override + public IQuestObjective[] getObjectives(EntityPlayer player) { + List list = new ArrayList(); + for(Entry entry : manuals.entrySet()){ + list.add(new QuestManualObjective(player, entry.getKey(), entry.getValue())); + } + return list.toArray(new IQuestObjective[list.size()]); + } + + @Override + public IQuestObjective[] getPartyObjectives(Party party){ + List list = new ArrayList(); + for(Entry entry : manuals.entrySet()){ + list.add(new QuestManualObjective(party, entry.getKey(), entry.getValue())); + } + return (IQuestObjective[])list.toArray(new IQuestObjective[list.size()]); + } + + @Override + public Vector getPartyQuestLogStatus(Party party) { + Vector vec = new Vector(); + QuestData data = party.getQuestData(); + if(data == null) + return vec; + + if(data.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All){ + for(String entityName : manuals.keySet()){ + String firstLine = entityName + ": " + manuals.get(entityName); + List playerResults = new ArrayList<>(); + for(String player : party.getPlayerNames()){ + HashMap playerManual = getPlayerManual(data, player); + int amount = 0; + if(playerManual.containsKey(entityName)) + amount = playerManual.get(entityName); + + if(amount < manuals.get(entityName)){ + String state = player + ": " + amount; + playerResults.add(state); + } + } + + if(!playerResults.isEmpty()){ + vec.add(firstLine); + vec.add("[" + String.join(", ", playerResults) + "]"); + } + else { + vec.add(firstLine + " (Done)"); + } + } + } + else { + HashMap manual = getManual(data); + for (String entity : manuals.keySet()) { + int amount = 0; + if(manual.containsKey(entity)) + amount = manual.get(entity); + String state = amount + "/" + manuals.get(entity); + vec.add(entity + ": " + state); + } + } + return vec; + } + + @Override + public boolean isPartyCompleted(Party party) { + if(party == null) + return false; + + QuestData data = party.getQuestData(); + if(data == null) + return false; + + if(data.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All){ + for(String entityName : manuals.keySet()){ + for(String player : party.getPlayerNames()){ + HashMap playerManual = getPlayerManual(data, player); + int amount = playerManual.getOrDefault(entityName, 0); + if(amount < manuals.get(entityName)){ + return false; + } + } + } + } + else { + int completed = 0; + HashMap playerManual = getManual(data); + for(String entityName : manuals.keySet()){ + int amount = 0; + if(playerManual.containsKey(entityName)) + amount = playerManual.get(entityName); + if(amount >= manuals.get(entityName)){ + completed++; + } + } + if(completed >= manuals.keySet().size()) + return true; + + if(playerManual.size() != manuals.size()) + return false; + for(String entity : playerManual.keySet()){ + if(!manuals.containsKey(entity) || manuals.get(entity) > playerManual.get(entity)) + return false; + } + } + return true; + } + + class QuestManualObjective implements IQuestObjective{ + private final EntityPlayer player; + private final String entity; + private final Party party; + private final int amount; + + public QuestManualObjective(EntityPlayer player, String entity, int amount) { + this.player = player; + this.entity = entity; + this.amount = amount; + this.party = null; + } + + public QuestManualObjective(Party party, String entity, int amount) { + this.party = party; + this.entity = entity; + this.amount = amount; + this.player = null; + } + + @Override + public int getProgress() { + if(player != null){ + PlayerData data = PlayerDataController.Instance.getPlayerData(player); + PlayerQuestData playerdata = data.questData; + QuestData questdata = (QuestData)playerdata.activeQuests.get(questId); + if(questdata != null){ + HashMap playerManual = getManual(questdata); + return !playerManual.containsKey(this.entity) ? 0 : (Integer)playerManual.get(this.entity); + } + } else if(party != null) { + QuestData questdata = party.getQuestData(); + if (questdata != null) { + if (questdata.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All) { + int progress = 0; + for (String player : party.getPlayerNames()) { + HashMap playerManual = getPlayerManual(questdata, player); + int currentProgress = !playerManual.containsKey(this.entity) ? 0 : (Integer) playerManual.get(this.entity); + if(currentProgress >= this.amount) + progress += 1; + } + return progress; + } else { + HashMap playerManual = getManual(questdata); + return !playerManual.containsKey(this.entity) ? 0 : (Integer) playerManual.get(this.entity); + } + } + } + return 0; + } + + @Override + public void setProgress(int progress) { + if (progress >= 0 && progress <= this.amount) { + if (player != null) { + PlayerData data = PlayerDataController.Instance.getPlayerData(player); + PlayerQuestData playerdata = data.questData; + QuestData questdata = (QuestData) playerdata.activeQuests.get(questId); + if (questdata != null) { + HashMap playerManual = getManual(questdata); + if (!playerManual.containsKey(this.entity) || (Integer) playerManual.get(this.entity) != progress) { + playerManual.put(this.entity, progress); + setManual(questdata, playerManual); + data.questData.checkQuestCompletion(data, EnumQuestType.Manual); + data.updateClient = true; + data.save(); + } + } + } else if (party != null) { + QuestData questdata = party.getQuestData(); + if (questdata != null) { + if (questdata.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All) { + for (String player : party.getPlayerNames()) { + HashMap playerManual = getPlayerManual(questdata, player); + if (!playerManual.containsKey(this.entity) || (Integer) playerManual.get(this.entity) != progress) { + playerManual.put(this.entity, progress); + setPlayerManual(questdata, playerManual, player); + } + } + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.Manual); + } else { + HashMap playerManual = getManual(questdata); + if (!playerManual.containsKey(this.entity) || (Integer) playerManual.get(this.entity) != progress) { + playerManual.put(this.entity, progress); + setManual(questdata, playerManual); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.Manual); + } + } + } + } + } else { + throw new CustomNPCsException("Progress has to be between 0 and " + this.amount, new Object[0]); + } + } + + @Override + public void setPlayerProgress(String playerName, int progress) { + if (progress >= 0 && progress <= this.amount) { + EntityPlayer foundplayer = NoppesUtilServer.getPlayerByName(playerName); + if(foundplayer != null && party == null){ + PlayerData data = PlayerDataController.Instance.getPlayerData(foundplayer); + PlayerQuestData playerdata = data.questData; + QuestData questdata = (QuestData) playerdata.activeQuests.get(questId); + if (questdata != null) { + HashMap playerManual = getManual(questdata); + if (!playerManual.containsKey(this.entity) || (Integer) playerManual.get(this.entity) != progress) { + playerManual.put(this.entity, progress); + setManual(questdata, playerManual); + data.questData.checkQuestCompletion(data, EnumQuestType.Manual); + data.updateClient = true; + data.save(); + } + } + } else if (foundplayer != null){ + QuestData questdata = party.getQuestData(); + if (questdata != null) { + if (questdata.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All) { + HashMap playerManual = getPlayerManual(questdata, foundplayer.getCommandSenderName()); + if (!playerManual.containsKey(this.entity) || (Integer) playerManual.get(this.entity) != progress) { + playerManual.put(this.entity, progress); + setPlayerManual(questdata, playerManual, foundplayer.getCommandSenderName()); + } + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.Manual); + } else { + HashMap playerManual = getManual(questdata); + if (!playerManual.containsKey(this.entity) || (Integer) playerManual.get(this.entity) != progress) { + playerManual.put(this.entity, progress); + setManual(questdata, playerManual); + PartyController.Instance().checkQuestCompletion(party, EnumQuestType.Manual); + } + } + } + } + } else { + throw new CustomNPCsException("Progress has to be between 0 and " + this.amount, new Object[0]); + } + } + + @Override + public int getMaxProgress() { + return amount; + } + + @Override + public boolean isCompleted() { + return getProgress() >= amount; + } + + @Override + public String getText() { + if(party != null) { + if(party.getObjectiveRequirement() == EnumPartyObjectives.All ){ + return this.entity + ": " + this.getMaxProgress() + (isCompleted() ? " (Done)" : ""); + } + } + return this.entity + ": " + this.getProgress() + "/" + this.getMaxProgress(); + } + + @Override + public String getAdditionalText() { + if(party != null) { + List incompletePlayers = new ArrayList<>(); + QuestData questdata = party.getQuestData(); + if (questdata != null) { + if (questdata.quest.partyOptions.objectiveRequirement == EnumPartyObjectives.All) { + for (String player : party.getPlayerNames()) { + HashMap playerManual = getPlayerManual(questdata, player); + int currentProgress = !playerManual.containsKey(this.entity) ? 0 : (Integer) playerManual.get(this.entity); + if(currentProgress < this.amount){ + String state = player + ": " + currentProgress; + incompletePlayers.add(state); + } + } + if(!incompletePlayers.isEmpty()) + return "[" + String.join(", ", incompletePlayers) + "]"; + } + } + } + return null; + } + } + +} diff --git a/src/main/java/noppes/npcs/util/ValueUtil.java b/src/main/java/noppes/npcs/util/ValueUtil.java index 5f01534a3..1643accd2 100644 --- a/src/main/java/noppes/npcs/util/ValueUtil.java +++ b/src/main/java/noppes/npcs/util/ValueUtil.java @@ -32,4 +32,20 @@ public class ValueUtil { return min; return Math.min(given, max); } + + public static float correctFloat(float given, float min, float max){ + if(given < min) + return min; + if(given > max) + return max; + return given; + } + + public static int CorrectInt(int given, int min, int max) { + if(given < min) + return min; + if(given > max) + return max; + return given; + } } diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index a0a9c8883..32a33eacf 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -595,6 +595,7 @@ quest.kill=Kill quest.areakill=AreaKill quest.dialog=Dialog quest.location=Location +quest.manual=Manual quest.completedtext=Completed text quest.questlogtext=Questlog text quest.complete=Complete