diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/FTBQuestsEventHandler.java b/common/src/main/java/dev/ftb/mods/ftbquests/FTBQuestsEventHandler.java index 2ecd3a152..f6cb9d3e4 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/FTBQuestsEventHandler.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/FTBQuestsEventHandler.java @@ -10,6 +10,7 @@ import dev.ftb.mods.ftbquests.quest.TeamData; import dev.ftb.mods.ftbquests.quest.task.DimensionTask; import dev.ftb.mods.ftbquests.quest.task.KillTask; +import dev.ftb.mods.ftbquests.quest.task.ScoreboardTask; import dev.ftb.mods.ftbquests.quest.task.Task; import dev.ftb.mods.ftbquests.util.FTBQuestsInventoryListener; import dev.ftb.mods.ftbteams.event.PlayerChangedTeamEvent; @@ -26,6 +27,7 @@ import net.minecraft.commands.Commands; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerScoreboard; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; @@ -38,7 +40,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; - import java.util.List; /** @@ -72,6 +73,13 @@ public void init() { private void serverAboutToStart(MinecraftServer server) { ServerQuestFile.INSTANCE = new ServerQuestFile(server); + final ServerScoreboard scoreboard = ServerQuestFile.INSTANCE.server.getScoreboard(); + scoreboard.addDirtyListener(() -> { + ServerQuestFile file = ServerQuestFile.INSTANCE; + for (ScoreboardTask task : file.collect(ScoreboardTask.class)) { + task.test(file, scoreboard); + } + }); } private void registerCommands(CommandDispatcher dispatcher, Commands.CommandSelection selection) { diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestButton.java b/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestButton.java index 48c9658c3..1917442ae 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestButton.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestButton.java @@ -186,6 +186,16 @@ public void onClicked(MouseButton button) { getGui().openContextMenu(contextMenu2); })); + contextMenu.add(new ContextMenuItem(new TranslatableComponent("ftbquests.gui.clear_reward_all"), ThemeProperties.DELETE_ICON.get(quest), () -> { + for (Movable movable : questScreen.selectedObjects) { + if (movable instanceof Quest) { + Quest q = (Quest)movable; + q.rewards.clear(); + new EditObjectMessage(q).sendToServer(); + } + } + })); + contextMenu.add(new ContextMenuItem(new TranslatableComponent("selectServer.delete"), ThemeProperties.DELETE_ICON.get(quest), () -> { questScreen.selectedObjects.forEach(q -> { if (q instanceof Quest) { @@ -214,11 +224,8 @@ public void addMouseOverText(TooltipList list) { list.add(new TranslatableComponent("ftbquests.gui.move_tooltip").withStyle(ChatFormatting.DARK_GRAY)); } }); - - // contextMenu.add(new ContextMenuItem(new TranslatableComponent("ftbquests.gui.edit_text"), GuiIcons.INFO, () -> TextEditorFrame.open(quest))); - - contextMenu.add(ContextMenuItem.SEPARATOR); questScreen.addObjectMenuItems(contextMenu, getGui(), quest); + // contextMenu.add(new ContextMenuItem(new TranslatableComponent("ftbquests.gui.edit_text"), GuiIcons.INFO, () -> TextEditorFrame.open(quest))); } getGui().openContextMenu(contextMenu); diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestScreen.java b/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestScreen.java index df9f5cc74..c113c15d6 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestScreen.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/QuestScreen.java @@ -175,11 +175,16 @@ public void toggleSelected(Movable movable) { } } + public void addObjectMenuItems(List contextMenu, Runnable gui, QuestObjectBase object) { ConfigGroup group = new ConfigGroup(FTBQuests.MOD_ID); ConfigGroup g = object.createSubGroup(group); object.getConfig(g); + contextMenu.add(new ContextMenuItem(new TranslatableComponent("selectServer.edit"), ThemeProperties.EDIT_ICON.get(), () -> object.onEditButtonClicked(gui))); + contextMenu.add(ContextMenuItem.SEPARATOR); + + if (!g.getValues().isEmpty()) { List list = new ArrayList<>(); @@ -222,8 +227,6 @@ public void drawIcon(PoseStack matrixStack, Theme theme, int x, int y, int w, in } } - contextMenu.add(new ContextMenuItem(new TranslatableComponent("selectServer.edit"), ThemeProperties.EDIT_ICON.get(), () -> object.onEditButtonClicked(gui))); - if (object instanceof RandomReward && !QuestObjectBase.isNull(((RandomReward) object).getTable())) { contextMenu.add(new ContextMenuItem(new TranslatableComponent("ftbquests.reward_table.edit"), ThemeProperties.EDIT_ICON.get(), () -> ((RandomReward) object).getTable().onEditButtonClicked(gui))); } diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/ViewQuestPanel.java b/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/ViewQuestPanel.java index b9d622de0..59b3d96b5 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/ViewQuestPanel.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/gui/quests/ViewQuestPanel.java @@ -124,6 +124,8 @@ public CursorType getCursor() { if (quest.minWidth > 0) { w = Math.max(quest.minWidth, w); + } else if (questScreen.selectedChapter.defaultMinWidth > 0) { + w = Math.max(questScreen.selectedChapter.defaultMinWidth, w); } titleField.setPosAndSize(27, 4, w - 54, 8); diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/Chapter.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/Chapter.java index 3d7d2c888..8cf0fe9c9 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/Chapter.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/Chapter.java @@ -41,6 +41,7 @@ public final class Chapter extends QuestObject { public String defaultQuestShape; public final List images; public boolean defaultHideDependencyLines; + public int defaultMinWidth = 0; public Chapter(QuestFile f, ChapterGroup g) { file = f; @@ -102,6 +103,8 @@ public void writeData(CompoundTag nbt) { nbt.put("images", list); } + + nbt.putInt("default_min_width", defaultMinWidth); } @Override @@ -134,6 +137,8 @@ public void readData(CompoundTag nbt) { image.readData(imgs.getCompound(i)); images.add(image); } + + defaultMinWidth = nbt.getInt("default_min_width"); } @Override @@ -145,6 +150,7 @@ public void writeNetData(FriendlyByteBuf buffer) { buffer.writeUtf(defaultQuestShape, Short.MAX_VALUE); NetUtils.write(buffer, images, (d, img) -> img.writeNetData(d)); buffer.writeBoolean(defaultHideDependencyLines); + buffer.writeInt(defaultMinWidth); } @Override @@ -160,6 +166,7 @@ public void readNetData(FriendlyByteBuf buffer) { return image; }); defaultHideDependencyLines = buffer.readBoolean(); + defaultMinWidth = buffer.readInt(); } public int getIndex() { @@ -310,6 +317,7 @@ public void getConfig(ConfigGroup config) { config.addBool("always_invisible", alwaysInvisible, v -> alwaysInvisible = v, false); config.addEnum("default_quest_shape", defaultQuestShape.isEmpty() ? "default" : defaultQuestShape, v -> defaultQuestShape = v.equals("default") ? "" : v, QuestShape.idMapWithDefault); config.addBool("default_hide_dependency_lines", defaultHideDependencyLines, v -> defaultHideDependencyLines = v, false); + config.addInt("default_min_width", defaultMinWidth, v -> defaultMinWidth = v, 0, 0, 3000); } @Override diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/Quest.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/Quest.java index c69b1e1e9..dc3f61cca 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/Quest.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/Quest.java @@ -67,6 +67,8 @@ public final class Quest extends QuestObject implements Movable { public double size; public boolean optional; public int minWidth; + public boolean invisible; + public int invisibleUntilTasks; private Component cachedSubtitle = null; private Component[] cachedDescription = null; @@ -184,6 +186,14 @@ public void writeData(CompoundTag nbt) { if (minWidth > 0) { nbt.putInt("min_width", minWidth); } + + if (invisible) { + nbt.putBoolean("invisible", true); + } + + if (invisibleUntilTasks > 0) { + nbt.putInt("invisible_until_tasks", invisibleUntilTasks); + } } @Override @@ -238,6 +248,8 @@ public void readData(CompoundTag nbt) { size = nbt.contains("size") ? nbt.getDouble("size") : 1D; optional = nbt.getBoolean("optional"); minWidth = nbt.getInt("min_width"); + invisible = nbt.getBoolean("invisible"); + invisibleUntilTasks = nbt.getInt("invisible_until_tasks"); } @Override @@ -254,6 +266,8 @@ public void writeNetData(FriendlyByteBuf buffer) { //flags = Bits.setFlag(flags, 128, hideTextUntilComplete); flags = Bits.setFlag(flags, 256, optional); flags = Bits.setFlag(flags, 512, minWidth > 0); + flags = Bits.setFlag(flags, 1024, invisible); + flags = Bits.setFlag(flags, 2048, invisibleUntilTasks > 0); buffer.writeVarInt(flags); hide.write(buffer); @@ -295,6 +309,10 @@ public void writeNetData(FriendlyByteBuf buffer) { if (minWidth > 0) { buffer.writeVarInt(minWidth); } + + if (invisibleUntilTasks > 0) { + buffer.writeVarInt(invisibleUntilTasks); + } } @Override @@ -338,6 +356,8 @@ public void readNetData(FriendlyByteBuf buffer) { size = Bits.getFlag(flags, 4) ? buffer.readDouble() : 1D; minWidth = Bits.getFlag(flags, 512) ? buffer.readVarInt() : 0; + invisible = Bits.getFlag(flags, 1024); + invisibleUntilTasks = Bits.getFlag(flags, 2048) ? buffer.readVarInt() : 0; } @Override @@ -504,6 +524,8 @@ public void onClicked(MouseButton button, ConfigCallback callback) { config.addEnum("disable_jei", disableJEI, v -> disableJEI = v, Tristate.NAME_MAP); config.addBool("optional", optional, v -> optional = v, false); config.addInt("min_width", minWidth, v -> minWidth = v, 0, 0, 3000); + config.addBool("invisible", invisible, v -> invisible = v, false); + config.addInt("invisible_until_tasks", invisibleUntilTasks, v -> invisibleUntilTasks = v, 0, 0, Integer.MAX_VALUE); } public boolean getHideDependencyLines() { @@ -548,6 +570,22 @@ public void move(Chapter to, double x, double y) { @Override public boolean isVisible(TeamData data) { + if (invisible && !data.isCompleted(this)) { + return false; + } + + if (invisibleUntilTasks > 0) { + int completedTasks = 0; + for (Task task : tasks) { + if (data.isCompleted(task)) { + completedTasks++; + } + } + if (invisibleUntilTasks > completedTasks) { + return false; + } + } + if (dependencies.isEmpty()) { return true; } diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/ServerQuestFile.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/ServerQuestFile.java index cdb4b13e7..579f2a283 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/ServerQuestFile.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/ServerQuestFile.java @@ -97,6 +97,12 @@ public void load() { } } }); + + // for inital load, when this is not on disk + if (TeamData.GLOBAL.file != this) { + TeamData.GLOBAL.file = this; + addData(TeamData.GLOBAL, true); + } } catch (Exception ex) { ex.printStackTrace(); } diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/TeamData.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/TeamData.java index 51cf52cbf..730132a4d 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/TeamData.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/TeamData.java @@ -53,6 +53,13 @@ */ public class TeamData { public static int VERSION = 1; + public static final TeamData GLOBAL = new TeamData(new UUID(0L, 0L)) { + @Override + public boolean isGlobal() { + return true; + } + }; + private static final byte BOOL_NONE = -1; private static final byte BOOL_FALSE = 0; private static final byte BOOL_TRUE = 1; @@ -105,13 +112,18 @@ public void save() { shouldSave = true; } + public boolean isGlobal() { + return false; + } + @Override public String toString() { return name.isEmpty() ? uuid.toString() : name; } public long getProgress(long task) { - return taskProgress.get(task); + long globalProgress = isGlobal() ? 0L : TeamData.GLOBAL.getProgress(task); + return globalProgress == 0L ? taskProgress.get(task) : globalProgress; } public long getProgress(Task task) { @@ -129,6 +141,10 @@ public boolean setStarted(long id, @Nullable Date time) { return false; } + if (!isGlobal()) { + TeamData.GLOBAL.setStarted(id, time); + } + if (time == null) { if (started.remove(id) >= 0L) { clearCachedProgress(); @@ -173,7 +189,7 @@ public boolean setCompleted(long id, @Nullable Date time) { save(); if (file.isServerSide()) { - new ObjectCompletedResetMessage(uuid, id).sendToAll(((ServerQuestFile) file).server); + new ObjectCompletedResetMessage(isGlobal() ? GLOBAL.uuid : uuid, id).sendToAll(((ServerQuestFile) file).server); } return true; @@ -184,7 +200,7 @@ public boolean setCompleted(long id, @Nullable Date time) { save(); if (file.isServerSide()) { - new ObjectCompletedMessage(uuid, id).sendToAll(((ServerQuestFile) file).server); + new ObjectCompletedMessage(isGlobal() ? GLOBAL.uuid : uuid, id).sendToAll(((ServerQuestFile) file).server); } return true; @@ -533,10 +549,16 @@ public int getRelativeProgress(QuestObject object) { } public boolean isStarted(QuestObject object) { + if (!isGlobal() && object instanceof Task && ((Task) object).global) { + return TeamData.GLOBAL.isStarted(object); + } return started.containsKey(object.id); } public boolean isCompleted(QuestObject object) { + if (!isGlobal() && object instanceof Task && ((Task) object).global) { + return TeamData.GLOBAL.isCompleted(object); + } return completed.containsKey(object.id); } @@ -664,6 +686,10 @@ public final void setProgress(Task task, long progress) { return; } + if (task.global && !isGlobal()) { + TeamData.GLOBAL.setProgress(task, progress); + } + long maxProgress = task.getMaxProgress(); progress = Math.max(0L, Math.min(progress, maxProgress)); long prevProgress = getProgress(task); diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RepeatReward.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RepeatReward.java new file mode 100644 index 000000000..c159ad13c --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RepeatReward.java @@ -0,0 +1,118 @@ +package dev.ftb.mods.ftbquests.quest.reward; + +import dev.ftb.mods.ftblibrary.config.ConfigGroup; +import dev.ftb.mods.ftbquests.quest.Quest; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.server.level.ServerPlayer; +import dev.ftb.mods.ftbquests.quest.ServerQuestFile; +import dev.ftb.mods.ftbquests.quest.TeamData; +import dev.ftb.mods.ftbquests.quest.task.Task; +import dev.ftb.mods.ftbquests.util.ProgressChange; +import dev.ftb.mods.ftbteams.FTBTeamsAPI; + +/** + * @author MasterOfBob777 + */ +public class RepeatReward extends Reward { + public int maxRepeats; + + + public RepeatReward(Quest quest) { + super(quest); + autoclaim = RewardAutoClaim.INVISIBLE; + } + + @Override + public RewardType getType() { + return RewardTypes.REPEAT; + } + + @Override + public void writeData(CompoundTag nbt) { + super.writeData(nbt); + nbt.putInt("maxRepeats", maxRepeats); + } + + @Override + public void readData(CompoundTag nbt) { + super.readData(nbt); + maxRepeats = nbt.getInt("maxRepeats"); + } + + @Override + public void writeNetData(FriendlyByteBuf buffer) { + super.writeNetData(buffer); + buffer.writeInt(maxRepeats); + } + + @Override + public void readNetData(FriendlyByteBuf buffer) { + super.readNetData(buffer); + maxRepeats = buffer.readInt(); + } + + @Override + @Environment(EnvType.CLIENT) + public void getConfig(ConfigGroup config) { + super.getConfig(config); + config.addInt("maxRepeats", maxRepeats, v -> maxRepeats = v, 0, 0, Integer.MAX_VALUE); + } + + @Override + public void forceProgress(TeamData teamData, ProgressChange progressChange) { + super.forceProgress(teamData, progressChange); + if (progressChange.reset && progressChange.origin != this) { + teamData.getOnlineMembers().forEach(player -> { + CompoundTag extra = FTBTeamsAPI.getPlayerTeam(player).getExtraData(); + String timesCompletedKey = "ftbquests:repeat/times_completed?" + quest.id; + extra.putInt(timesCompletedKey, 0); + }); + } + } + + @Override + public void claim(ServerPlayer player, boolean notify) { + ProgressChange progressChange = new ProgressChange(ServerQuestFile.INSTANCE); + progressChange.origin = this; + progressChange.reset = true; + progressChange.player = player.getUUID(); + + CompoundTag extra = FTBTeamsAPI.getPlayerTeam(player).getExtraData(); + String timesCompletedKey = "ftbquests:repeat/times_completed?" + quest.id; + int timesCompleted = extra.getInt(timesCompletedKey); + + // String lastCompletedKey = "ftbquests:repeat/last_completed?" + quest.id; + // long lastCompleted = extra.getLong(lastCompletedKey); + + if (maxRepeats != 0 && timesCompleted < maxRepeats - 1) { + extra.putInt(timesCompletedKey, timesCompleted + 1); + + TeamData teamData = ServerQuestFile.INSTANCE.getData(player); + + for (Reward reward : quest.rewards) { + reward.forceProgress(teamData, progressChange); + } + + for (Task task : quest.tasks) { + task.forceProgress(teamData, progressChange); + } + + } + + if (notify) { + player.sendMessage(new TranslatableComponent("ftbquests.reward.ftbquests.repeat"), Util.NIL_UUID); + } + } + + @Override + @Environment(EnvType.CLIENT) + public MutableComponent getAltTitle() { + return new TranslatableComponent("ftbquests.reward.ftbquests.repeat"); + } +} diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/Reward.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/Reward.java index 32bb619eb..8604030fa 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/Reward.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/Reward.java @@ -39,11 +39,13 @@ public abstract class Reward extends QuestObjectBase { public Tristate team; public RewardAutoClaim autoclaim; + public boolean optional; public Reward(Quest q) { quest = q; team = Tristate.DEFAULT; autoclaim = RewardAutoClaim.DEFAULT; + optional = getType().getExcludeFromListRewards(); } @Override @@ -80,6 +82,8 @@ public void writeData(CompoundTag nbt) { if (autoclaim != RewardAutoClaim.DEFAULT) { nbt.putString("auto", autoclaim.id); } + + if (optional) nbt.putBoolean("optional", optional); } @Override @@ -87,6 +91,7 @@ public void readData(CompoundTag nbt) { super.readData(nbt); team = Tristate.read(nbt, "team_reward"); autoclaim = RewardAutoClaim.NAME_MAP.get(nbt.getString("auto")); + optional = nbt.getBoolean("optional"); } @Override @@ -94,6 +99,7 @@ public void writeNetData(FriendlyByteBuf buffer) { super.writeNetData(buffer); Tristate.NAME_MAP.write(buffer, team); RewardAutoClaim.NAME_MAP.write(buffer, autoclaim); + buffer.writeBoolean(optional); } @Override @@ -101,6 +107,7 @@ public void readNetData(FriendlyByteBuf buffer) { super.readNetData(buffer); team = Tristate.NAME_MAP.read(buffer); autoclaim = RewardAutoClaim.NAME_MAP.read(buffer); + optional = buffer.readBoolean(); } @Override @@ -109,6 +116,7 @@ public void getConfig(ConfigGroup config) { super.getConfig(config); config.addEnum("team", team, v -> team = v, Tristate.NAME_MAP).setNameKey("ftbquests.reward.team_reward"); config.addEnum("autoclaim", autoclaim, v -> autoclaim = v, RewardAutoClaim.NAME_MAP).setNameKey("ftbquests.reward.autoclaim"); + config.addBool("optional", optional, v -> optional = v, optional).setNameKey("ftbquests.reward.optional"); } public abstract void claim(ServerPlayer player, boolean notify); @@ -194,7 +202,7 @@ public final RewardAutoClaim getAutoClaimType() { } @Override - public final void forceProgress(TeamData teamData, ProgressChange progressChange) { + public void forceProgress(TeamData teamData, ProgressChange progressChange) { if (progressChange.reset) { teamData.resetReward(progressChange.player, this); } else { @@ -238,7 +246,7 @@ public void onButtonClicked(Button button, boolean canClick) { } public boolean getExcludeFromClaimAll() { - return getType().getExcludeFromListRewards(); + return optional; } @Nullable diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardType.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardType.java index 0850c2d24..872323e46 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardType.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardType.java @@ -56,7 +56,7 @@ public interface GuiProvider { private final Supplier icon; private Component displayName; private GuiProvider guiProvider; - private boolean excludeFromListRewards; + private boolean excludeFromListRewards = false; public int intId; public RewardType(ResourceLocation i, Provider p, Supplier ic) { diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardTypes.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardTypes.java index 7b543143c..5fb866650 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardTypes.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/reward/RewardTypes.java @@ -30,6 +30,7 @@ static RewardType register(ResourceLocation name, RewardType.Provider p, Supplie RewardType ADVANCEMENT = register(new ResourceLocation(FTBQuests.MOD_ID, "advancement"), AdvancementReward::new, () -> Icon.getIcon("minecraft:item/wheat")); RewardType TOAST = register(new ResourceLocation(FTBQuests.MOD_ID, "toast"), ToastReward::new, () -> Icon.getIcon("minecraft:item/oak_sign")); RewardType STAGE = RewardTypes.register(new ResourceLocation(FTBQuests.MOD_ID, "gamestage"), StageReward::new, () -> Icons.CONTROLLER); + RewardType REPEAT = RewardTypes.register(new ResourceLocation(FTBQuests.MOD_ID, "repeat"), RepeatReward::new, () -> Icons.COLOR_HSB); static void init() { } diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ItemTask.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ItemTask.java index e41d1bcbb..1e0e95f11 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ItemTask.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ItemTask.java @@ -240,9 +240,14 @@ public ItemStack insert(TeamData teamData, ItemStack stack, boolean simulate) { return stack; } + @Override + public boolean canExclusive() { + return true; + } + @Override public void submitTask(TeamData teamData, ServerPlayer player, ItemStack craftedItem) { - if (teamData.isCompleted(this) || item.getItem() instanceof MissingItem || craftedItem.getItem() instanceof MissingItem) { + if ((exclusive ? false : teamData.isCompleted(this)) || item.getItem() instanceof MissingItem || craftedItem.getItem() instanceof MissingItem) { return; } @@ -265,9 +270,13 @@ public void submitTask(TeamData teamData, ServerPlayer player, ItemStack crafted c = Math.min(count, c); - if (c > teamData.getProgress(this)) { + long progress = teamData.getProgress(this); + + if (c > progress) { teamData.setProgress(this, c); return; + } else if (exclusive && progress != c) { + teamData.setProgress(this, 0L); } return; diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ScoreboardTask.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ScoreboardTask.java new file mode 100644 index 000000000..bb9982bc9 --- /dev/null +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/ScoreboardTask.java @@ -0,0 +1,107 @@ +package dev.ftb.mods.ftbquests.quest.task; + +import java.util.Collection; +import dev.ftb.mods.ftblibrary.config.ConfigGroup; +import dev.ftb.mods.ftbquests.quest.Quest; +import dev.ftb.mods.ftbquests.quest.ServerQuestFile; +import dev.ftb.mods.ftbquests.quest.TeamData; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.ServerScoreboard; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.scores.Objective; +import net.minecraft.world.scores.Score; + +/** + * @author MasterOfBob777 + */ +public class ScoreboardTask extends Task { + public String name; + public int value; + private String objective; + + public ScoreboardTask(Quest quest) { + super(quest); + } + + @Override + public long getMaxProgress() { + return 1L; + } + + @Override + public TaskType getType() { + return TaskTypes.SCOREBOARD; + } + + @Override + public void getConfig(ConfigGroup config) { + super.getConfig(config); + config.addString("objective", objective, v -> objective = v, ""); + config.addInt("value", value, v -> value = v, 0, 0, Integer.MAX_VALUE); + } + + @Override + public void writeData(CompoundTag nbt) { + super.writeData(nbt); + nbt.putString("objective", objective); + nbt.putInt("value", value); + } + + @Override + public void readData(CompoundTag nbt) { + super.readData(nbt); + objective = nbt.getString("objective"); + value = nbt.getInt("value"); + } + + @Override + public void writeNetData(FriendlyByteBuf buffer) { + super.writeNetData(buffer); + buffer.writeUtf(objective); + buffer.writeInt(value); + } + + @Override + public void readNetData(FriendlyByteBuf buffer) { + super.readNetData(buffer); + objective = buffer.readUtf(); + value = buffer.readInt(); + } + + @Override + public boolean canExclusive() { + return true; + } + + private int lastVal = -1; + + public void test(ServerQuestFile file, ServerScoreboard scoreboard) { + Objective obj = scoreboard.getObjective(objective); + Collection scores = scoreboard.getPlayerScores(obj); + + for (Score score : scores) { + ServerPlayer player = file.server.getPlayerList().getPlayerByName(score.getOwner()); + if (player == null) { + continue; + } + TeamData data = file.getData(player); + if (data.isLocked()) { + return; + } + + if (exclusive ? false : data.isCompleted(this)) { + continue; + } + + int val = score.getScore(); + + if (val >= value) { + data.addProgress(this, 1L); + lastVal = val; + } else if (exclusive && val != lastVal){ + data.setProgress(this, 0L); + } + } + } +} diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/Task.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/Task.java index a91ead725..59e0f6894 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/Task.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/Task.java @@ -26,6 +26,8 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.TextComponent; @@ -40,6 +42,9 @@ public abstract class Task extends QuestObject { public final Quest quest; + public boolean exclusive = false; + public boolean global = false; + public Task(Quest q) { quest = q; } @@ -88,6 +93,7 @@ public final int getRelativeProgressFromChildren(TeamData data) { @Override public void onStarted(QuestProgressEventData data) { data.teamData.setStarted(id, data.time); + ObjectStartedEvent.TASK.invoker().act(new ObjectStartedEvent.TaskEvent(data.withObject(this))); quest.onStarted(data.withObject(quest)); } @@ -95,6 +101,7 @@ public void onStarted(QuestProgressEventData data) { @Override public final void onCompleted(QuestProgressEventData data) { data.teamData.setCompleted(id, data.time); + ObjectCompletedEvent.TASK.invoker().act(new ObjectCompletedEvent.TaskEvent(data.withObject(this))); boolean questCompleted = quest.isCompletedRaw(data.teamData); @@ -108,6 +115,47 @@ public final void onCompleted(QuestProgressEventData data) { } } + @Override + public void writeData(CompoundTag nbt) { + super.writeData(nbt); + + if (exclusive) { nbt.putBoolean("exclusive", exclusive); } + if (global) { nbt.putBoolean("global", global); } + } + + @Override + public void readData(CompoundTag nbt) { + super.readData(nbt); + exclusive = nbt.getBoolean("exclusive"); + global = nbt.getBoolean("global"); + } + + @Override + public void writeNetData(FriendlyByteBuf buffer) { + super.writeNetData(buffer); + buffer.writeBoolean(exclusive); + buffer.writeBoolean(global); + } + + @Override + public void readNetData(FriendlyByteBuf buffer) { + super.readNetData(buffer); + exclusive = buffer.readBoolean(); + global = buffer.readBoolean(); + } + + public boolean canExclusive() { + return false; + }; + + @Override + @Environment(EnvType.CLIENT) + public void getConfig(ConfigGroup config) { + super.getConfig(config); + if (canExclusive()) config.addBool("exclusive", exclusive, v -> exclusive = v, false).setNameKey("ftbquests.task.exclusive"); + config.addBool("global", global, v -> global = v, false).setNameKey("ftbquests.task.global"); + } + public long getMaxProgress() { return 1L; } diff --git a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/TaskTypes.java b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/TaskTypes.java index 298986c0f..955bccaa6 100644 --- a/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/TaskTypes.java +++ b/common/src/main/java/dev/ftb/mods/ftbquests/quest/task/TaskTypes.java @@ -31,6 +31,7 @@ static TaskType register(ResourceLocation name, TaskType.Provider p, Supplier Icons.ART); TaskType BIOME = register(new ResourceLocation(FTBQuests.MOD_ID, "biome"), BiomeTask::new, () -> Icon.getIcon("minecraft:block/oak_sapling")); TaskType STAGE = TaskTypes.register(new ResourceLocation(FTBQuests.MOD_ID, "gamestage"), StageTask::new, () -> Icons.CONTROLLER); + TaskType SCOREBOARD = register(new ResourceLocation(FTBQuests.MOD_ID, "scoreboard"), ScoreboardTask::new, () -> Icon.getIcon("minecraft:item/painting")); static void init() { } diff --git a/common/src/main/resources/assets/ftbquests/lang/en_us.json b/common/src/main/resources/assets/ftbquests/lang/en_us.json index 7a91782e8..dfed3dea2 100644 --- a/common/src/main/resources/assets/ftbquests/lang/en_us.json +++ b/common/src/main/resources/assets/ftbquests/lang/en_us.json @@ -119,6 +119,7 @@ "ftbquests.chapter.image.click": "Click", "ftbquests.chapter.image.dev": "Only visible in Editing Mode", "ftbquests.chapter.image.corner": "Rotate and offset from corner", + "ftbquests.chapter.default_min_width": "Default Min Opened Quest Window Width", "ftbquests.quest": "Quest", "ftbquests.quests": "Quests", "ftbquests.quest.completed": "Quest completed!", @@ -156,6 +157,8 @@ "ftbquests.quest.disable_jei": "Disable JEI Recipe", "ftbquests.quest.optional": "Optional", "ftbquests.quest.min_width": "Min Opened Quest Window Width", + "ftbquests.quest.invisible": "Invisible", + "ftbquests.quest.invisible_until_tasks": "Invisible until X tasks are completed", "ftbquests.chapter_group": "Chapter Group", "ftbquests.chapter_groups": "Chapter Groups", "ftbquests.gui.edit_file": "Edit File", @@ -164,6 +167,7 @@ "ftbquests.gui.saved_as_file": "Saved as %s", "ftbquests.gui.error": "Error!", "ftbquests.gui.add_reward_all": "Add reward to all", + "ftbquests.gui.clear_reward_all": "Clear rewards from all", "ftbquests.gui.select_quest_object": "Select Quest Object", "ftbquests.gui.select_task_type": "Select Task Type", "ftbquests.gui.select_reward_type": "Select Reward Type", @@ -210,6 +214,7 @@ "ftbquests.task.auto_detected": "Items will be auto-detected", "ftbquests.task.click_to_submit_all": "Click to submit all items", "ftbquests.task.max_input": "Max Input", + "ftbquests.task.exclusive": "Exclusive", "ftbquests.task.ftbquests.item": "Item", "ftbquests.task.ftbquests.item.count": "Count", "ftbquests.task.ftbquests.item.consume_items": "Consume Items", @@ -287,6 +292,7 @@ "ftbquests.task.ftbquests.npc_faction.id": "Faction ID", "ftbquests.task.ftbquests.npc_faction.required_points": "Required Points", "ftbquests.task.ftbquests.npc_faction.mode": "Point mode", + "ftbquests.task.ftbquests.scoreboard": "Scoreboard", "ftbquests.reward": "Reward", "ftbquests.rewards": "Rewards", "ftbquests.reward.team_reward": "Team Reward", @@ -300,6 +306,7 @@ "ftbquests.reward.claim_all": "Claim All Rewards", "ftbquests.reward.collected": "Reward Collected!", "ftbquests.reward.random_bonus": "Random Bonus", + "ftbquests.reward.optional": "Optional", "ftbquests.reward.ftbquests.item": "Item", "ftbquests.reward.ftbquests.item.count": "Count", "ftbquests.reward.ftbquests.item.only_one": "Only One", @@ -336,6 +343,7 @@ "ftbquests.reward.ftbquests.npc_mail.quest_title": "CustomNPCs Quest Title", "ftbquests.reward.ftbquests.npc_mail.items": "Items", "ftbquests.reward.ftbquests.npc_mail.time_past": "Time Past", + "ftbquests.reward.ftbquests.repeat": "Repeat", "ftbquests.reward_table": "Reward Table", "ftbquests.reward_table.hide_tooltip": "Hide Tooltip", "ftbquests.reward_table.use_title": "Use Title",