diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..33c6e62 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Change Log + +### [1.18.2-1.0.0](https://github.com/KatatsumuriPan/BetterQuestPopup/releases/tag/1.18.2-1.0.0) - 2024-01-22 + +- First release. diff --git a/build.gradle b/build.gradle index 187fa46..4adbfea 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,9 @@ repositories { // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // See https://docs.gradle.org/current/userguide/declaring_repositories.html // for more information about repositories. + maven { + url 'https://cursemaven.com' + } } dependencies { @@ -31,6 +34,17 @@ dependencies { // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" + + modImplementation("curse.maven:ftb-quests-fabric-438496:4760360") + modImplementation("curse.maven:item-filters-309674:4553321") + modImplementation("curse.maven:ftb-library-fabric-438495:4396791") + modImplementation("curse.maven:ftb-teams-fabric-438497:4579980") + modImplementation("curse.maven:architectury-api-419699:4521464") + include modApi("teamreborn:energy:2.3.0") { + exclude(group: "net.fabricmc.fabric-api") + exclude(module: "fabric-loader") + } + } processResources { diff --git a/gradle.properties b/gradle.properties index 99ce1a1..af24a2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ loader_version=0.15.6 # Mod Properties mod_version=1.0.0 maven_group=kpan.bq_popup -archives_base_name=better_quest_popup +archives_base_name=BetterQuestPopup-1.18.2(Fabric) # Dependencies fabric_version=0.77.0+1.18.2 \ No newline at end of file diff --git a/src/main/java/kpan/bq_popup/BetterQuestPopup.java b/src/main/java/kpan/bq_popup/BetterQuestPopup.java deleted file mode 100644 index 126bc5a..0000000 --- a/src/main/java/kpan/bq_popup/BetterQuestPopup.java +++ /dev/null @@ -1,22 +0,0 @@ -package kpan.bq_popup; - -import net.fabricmc.api.ModInitializer; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BetterQuestPopup implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - public static final Logger LOGGER = LoggerFactory.getLogger("better_quest_popup"); - - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - LOGGER.info("Hello Fabric world!"); - } -} \ No newline at end of file diff --git a/src/main/java/kpan/bq_popup/ModMain.java b/src/main/java/kpan/bq_popup/ModMain.java new file mode 100644 index 0000000..8b940dc --- /dev/null +++ b/src/main/java/kpan/bq_popup/ModMain.java @@ -0,0 +1,16 @@ +package kpan.bq_popup; + +import kpan.bq_popup.client.SoundHandler; +import net.fabricmc.api.ModInitializer; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ModMain implements ModInitializer { + public static final String MOD_ID = "better_quest_popup"; + public static final Logger LOGGER = LogManager.getLogger(MOD_ID); + + @Override + public void onInitialize() { + SoundHandler.init(); + } +} \ No newline at end of file diff --git a/src/main/java/kpan/bq_popup/ModMainClient.java b/src/main/java/kpan/bq_popup/ModMainClient.java new file mode 100644 index 0000000..0ca3940 --- /dev/null +++ b/src/main/java/kpan/bq_popup/ModMainClient.java @@ -0,0 +1,17 @@ +package kpan.bq_popup; + +import kpan.bq_popup.client.QuestCompletePopup; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; + +public class ModMainClient implements ClientModInitializer { + + @Override + public void onInitializeClient() { + HudRenderCallback.EVENT.register((matrixStack, tickDelta) -> { + QuestCompletePopup.render(matrixStack); + }); + ClientTickEvents.END_CLIENT_TICK.register(QuestCompletePopup::ticking); + } +} \ No newline at end of file diff --git a/src/main/java/kpan/bq_popup/client/DisplayedPopup.java b/src/main/java/kpan/bq_popup/client/DisplayedPopup.java new file mode 100644 index 0000000..1f84adf --- /dev/null +++ b/src/main/java/kpan/bq_popup/client/DisplayedPopup.java @@ -0,0 +1,139 @@ +package kpan.bq_popup.client; + +import dev.ftb.mods.ftbquests.client.ClientQuestFile; +import dev.ftb.mods.ftbquests.gui.ToastQuestObject; +import dev.ftb.mods.ftbquests.quest.Chapter; +import dev.ftb.mods.ftbquests.quest.ChapterGroup; +import dev.ftb.mods.ftbquests.quest.Quest; +import dev.ftb.mods.ftbquests.quest.QuestObject; +import dev.ftb.mods.ftbquests.quest.TeamData; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; +import kpan.bq_popup.ModMain; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ServerInfo; +import org.apache.commons.lang3.StringUtils; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; + +public class DisplayedPopup { + public static LongSet popupDisplayed = new LongOpenHashSet(); + private static final File cacheDir = new File(new File(MinecraftClient.getInstance().runDirectory, ModMain.MOD_ID), "completed-cache"); + + public static void add(QuestObject object) { + popupDisplayed.add(object.id); + writeToFile(); + } + public static void remove(QuestObject object) { + popupDisplayed.remove(object.id); + writeToFile(); + } + + public static void display(QuestObject object) { + if (popupDisplayed.contains(object.id)) { + if (object instanceof Quest) + MinecraftClient.getInstance().getToastManager().add(new ToastQuestObject(object)); + } else { + QuestCompletePopup.add(object); + add(object); + } + } + + public static void onLoad() { + ClientQuestFile questFile = ClientQuestFile.INSTANCE; + readFromFile(); + if (!popupDisplayed.isEmpty()) { + TeamData teamData = questFile.self; + for (ChapterGroup chapterGroup : questFile.chapterGroups) { + for (Chapter chapter : chapterGroup.chapters) { + for (Quest quest : chapter.quests) { + if (teamData.isCompleted(quest) && !popupDisplayed.contains(quest.id)) + QuestCompletePopup.add(quest); + } + if (teamData.isCompleted(chapter) && !popupDisplayed.contains(chapter.id)) + QuestCompletePopup.add(chapter); + } + } + if (teamData.isCompleted(questFile) && !popupDisplayed.contains(questFile.id)) + QuestCompletePopup.add(questFile); + } + sync(questFile); + } + + public static void sync(ClientQuestFile questFile) { + popupDisplayed.clear(); + TeamData teamData = questFile.self; + for (ChapterGroup chapterGroup : questFile.chapterGroups) { + for (Chapter chapter : chapterGroup.chapters) { + for (Quest quest : chapter.quests) { + if (teamData.isCompleted(quest)) + popupDisplayed.add(quest.id); + } + if (teamData.isCompleted(chapter)) + popupDisplayed.add(chapter.id); + } + } + if (teamData.isCompleted(questFile)) + popupDisplayed.add(questFile.id); + writeToFile(); + } + + private static void readFromFile() { + popupDisplayed.clear(); + ServerInfo currentServerEntry = MinecraftClient.getInstance().getCurrentServerEntry(); + if (currentServerEntry == null) + return; + try { + if (!cacheDir.exists()) + return; + for (String line : Files.readAllLines(new File(cacheDir, sanitizeFileName(currentServerEntry.address)).toPath(), StandardCharsets.UTF_8)) { + if (line.isEmpty()) + continue; + popupDisplayed.add(Long.parseLong(line)); + } + } catch (IOException | NumberFormatException e) { + ModMain.LOGGER.error("Error while reading the cache.", e); + } + } + private static void writeToFile() { + ServerInfo currentServerEntry = MinecraftClient.getInstance().getCurrentServerEntry(); + if (currentServerEntry != null) { + File file = new File(cacheDir, sanitizeFileName(currentServerEntry.address)); + try { + if (file.getParentFile() != null) + file.getParentFile().mkdirs(); + + if (!file.exists() && !file.createNewFile()) { + ModMain.LOGGER.error("Cannot create a cache"); + return; + } + + if (file.canWrite()) { + FileOutputStream fos = new FileOutputStream(file); + BufferedWriter buffer = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8)); + + for (Long id : popupDisplayed) { + buffer.write(id + "\n"); + } + + buffer.close(); + fos.close(); + } else { + ModMain.LOGGER.error("Cannot write the cache file"); + } + } catch (IOException e) { + ModMain.LOGGER.error("Error while saving the cache.", e); + } + } + } + + private static String sanitizeFileName(String name) { + return StringUtils.replaceAll(name, "[/\\:*?\"<>|]", "-"); + } +} diff --git a/src/main/java/kpan/bq_popup/client/OtherTeamToast.java b/src/main/java/kpan/bq_popup/client/OtherTeamToast.java new file mode 100644 index 0000000..cde39bd --- /dev/null +++ b/src/main/java/kpan/bq_popup/client/OtherTeamToast.java @@ -0,0 +1,62 @@ +package kpan.bq_popup.client; + + +import com.mojang.blaze3d.systems.RenderSystem; +import dev.ftb.mods.ftblibrary.ui.GuiHelper; +import dev.ftb.mods.ftbquests.gui.ToastQuestObject; +import dev.ftb.mods.ftbquests.quest.QuestObject; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.DiffuseLighting; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.toast.ToastManager; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.OrderedText; +import net.minecraft.util.math.MathHelper; + +import java.util.List; +import java.util.Objects; + +public class OtherTeamToast extends ToastQuestObject { + private final QuestObject object; + private final String team; + public OtherTeamToast(QuestObject questObject, String team) { + super(questObject); + object = questObject; + this.team = team; + } + + @Override + public Visibility draw(MatrixStack matrixStack, ToastManager gui, long delta) { + GuiHelper.setupDrawing(); + MinecraftClient mc = gui.getClient(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderTexture(0, TEXTURE); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + gui.drawTexture(matrixStack, 0, 0, 0, 0, 160, 32); + List list = mc.textRenderer.wrapLines(getSubtitle(), 125); + int color = isImportant() ? 0xff88ff : 0xffff00; + int y = 16 - Math.min(list.size() + 1, 3) * mc.textRenderer.fontHeight / 2; + { + if (delta < 1500L) { + int alpha = MathHelper.floor(MathHelper.clamp((float) (1500L - delta) / 300.0F, 0.0F, 1.0F) * 255.0F) << 24 | 0x400_0000; + mc.textRenderer.drawWithShadow(matrixStack, team, 30.0F, y, color | alpha); + y += mc.textRenderer.fontHeight; + mc.textRenderer.drawWithShadow(matrixStack, getTitle(), 30.0F, y, color | alpha); + } else { + int alpha = MathHelper.floor(MathHelper.clamp((float) (delta - 1500L) / 300.0F, 0.0F, 1.0F) * 252.0F) << 24 | 0x400_0000; + Objects.requireNonNull(mc.textRenderer); + for (OrderedText s : list) { + mc.textRenderer.drawWithShadow(matrixStack, s, 30.0F, (float) y, 0xff_ffff | alpha); + Objects.requireNonNull(mc.textRenderer); + y += mc.textRenderer.fontHeight; + } + } + } + + GuiHelper.setupDrawing(); + DiffuseLighting.enableGuiDepthLighting(); + getIcon().draw(matrixStack, 8, 8, 16, 16); + return delta >= 5000L ? Visibility.HIDE : Visibility.SHOW; + } + +} diff --git a/src/main/java/kpan/bq_popup/client/QuestCompletePopup.java b/src/main/java/kpan/bq_popup/client/QuestCompletePopup.java new file mode 100644 index 0000000..da83c2c --- /dev/null +++ b/src/main/java/kpan/bq_popup/client/QuestCompletePopup.java @@ -0,0 +1,98 @@ +package kpan.bq_popup.client; + +import com.mojang.blaze3d.systems.RenderSystem; +import dev.ftb.mods.ftbquests.client.ClientQuestFile; +import dev.ftb.mods.ftbquests.quest.Chapter; +import dev.ftb.mods.ftbquests.quest.QuestObject; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.text.TranslatableText; +import net.minecraft.util.Formatting; + +import java.util.ArrayDeque; +import java.util.Queue; + +public class QuestCompletePopup { + private static final PositionedSoundInstance QUEST_COMPLETE = PositionedSoundInstance.master(SoundHandler.QUEST_COMPLETE, 1); + private static final PositionedSoundInstance CHAPTER_COMPLETE = PositionedSoundInstance.master(SoundHandler.CHAPTER_COMPLETE, 1); + private static final PositionedSoundInstance ALL_CHAPTERS_COMPLETE = PositionedSoundInstance.master(SoundHandler.ALL_CHAPTERS_COMPLETE, 1); + private final QuestObject object; + private int tick = 0; + private QuestCompletePopup(QuestObject object) { this.object = object; } + + private boolean tick() { + if (tick >= 100) + return true; + MinecraftClient mc = MinecraftClient.getInstance(); + if (tick == 0) { + if (object instanceof Chapter) + mc.getSoundManager().play(CHAPTER_COMPLETE); + else if (object instanceof ClientQuestFile) + mc.getSoundManager().play(ALL_CHAPTERS_COMPLETE); + else + mc.getSoundManager().play(QUEST_COMPLETE); + } + tick++; + return false; + } + private void render1(MatrixStack matrixStack) { + MinecraftClient mc = MinecraftClient.getInstance(); + var res = mc.getWindow(); + int w = res.getScaledWidth(); + int h = res.getScaledHeight(); + int y = h / 3; + float alphaf; + if (tick < 20) + alphaf = tick / 20f; + else if (tick < 60) + alphaf = 1; + else + alphaf = 1 - (tick - 60) / 40f; + int alpha = Math.max((int) (alphaf * 255), 16); + RenderSystem.enableBlend(); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha); + object.getIcon().draw(matrixStack, w / 2 - 8, y, 16, 16); + y += 16 + 2; + + Text text = new TranslatableText(object.getObjectType().translationKey + ".completed").formatted(Formatting.BOLD, Formatting.UNDERLINE); + int color; + if (object instanceof Chapter) + color = 0xFF88FF; + else if (object instanceof ClientQuestFile) + color = 0x88FF88; + else + color = 0xFFFF00; + mc.textRenderer.drawWithShadow(matrixStack, text, w / 2f - mc.textRenderer.getWidth(text) / 2f, y, color | (alpha << 24)); + y += mc.textRenderer.fontHeight + 2; + text = object.getTitle(); + mc.textRenderer.drawWithShadow(matrixStack, text, w / 2f - mc.textRenderer.getWidth(text) / 2f, y, 0xFFFFFF | (alpha << 24)); + } + + private static final Queue TITLES = new ArrayDeque<>(); + public static void add(QuestObject object) { + TITLES.add(new QuestCompletePopup(object)); + } + public static void render(MatrixStack matrixStack) { + if (TITLES.isEmpty()) + return; + MinecraftClient mc = MinecraftClient.getInstance(); + if (mc.currentScreen != null && !(mc.currentScreen instanceof ChatScreen)) + return; + QuestCompletePopup title = TITLES.peek(); + title.render1(matrixStack); + } + public static void ticking(MinecraftClient mc) { + if (mc.world == null) + TITLES.clear(); + if (TITLES.isEmpty()) + return; + if (mc.currentScreen != null && !(mc.currentScreen instanceof ChatScreen)) + return; + QuestCompletePopup title = TITLES.peek(); + if (title.tick()) + TITLES.remove(); + } +} diff --git a/src/main/java/kpan/bq_popup/client/SoundHandler.java b/src/main/java/kpan/bq_popup/client/SoundHandler.java new file mode 100644 index 0000000..a5cf9c8 --- /dev/null +++ b/src/main/java/kpan/bq_popup/client/SoundHandler.java @@ -0,0 +1,26 @@ +package kpan.bq_popup.client; + + +import kpan.bq_popup.ModMain; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class SoundHandler { + public static final Identifier QUEST_COMPLETE_ID = new Identifier(ModMain.MOD_ID, "quest_complete"); + public static final Identifier CHAPTER_COMPLETE_ID = new Identifier(ModMain.MOD_ID, "chapter_complete"); + public static final Identifier ALL_CHAPTERS_COMPLETE_ID = new Identifier(ModMain.MOD_ID, "all_chapters_complete"); + public static final SoundEvent QUEST_COMPLETE = createSoundEvent(QUEST_COMPLETE_ID); + public static final SoundEvent CHAPTER_COMPLETE = createSoundEvent(CHAPTER_COMPLETE_ID); + public static final SoundEvent ALL_CHAPTERS_COMPLETE = createSoundEvent(ALL_CHAPTERS_COMPLETE_ID); + + public static void init() { + Registry.register(Registry.SOUND_EVENT, QUEST_COMPLETE_ID, QUEST_COMPLETE); + Registry.register(Registry.SOUND_EVENT, CHAPTER_COMPLETE_ID, CHAPTER_COMPLETE); + Registry.register(Registry.SOUND_EVENT, ALL_CHAPTERS_COMPLETE_ID, ALL_CHAPTERS_COMPLETE); + } + + private static SoundEvent createSoundEvent(Identifier soundId) { + return new SoundEvent(soundId); + } +} diff --git a/src/main/java/kpan/bq_popup/mixin/ExampleMixin.java b/src/main/java/kpan/bq_popup/mixin/ExampleMixin.java deleted file mode 100644 index 05b6a8f..0000000 --- a/src/main/java/kpan/bq_popup/mixin/ExampleMixin.java +++ /dev/null @@ -1,15 +0,0 @@ -package kpan.bq_popup.mixin; - -import net.minecraft.server.MinecraftServer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(MinecraftServer.class) -public class ExampleMixin { - @Inject(at = @At("HEAD"), method = "loadWorld") - private void init(CallbackInfo info) { - // This code is injected into the start of MinecraftServer.loadWorld()V - } -} \ No newline at end of file diff --git a/src/main/java/kpan/bq_popup/mixin/FTBQuestsNetClientMixin.java b/src/main/java/kpan/bq_popup/mixin/FTBQuestsNetClientMixin.java new file mode 100644 index 0000000..e22592d --- /dev/null +++ b/src/main/java/kpan/bq_popup/mixin/FTBQuestsNetClientMixin.java @@ -0,0 +1,43 @@ +package kpan.bq_popup.mixin; + +import dev.ftb.mods.ftbquests.client.ClientQuestFile; +import dev.ftb.mods.ftbquests.client.FTBQuestsNetClient; +import dev.ftb.mods.ftbquests.gui.ToastQuestObject; +import dev.ftb.mods.ftbquests.quest.QuestObject; +import dev.ftb.mods.ftbquests.quest.TeamData; +import dev.ftb.mods.ftbquests.quest.task.Task; +import kpan.bq_popup.client.DisplayedPopup; +import kpan.bq_popup.client.QuestCompletePopup; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(FTBQuestsNetClient.class) +public class FTBQuestsNetClientMixin { + /** + * @author + * @reason + */ + @Overwrite(remap = false) + public void displayCompletionToast(long id) { + QuestObject object = ClientQuestFile.INSTANCE.get(id); + if (object != null) { + if (object instanceof Task) + MinecraftClient.getInstance().getToastManager().add(new ToastQuestObject(object)); + else + QuestCompletePopup.add(object); + } + + ClientQuestFile.INSTANCE.questScreen.questPanel.refreshWidgets(); + ClientQuestFile.INSTANCE.questScreen.chapterPanel.refreshWidgets(); + ClientQuestFile.INSTANCE.questScreen.viewQuestPanel.refreshWidgets(); + } + + @Inject(at = @At("RETURN"), method = "syncTeamData", remap = false) + public void syncTeamData(boolean self, TeamData data, CallbackInfo ci) { + DisplayedPopup.onLoad(); + } +} \ No newline at end of file diff --git a/src/main/java/kpan/bq_popup/mixin/TeamDataMixin.java b/src/main/java/kpan/bq_popup/mixin/TeamDataMixin.java new file mode 100644 index 0000000..657da93 --- /dev/null +++ b/src/main/java/kpan/bq_popup/mixin/TeamDataMixin.java @@ -0,0 +1,84 @@ +package kpan.bq_popup.mixin; + +import dev.ftb.mods.ftbquests.client.ClientQuestFile; +import dev.ftb.mods.ftbquests.quest.Chapter; +import dev.ftb.mods.ftbquests.quest.Quest; +import dev.ftb.mods.ftbquests.quest.QuestFile; +import dev.ftb.mods.ftbquests.quest.QuestObject; +import dev.ftb.mods.ftbquests.quest.TeamData; +import dev.ftb.mods.ftbquests.quest.task.Task; +import kpan.bq_popup.client.DisplayedPopup; +import kpan.bq_popup.client.OtherTeamToast; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Date; + +@Mixin(TeamData.class) +public class TeamDataMixin { + @Inject(at = @At("RETURN"), method = "setCompleted", remap = false) + public void setCompleted(long id, Date time, CallbackInfoReturnable cir) { + if (!cir.getReturnValueZ()) + return; + TeamData teamData = (TeamData) (Object) this; + if (teamData.file.isServerSide()) + return; + boolean isSelf = ClientQuestFile.INSTANCE != null && teamData == ClientQuestFile.INSTANCE.self; + QuestObject object = teamData.file.get(id); + String teamName = teamData.name; + if (!teamData.isCompleted(object)) { + if (isSelf) { + DisplayedPopup.remove(object); + } + return; + } + if (object instanceof Task task) { + boolean displayPopup = !task.quest.chapter.alwaysInvisible;//QuestObjectBase.sendNotifications.get(true)はサーバー限定なので取得不可 + boolean displayTaskToast = task.quest.tasks.size() > 1 && !teamData.isCompleted(task.quest) && !task.disableToast; + if (displayTaskToast && displayPopup) { + if (!isSelf) + MinecraftClient.getInstance().getToastManager().add(new OtherTeamToast(task, teamName)); + } + } else if (object instanceof Quest quest) { + boolean displayPopup = !quest.chapter.alwaysInvisible; + boolean displayQuestToast = !quest.disableToast; + if (displayQuestToast && displayPopup) { + if (isSelf) + DisplayedPopup.add(quest); + else + MinecraftClient.getInstance().getToastManager().add(new OtherTeamToast(quest, teamName)); + } else { + if (isSelf) + DisplayedPopup.add(quest); + } + } else if (object instanceof Chapter chapter) { + boolean displayPopup = !chapter.alwaysInvisible; + boolean displayChapterToast = !chapter.disableToast; + if (displayChapterToast && displayPopup) { + if (isSelf) + DisplayedPopup.add(chapter); + else + MinecraftClient.getInstance().getToastManager().add(new OtherTeamToast(chapter, teamName)); + } else { + if (isSelf) + DisplayedPopup.add(chapter); + } + } else if (object instanceof QuestFile file) { + boolean displayPopup = true;//chapter.alwaysInvisibleの参照はちょっと無理そう + boolean displayFileToast = !file.disableToast; + if (displayFileToast && displayPopup) { + if (isSelf) + DisplayedPopup.add(file); + else + MinecraftClient.getInstance().getToastManager().add(new OtherTeamToast(file, teamName)); + } else { + if (isSelf) + DisplayedPopup.add(file); + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/better_quest_popup/icon.png b/src/main/resources/assets/better_quest_popup/icon.png index 047b91f..732a954 100644 Binary files a/src/main/resources/assets/better_quest_popup/icon.png and b/src/main/resources/assets/better_quest_popup/icon.png differ diff --git a/src/main/resources/assets/better_quest_popup/sounds.json b/src/main/resources/assets/better_quest_popup/sounds.json new file mode 100644 index 0000000..fe2c801 --- /dev/null +++ b/src/main/resources/assets/better_quest_popup/sounds.json @@ -0,0 +1,17 @@ +{ + "quest_complete": { + "sounds": [ + "better_quest_popup:quest_complete" + ] + }, + "chapter_complete": { + "sounds": [ + "better_quest_popup:chapter_complete" + ] + }, + "all_chapters_complete": { + "sounds": [ + "better_quest_popup:all_chapters_complete" + ] + } +} \ No newline at end of file diff --git a/src/main/resources/assets/better_quest_popup/sounds/all_chapters_complete.ogg b/src/main/resources/assets/better_quest_popup/sounds/all_chapters_complete.ogg new file mode 100644 index 0000000..0fcc0de Binary files /dev/null and b/src/main/resources/assets/better_quest_popup/sounds/all_chapters_complete.ogg differ diff --git a/src/main/resources/assets/better_quest_popup/sounds/chapter_complete.ogg b/src/main/resources/assets/better_quest_popup/sounds/chapter_complete.ogg new file mode 100644 index 0000000..2a929ff Binary files /dev/null and b/src/main/resources/assets/better_quest_popup/sounds/chapter_complete.ogg differ diff --git a/src/main/resources/assets/better_quest_popup/sounds/quest_complete.ogg b/src/main/resources/assets/better_quest_popup/sounds/quest_complete.ogg new file mode 100644 index 0000000..a3f4c0b Binary files /dev/null and b/src/main/resources/assets/better_quest_popup/sounds/quest_complete.ogg differ diff --git a/src/main/resources/better_quest_popup.mixins.json b/src/main/resources/better_quest_popup.mixins.json index a618de3..60e34a4 100644 --- a/src/main/resources/better_quest_popup.mixins.json +++ b/src/main/resources/better_quest_popup.mixins.json @@ -3,9 +3,12 @@ "package": "kpan.bq_popup.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ - "ExampleMixin" ], "injectors": { "defaultRequire": 1 - } + }, + "client": [ + "FTBQuestsNetClientMixin", + "TeamDataMixin" + ] } \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2d9b0e2..2a8bc21 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -3,20 +3,22 @@ "id": "better_quest_popup", "version": "${version}", "name": "Better Quest Pop-up", - "description": "This is an example description! Tell everyone what your mod is about!", + "description": "\"Better\" quest pop-up for FTB Quests!", "authors": [ - "Me!" + "Katatsumuri.pan" ], "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" + "sources": "https://github.com/KatatsumuriPan/BetterQuestPopup" }, - "license": "CC0-1.0", + "license": "LGPL-2.1", "icon": "assets/better_quest_popup/icon.png", "environment": "*", "entrypoints": { "main": [ - "kpan.bq_popup.BetterQuestPopup" + "kpan.bq_popup.ModMain" + ], + "client": [ + "kpan.bq_popup.ModMainClient" ] }, "mixins": [