HTTPS
https://git.nageyqma.icu/nageyqma/blade-addons-next.git
SSH
git@git.nageyqma.icu:nageyqma/blade-addons-next.git
HTTPS 链接可直接 git clone;推送代码请使用 SSH。
仅展示默认分支 next 最近 100 条提交。
add description查看变更README.md | 4 ++++ 1 file changed, 4 insertions(+) @@ -1,3 +1,7 @@ +# Blade Addons - next + +This is a fork of [Blade Addons](https://github.com/BladeMasterGabe/blade-addons), with support of latest minecraft version. + # Blade Addons A dungeons mod made to port dungeons features to the newer Minecraft versions. Huge thanks to Ohful for letting me port |
| Migrate to Minecraft 26.3 (Fabric API 0.161.0+26.3, ModMenu 21.0.0, loader 0.19.5) - Bump minecraft_version 26.2 -> 26.3, mod_version 2.6.0 -> 2.7.0,
loom 1.17-SNAPSHOT -> 1.18.2, fabric-loader 0.19.3 -> 0.19.5,
fabric-api 0.161.0+26.2 -> 0.161.0+26.3, modmenu 20.0.2 -> 21.0.0
- 26.3 replaced the Blaze3D GPU abstraction with the RenderPearl API:
com.mojang.blaze3d.pipeline.* -> com.mojang.renderpearl.api.pipeline.*
(RenderPipeline/BlendFunction/ColorTargetState/DepthStencilState/PrimitiveTopology/
CompareOp) and VertexFormat -> com.mojang.renderpearl.api.vertex.VertexFormat.
BindGroupLayouts.MATRICES_PROJECTION split into PROJECTION + DYNAMIC_TRANSFORMS;
the custom FILLED/LINE snippets were rebuilt to match vanilla's 26.3
DEBUG_FILLED_SNIPPET/LINES_SNIPPET composition. PoseStack#mulPose -> rotate and
VertexConsumer#setUv3 is now abstract (implemented in RenderHandler's recorder).
- GLFW was removed in 26.3 (SDL is used instead): mod and practical-config now use
com.mojang.blaze3d.platform.InputConstants (SDL scancodes/keymod) for keybinds,
the search bar and chat click handling.
- Mixin/method retargets for 26.3:
* vanilla renames: EnderMan -> Enderman
* ClientboundLevelParticlesPacket is now a record (getX() -> x(), getParticle() ->
particle(), getXDist() -> xDist(), ...)
* InterpolationHandler#position() -> #target().position()
* EntityRenderDispatcher#shouldRender gained a partial-tick float
* ItemInHandRenderer was split into net.minecraft.client.player.FirstPersonHandsAndItems
(held-item state) + net.minecraft.client.renderer.FirstPersonHandsAndItemsRenderer
(arm transforms): HeldItemRendererMixin was split to match
* LocalPlayer#drop(boolean) moved to MultiPlayerGameMode#dropItem(LocalPlayer, boolean):
drop protection + DropAnimation hooking moved into MultiPlayerGameModeMixin
* LivingEntity#swing(InteractionHand, boolean) -> swing(InteractionHand,
net.minecraft.world.item.component.SwingAnimation, boolean)
* ShovelItem/AxeItem/HoeItem were removed; tool transforms are now data driven via the
BLOCK_TRANSFORMER component, so ShovelItemMixin was replaced by BlockTransformerMixin
(redirects the transform sound in BlockTransformer#transformBlock, still gated on
SHOVEL_FLATTEN so axe stripping keeps its swing)
* AbstractContainerScreen#slotClicked gained a MouseButtonEvent overload and
Minecraft#updateLevelInEngines stays overloaded: descriptors pinned so the injectors
stay unambiguous
* GuiGraphicsExtractor#tooltip gained a trailing boolean: callback declares it
- practical-config is a local patched build for 26.3 (GLFW -> InputConstants,
Minecraft#setScreen/screen -> Gui), served from the project-local maven repo
(libs-local) and versioned through the new practical_config_version property.
- Packets: no outbound packet format changes. The mod still only issues vanilla
ClientPacketListener#sendCommand plus the bundled (Minecraft-independent)
net.hypixel:mod-api protocol library; ConnectionMixin remains observation-only.
- Verified: ./gradlew clean build green; client boots on 26.3 with all 29 mixins applied
(0 failures), enters a world and renders (Vulkan) with no mod-side errors; config
screen opens and closes cleanly. 查看变更README.md | 2 +-
build.gradle | 2 +-
gradle.properties | 13 +++++++------
libs-local/maven/com/github/BladeMasterGabe/practical-config/26.3-patched/practical-config-26.3-patched.jar | Bin 0 -> 108521 bytes
libs-local/maven/com/github/BladeMasterGabe/practical-config/26.3-patched/practical-config-26.3-patched.pom | 8 ++++++++
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonSpawn.java | 19 ++++++++++---------
src/main/java/blade/addon/features/highlight/MobHighlight.java | 4 ++--
src/main/java/blade/addon/features/other/SearchBar.java | 10 +++++-----
src/main/java/blade/addon/mixin/AbstractContainerScreenMixin.java | 6 ++++--
src/main/java/blade/addon/mixin/BlockTransformerMixin.java | 39 +++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/mixin/ChatScreenMixin.java | 4 ++--
src/main/java/blade/addon/mixin/EntityRenderDispatcherMixin.java | 6 ++++--
src/main/java/blade/addon/mixin/{HeldItemRendererMixin.java => FirstPersonHandsAndItemsMixin.java} | 36 ++++++++++--------------------------
src/main/java/blade/addon/mixin/FirstPersonHandsAndItemsRendererMixin.java | 37 +++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/mixin/GuiGraphicsExtractorMixin.java | 4 +++-
src/main/java/blade/addon/mixin/LivingEntityMixin.java | 8 +++++---
src/main/java/blade/addon/mixin/LocalPlayerMixin.java | 36 ------------------------------------
src/main/java/blade/addon/mixin/MinecraftMixin.java | 3 ++-
src/main/java/blade/addon/mixin/MultiPlayerGameModeMixin.java | 25 +++++++++++++++++++++++++
src/main/java/blade/addon/mixin/ShovelItemMixin.java | 23 -----------------------
src/main/java/blade/addon/utils/Keybinds.java | 25 ++++++++++++-------------
src/main/java/blade/addon/utils/rendering/RenderHandler.java | 7 +++++++
src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 21 ++++++++++++---------
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 2 +-
src/main/resources/blade-addons.mixins.json | 6 +++---
src/main/resources/fabric.mod.json | 4 ++--
26 files changed, 202 insertions(+), 148 deletions(-)@@ -4,7 +4,7 @@ A dungeons mod made to port dungeons features to the newer Minecraft versions. H his amazing mods like Valley addons. # Current Version -26.2 +26.3 # Dependencies - Hypixel Mod API https://modrinth.com/mod/hypixel-mod-api @@ -48,7 +48,7 @@ dependencies { implementation "net.fabricmc:fabric-loader:${project.loader_version}" implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" include implementation("net.hypixel:mod-api:${project.hypixel_api_version}") - include implementation("com.github.BladeMasterGabe:practical-config:26.2-patched") + include implementation("com.github.BladeMasterGabe:practical-config:${project.practical_config_version}") runtimeOnly("me.djtheredstoner:DevAuth-fabric:${project.dev_auth_version}") compileOnly("com.terraformersmc:modmenu:${project.modmenu_version}") @@ -5,17 +5,18 @@ org.gradle.parallel=true org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=26.2 -loader_version=0.19.3 -loom_version=1.17-SNAPSHOT +minecraft_version=26.3 +loader_version=0.19.5 +loom_version=1.18.2 # Mod Properties -mod_version=2.6.0 +mod_version=2.7.0 maven_group=blade.addon archives_base_name=blade-addons # Dependencies -fabric_api_version=0.161.0+26.2 +fabric_api_version=0.161.0+26.3 # I love dependencies sometimes breaking practical_config=757ad46ab1b257d494cc150261736b6f9b0e131c -modmenu_version=20.0.2 +practical_config_version=26.3-patched +modmenu_version=21.0.0 hypixel_api_version=1.0.2 dev_auth_version=1.2.2 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.github.BladeMasterGabe</groupId> + <artifactId>practical-config</artifactId> + <version>26.3-patched</version> + <packaging>jar</packaging> +</project> @@ -35,7 +35,7 @@ public class DragonSpawn { public static void init() { Events.ON_PARTICLE.register(packet -> { if (!validParticle(packet)) return false; - Dragon dragon = Dragon.getDragon(packet.getX(), packet.getY(), packet.getZ()); + Dragon dragon = Dragon.getDragon(packet.x(), packet.y(), packet.z()); testDragon(dragon); return false; }); @@ -75,14 +75,15 @@ public class DragonSpawn { } private static boolean validParticle(ClientboundLevelParticlesPacket packet) { - if (packet.getCount() != 20) return false; - if (packet.getY() != 19) return false; - if (packet.getParticle().getType() != ParticleTypes.FLAME) return false; - if (packet.getXDist() != 2) return false; - if (packet.getYDist() != 3) return false; - if (packet.getZDist() != 2) return false; - if (packet.getX() % 1 != 0) return false; - if (packet.getZ() % 1 != 0) return false; + // 26.3 turned ClientboundLevelParticlesPacket into a record: getters are now record accessors. + if (packet.count() != 20) return false; + if (packet.y() != 19) return false; + if (packet.particle().getType() != ParticleTypes.FLAME) return false; + if (packet.xDist() != 2) return false; + if (packet.yDist() != 3) return false; + if (packet.zDist() != 2) return false; + if (packet.x() % 1 != 0) return false; + if (packet.z() % 1 != 0) return false; return true; } @@ -17,7 +17,7 @@ import net.minecraft.network.chat.TextColor; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Enderman; import net.minecraft.world.entity.monster.zombie.Zombie; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; @@ -287,7 +287,7 @@ public class MobHighlight { AABB box = EntityUtil.getBox(entity); //only shows the head - if (entity instanceof EnderMan && entity.isInvisible() && MobHighlight.dontShowInvisibleMobs) { + if (entity instanceof Enderman && entity.isInvisible() && MobHighlight.dontShowInvisibleMobs) { box = box.inflate(0, -1.8, 0).move(0, -1.2, 0); } @@ -5,6 +5,7 @@ import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.data.ItemUtil; import blade.addon.utils.rendering.DrawEvents; import blade.addon.utils.rendering.RenderUtils; +import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.platform.Window; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; @@ -15,7 +16,6 @@ import net.minecraft.client.input.KeyEvent; import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; -import org.lwjgl.glfw.GLFW; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -79,17 +79,17 @@ public class SearchBar { public static boolean keyPressed(KeyEvent input) { if (!exists() || !ExtraOptions.toggleableSearchBar) return false; - boolean ctrlIsPressed = (input.modifiers() & GLFW.GLFW_MOD_CONTROL) != 0; + boolean ctrlIsPressed = (input.modifiers() & InputConstants.MOD_CONTROL) != 0; - if (ctrlIsPressed && input.key() == GLFW.GLFW_KEY_F) { + if (ctrlIsPressed && input.key() == InputConstants.KEY_F) { shouldDisplay = !shouldDisplay; return true; } else if (shouldDisplay() && searchBar.isFocused()) { - if (input.key() == GLFW.GLFW_KEY_ENTER) { + if (input.key() == InputConstants.KEY_RETURN) { if (!Double.isNaN(parsedValue)) { searchBar.setValue(RenderUtils.formatNumber((float) parsedValue)); } - } else if (input.key() != GLFW.GLFW_KEY_ESCAPE) { + } else if (input.key() != InputConstants.KEY_ESCAPE) { searchBar.keyPressed(input); return true; } @@ -68,7 +68,9 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe SearchBar.onMouseClick(click); } - @Inject(method = "slotClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;onMouseClickAction(Lnet/minecraft/world/inventory/Slot;Lnet/minecraft/world/inventory/ContainerInput;)V"), cancellable = true) + // 26.3 added a private slotClicked(Slot, int, MouseButtonEvent, ContainerInput) overload, so the + // descriptor of the vanilla protected entry point has to be spelled out to stay unambiguous. + @Inject(method = "slotClicked(Lnet/minecraft/world/inventory/Slot;IILnet/minecraft/world/inventory/ContainerInput;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;onMouseClickAction(Lnet/minecraft/world/inventory/Slot;Lnet/minecraft/world/inventory/ContainerInput;)V"), cancellable = true) public void protectItem(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) { ItemStack held = menu.getCarried(); @@ -93,7 +95,7 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe } } - @Inject(method = "slotClicked", at = @At("HEAD"), cancellable = true) + @Inject(method = "slotClicked(Lnet/minecraft/world/inventory/Slot;IILnet/minecraft/world/inventory/ContainerInput;)V", at = @At("HEAD"), cancellable = true) public void slotClicked(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) { if (Events.ON_SLOT_CLICKED.invoke(slotEvent -> slotEvent.onSlot(slot, slotId, buttonNum, containerInput, this))) { ci.cancel(); @@ -0,0 +1,39 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SwingAnimation; +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.data.EntityUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.BlockTransformer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +/** + * 26.3 removed the dedicated tool item classes (ShovelItem / AxeItem / HoeItem). Their + * right-click behaviour is now data driven through the BLOCK_TRANSFORMER item component, + * applied from Item#useOn via net.minecraft.core.component.BlockTransformer#transformBlock, + * which is also where the transform sound is played. This replaces the old ShovelItemMixin, + * which hooked ShovelItem#useOn at the Level#playSound call. + */ +@Mixin(BlockTransformer.class) +public class BlockTransformerMixin { + + @Redirect(method = "transformBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) + private void bladeAddons$onTransformSound(Level level, Entity entity, BlockPos pos, SoundEvent sound, SoundSource source, float volume, float pitch) { + // Only the shovel flatten sound, so that e.g. axe stripping keeps its normal swing. + if (Visual.stopShovelFlattening + && sound != null + && sound.location().equals(SoundEvents.SHOVEL_FLATTEN.value().location()) + && EntityUtil.isClientPlayer(entity)) { + SwingAnimation.ignoreNext(2); + } + + level.playSound(entity, pos, sound, source, volume, pitch); + } +} \ No newline at end of file @@ -3,7 +3,7 @@ package blade.addon.mixin; import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.data.TextUtil; -import org.lwjgl.glfw.GLFW; +import com.mojang.blaze3d.platform.InputConstants; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -25,7 +25,7 @@ public class ChatScreenMixin { @Inject(method = "mouseClicked", at = @At("HEAD")) private void click(MouseButtonEvent click, boolean doubled, CallbackInfoReturnable<Boolean> cir) { - if (!ExtraOptions.copyChat || click.button() != GLFW.GLFW_MOUSE_BUTTON_RIGHT) return; + if (!ExtraOptions.copyChat || click.button() != InputConstants.MOUSE_BUTTON_RIGHT) return; Minecraft mc = Minecraft.getInstance(); ChatComponent chatHud = mc.gui.hud.getChat(); @@ -25,8 +25,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EntityRenderDispatcher.class) public class EntityRenderDispatcherMixin { + // 26.3 added a partial-tick float parameter to shouldRender. @Inject(method = "shouldRender", at = @At("TAIL"), cancellable = true) - private <E extends Entity> void shouldRender(E entity, Frustum frustum, double x, double y, double z, CallbackInfoReturnable<Boolean> cir) { + private <E extends Entity> void shouldRender(E entity, Frustum frustum, double x, double y, double z, float partialTick, CallbackInfoReturnable<Boolean> cir) { if (entity instanceof Player player) { LocalPlayer clientPlayer = Minecraft.getInstance().player; if (clientPlayer != null) { @@ -59,7 +60,8 @@ public class EntityRenderDispatcherMixin { //Pretty much just hides the bobber if it's too close //its def not exact, but it's good enough for now - Vec3 pos = bobber.getInterpolation().position(); + // 26.3 moved the interpolated position from InterpolationHandler#position() to #target().position(). + Vec3 pos = bobber.getInterpolation().target().position(); if (clientPlayer.position().distanceTo(pos) < 2 && bobber.tickCount < 6 && pos.y > clientPlayer.getY() + 1.2 && clientPlayer.getXRot() > -60) { cir.setReturnValue(false); } @@ -1,13 +1,9 @@ package blade.addon.mixin; import blade.addon.features.item.DropAnimation; -import blade.addon.features.other.SwingAnimation; import com.llamalad7.mixinextras.sugar.Local; -import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.player.FirstPersonHandsAndItems; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.ItemInHandRenderer; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.spongepowered.asm.mixin.Mixin; @@ -16,8 +12,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(ItemInHandRenderer.class) -public abstract class HeldItemRendererMixin { +/** + * 26.3 split the old net.minecraft.client.renderer.ItemInHandRenderer: the held item state + * (mainHandItem / mainHandHeight and the per-tick update) now lives in + * net.minecraft.client.player.FirstPersonHandsAndItems, while the actual rendering moved to + * net.minecraft.client.renderer.FirstPersonHandsAndItemsRenderer. + */ +@Mixin(FirstPersonHandsAndItems.class) +public abstract class FirstPersonHandsAndItemsMixin { @Shadow private ItemStack mainHandItem; @@ -53,22 +55,4 @@ public abstract class HeldItemRendererMixin { mainHandItem = stack; this.mainHandHeight = 1; } - - @Inject(method = "applyItemArmTransform", at = @At("HEAD"), cancellable = true) - private void applyEquipOffset(PoseStack matrices, HumanoidArm arm, float swingProgress, CallbackInfo ci) { - if (!SwingAnimation.shouldIgnore()) return; - int side = arm == HumanoidArm.RIGHT ? 1 : -1; - matrices.translate((float) side * 0.56F, -0.52F, -0.72F); - ci.cancel(); - } - - @Inject(method = "swingArm", at = @At("HEAD"), cancellable = true) - private void swingArm(float swingProgress, PoseStack matrixStack, int i, HumanoidArm arm, CallbackInfo ci) { - if (!SwingAnimation.shouldIgnore()) return; - float f = -0.4F * Mth.sin(Mth.sqrt(1) * (float) Math.PI); - float g = 0.2F * Mth.sin(Mth.sqrt(1) * (float) (Math.PI * 2)); - float h = -0.2F * Mth.sin(1 * (float) Math.PI); - matrixStack.translate(i * f, g, h); - ci.cancel(); - } -} +} \ No newline at end of file @@ -0,0 +1,37 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SwingAnimation; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.FirstPersonHandsAndItemsRenderer; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.HumanoidArm; +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; + +/** + * 26.3 split the old net.minecraft.client.renderer.ItemInHandRenderer: the arm/item transforms + * now live in net.minecraft.client.renderer.FirstPersonHandsAndItemsRenderer. + */ +@Mixin(FirstPersonHandsAndItemsRenderer.class) +public class FirstPersonHandsAndItemsRendererMixin { + + @Inject(method = "applyItemArmTransform", at = @At("HEAD"), cancellable = true) + private void applyEquipOffset(PoseStack matrices, HumanoidArm arm, float swingProgress, CallbackInfo ci) { + if (!SwingAnimation.shouldIgnore()) return; + int side = arm == HumanoidArm.RIGHT ? 1 : -1; + matrices.translate((float) side * 0.56F, -0.52F, -0.72F); + ci.cancel(); + } + + @Inject(method = "swingArm", at = @At("HEAD"), cancellable = true) + private void swingArm(float swingProgress, PoseStack matrixStack, int i, HumanoidArm arm, CallbackInfo ci) { + if (!SwingAnimation.shouldIgnore()) return; + float f = -0.4F * Mth.sin(Mth.sqrt(1) * (float) Math.PI); + float g = 0.2F * Mth.sin(Mth.sqrt(1) * (float) (Math.PI * 2)); + float h = -0.2F * Mth.sin(1 * (float) Math.PI); + matrixStack.translate(i * f, g, h); + ci.cancel(); + } +} \ No newline at end of file @@ -69,9 +69,11 @@ public abstract class GuiGraphicsExtractorMixin { return 0; } + // 26.3 appended a trailing boolean to GuiGraphicsExtractor#tooltip, so the callback has to + // declare it (Mixin requires either all of the target arguments or none of them). @Inject(method = "tooltip", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;pushMatrix()Lorg/joml/Matrix3x2fStack;")) private void scaleUpTooltip_head(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, - @Nullable Identifier style, CallbackInfo ci, @Local(name = "h") int h) { + @Nullable Identifier style, boolean bl, CallbackInfo ci, @Local(name = "h") int h) { if (Visual.tooltipSize == 1) return; float newX = xo + 6; float newY = yo - ((float) h / 2) * Visual.tooltipSize + 4; @@ -8,14 +8,16 @@ import net.minecraft.world.entity.LivingEntity; 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; @Mixin(LivingEntity.class) public class LivingEntityMixin { - @Inject(method = "swing(Lnet/minecraft/world/InteractionHand;Z)V", at = @At("TAIL")) - public void swingHand(InteractionHand hand, boolean fromServerPlayer, CallbackInfo ci) { + // 26.3 replaced swing(InteractionHand, boolean) with + // swing(InteractionHand, net.minecraft.world.item.component.SwingAnimation, boolean). + @Inject(method = "swing(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/item/component/SwingAnimation;Z)Z", at = @At("TAIL")) + public void swingHand(InteractionHand hand, net.minecraft.world.item.component.SwingAnimation animation, boolean fromServerPlayer, CallbackInfoReturnable<Boolean> cir) { if (EntityUtil.isClientPlayer((Entity) (Object) this)) { SwingAnimation.consumeSwing(); } @@ -1,36 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.features.item.DropAnimation; -import blade.addon.features.item.ProtectItem; -import blade.addon.utils.config.values.Dungeons; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.world.item.ItemStack; -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.CallbackInfoReturnable; - -@Mixin(LocalPlayer.class) -public class LocalPlayerMixin { - - @Inject(method = "drop(Z)Z", at = @At("HEAD"), cancellable = true) - public void protectItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) { - if (Dungeons.dontProtectHeldItem && ProtectItem.isInADungeon()) return; - - LocalPlayer self = (LocalPlayer) (Object) this; - - if (ProtectItem.protect(self.getInventory().getSelectedItem())) { - cir.setReturnValue(false); - } - } - - @Inject(method = "drop(Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V")) - public void getDropped(boolean entireStack, CallbackInfoReturnable<Boolean> cir, @Local ItemStack itemStack) { - if (!DropAnimation.shouldProceed()) return; - - LocalPlayer self = (LocalPlayer) (Object) this; - int slot = self.getInventory().getSelectedSlot(); - DropAnimation.setDroppedData(itemStack, slot); - } -} @@ -38,7 +38,8 @@ public class MinecraftMixin { DropAnimation.clearData(); } - @Inject(method = "updateLevelInEngines", at = @At(value = "TAIL")) + // 26.3 keeps two updateLevelInEngines overloads, so spell out the descriptor. + @Inject(method = "updateLevelInEngines(Lnet/minecraft/client/multiplayer/ClientLevel;)V", at = @At(value = "TAIL")) private void onWorld(ClientLevel world, CallbackInfo ci) { Events.ON_WORLD_CHANGE.invoke(WorldEvent::onWorldSwap); } @@ -1,9 +1,15 @@ package blade.addon.mixin; +import blade.addon.features.item.DropAnimation; +import blade.addon.features.item.ProtectItem; import blade.addon.features.other.pet.SelectedPet; +import blade.addon.utils.config.values.Dungeons; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.ContainerInput; +import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,4 +23,23 @@ public class MultiPlayerGameModeMixin { SelectedPet.testLoadoutClick(container, slotId, button, containerInput, player); } + // 26.3 moved the drop handling from LocalPlayer#drop(boolean) to + // MultiPlayerGameMode#dropItem(LocalPlayer, boolean) (see LocalPlayerMixin for 26.2). + @Inject(method = "dropItem", at = @At("HEAD"), cancellable = true) + public void protectItem(LocalPlayer player, boolean entireStack, CallbackInfo ci) { + if (Dungeons.dontProtectHeldItem && ProtectItem.isInADungeon()) return; + + if (ProtectItem.protect(player.getInventory().getSelectedItem())) { + ci.cancel(); + } + } + + @Inject(method = "dropItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V")) + public void getDropped(LocalPlayer player, boolean entireStack, CallbackInfo ci, @Local ItemStack itemStack) { + if (!DropAnimation.shouldProceed()) return; + + int slot = player.getInventory().getSelectedSlot(); + DropAnimation.setDroppedData(itemStack, slot); + } + } @@ -1,23 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.features.other.SwingAnimation; -import blade.addon.utils.config.values.Visual; -import blade.addon.utils.data.EntityUtil; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.item.ShovelItem; -import net.minecraft.world.item.context.UseOnContext; -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.CallbackInfoReturnable; - -@Mixin(ShovelItem.class) -public class ShovelItemMixin { - - @Inject(method = "useOn", at= @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;Lnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")) - public void useOnBlock(UseOnContext context, CallbackInfoReturnable<InteractionResult> cir) { - if (Visual.stopShovelFlattening && EntityUtil.isClientPlayer(context.getPlayer())) { - SwingAnimation.ignoreNext(2); - } - } -} @@ -23,7 +23,6 @@ import net.minecraft.world.level.block.entity.SkullBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; -import org.lwjgl.glfw.GLFW; import java.util.List; @@ -44,39 +43,39 @@ public class Keybinds { //normal keybinds openConfig = KeyMappingHelper.registerKeyMapping(new KeyMapping( "opens Config", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_RIGHT_SHIFT, + InputConstants.Type.KEYBOARD, + InputConstants.KEY_RSHIFT, category)); trades = KeyMappingHelper.registerKeyMapping(new KeyMapping( "Opens the trades menu", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_UNKNOWN, + InputConstants.Type.KEYBOARD, + InputConstants.UNKNOWN.getValue(), category)); potions = KeyMappingHelper.registerKeyMapping(new KeyMapping( "Opens the potion bag", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_UNKNOWN, + InputConstants.Type.KEYBOARD, + InputConstants.UNKNOWN.getValue(), category)); //debug keybinds getItemLore = KeyMappingHelper.registerKeyMapping(new KeyMapping( "Grabs the items lore", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_UNKNOWN, + InputConstants.Type.KEYBOARD, + InputConstants.UNKNOWN.getValue(), category)); getItemCustomData = KeyMappingHelper.registerKeyMapping(new KeyMapping( "Grabs the items custom data", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_UNKNOWN, + InputConstants.Type.KEYBOARD, + InputConstants.UNKNOWN.getValue(), category)); getBlockInfo = KeyMappingHelper.registerKeyMapping(new KeyMapping( "Grabs the blocks data", - InputConstants.Type.KEYSYM, - GLFW.GLFW_KEY_UNKNOWN, + InputConstants.Type.KEYBOARD, + InputConstants.UNKNOWN.getValue(), category)); ClientTickEvents.END_CLIENT_TICK.register(Keybinds::checkInputs); @@ -91,6 +91,13 @@ public class RenderHandler { return this; } + // New abstract method on VertexConsumer in 26.3 (third UV set for the renderpearl vertex formats). + @Override + public VertexConsumer setUv3(float u, float v) { + ops.add(consumer -> consumer.setUv3(u, v)); + return this; + } + @Override public VertexConsumer setNormal(float x, float y, float z) { ops.add(consumer -> consumer.setNormal(x, y, z)); @@ -1,26 +1,28 @@ package blade.addon.utils.rendering; import blade.addon.utils.Constants; -import com.mojang.blaze3d.PrimitiveTopology; -import com.mojang.blaze3d.pipeline.BlendFunction; -import com.mojang.blaze3d.pipeline.ColorTargetState; -import com.mojang.blaze3d.pipeline.DepthStencilState; -import com.mojang.blaze3d.pipeline.RenderPipeline; -import com.mojang.blaze3d.platform.CompareOp; import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.renderpearl.api.pipeline.BlendFunction; +import com.mojang.renderpearl.api.pipeline.ColorTargetState; +import com.mojang.renderpearl.api.pipeline.CompareOp; +import com.mojang.renderpearl.api.pipeline.DepthStencilState; +import com.mojang.renderpearl.api.pipeline.PrimitiveTopology; +import com.mojang.renderpearl.api.pipeline.RenderPipeline; import net.minecraft.client.renderer.BindGroupLayouts; import net.minecraft.resources.Identifier; public class RenderPipelines { - // Vanilla's DEBUG_FILLED_SNIPPET / LINES_SNIPPET are private in 26.2; rebuilt here with identical + // Vanilla's DEBUG_FILLED_SNIPPET / LINES_SNIPPET are private in 26.3; rebuilt here with identical // composition (see net.minecraft.client.renderer.RenderPipelines static initializer). + // 26.3 moved the whole pipeline API from com.mojang.blaze3d.pipeline to com.mojang.renderpearl.api.pipeline. private static final RenderPipeline.Snippet GLOBALS_SNIPPET = RenderPipeline.builder() .withBindGroupLayout(BindGroupLayouts.GLOBALS) .buildSnippet(); private static final RenderPipeline.Snippet DEBUG_FILLED_SNIPPET = RenderPipeline.builder(GLOBALS_SNIPPET) - .withBindGroupLayout(BindGroupLayouts.MATRICES_PROJECTION) + .withBindGroupLayout(BindGroupLayouts.PROJECTION) + .withBindGroupLayout(BindGroupLayouts.DYNAMIC_TRANSFORMS) .withVertexShader("core/position_color") .withFragmentShader("core/position_color") .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) @@ -31,7 +33,8 @@ public class RenderPipelines { .buildSnippet(); private static final RenderPipeline.Snippet LINES_SNIPPET = RenderPipeline.builder(GLOBALS_SNIPPET) - .withBindGroupLayout(BindGroupLayouts.MATRICES_PROJECTION) + .withBindGroupLayout(BindGroupLayouts.PROJECTION) + .withBindGroupLayout(BindGroupLayouts.DYNAMIC_TRANSFORMS) .withBindGroupLayout(BindGroupLayouts.FOG) .withVertexShader("core/rendertype_lines") .withFragmentShader("core/rendertype_lines") @@ -98,7 +98,7 @@ public class RenderUtils { matrices.pushPose(); matrices.translate(x, y, z); - matrices.mulPose(context.levelState().cameraRenderState.orientation); + matrices.rotate(context.levelState().cameraRenderState.orientation); matrices.scale(TEXT_SCALE * scale, -TEXT_SCALE * scale, TEXT_SCALE * scale); float halfWidth = textRenderer.width(text.getString()) / 2f; @@ -12,7 +12,7 @@ "ItemStackMixin", "LevelChunkMixin", "LivingEntityMixin", - "ShovelItemMixin" + "BlockTransformerMixin" ], "injectors": { "defaultRequire": 1 @@ -29,13 +29,13 @@ "EffectsInInventoryMixin", "EntityRenderDispatcherMixin", "EntityRendererMixin", + "FirstPersonHandsAndItemsMixin", + "FirstPersonHandsAndItemsRendererMixin", "GuiGraphicsExtractorMixin", "GuiMixin", - "HeldItemRendererMixin", "HudMixin", "InventoryScreenMixin", "KeyboardHandlerMixin", - "LocalPlayerMixin", "MinecraftMixin", "MouseHandlerMixin", "MultiPlayerGameModeMixin", @@ -26,8 +26,8 @@ "blade-addons.mixins.json" ], "depends": { - "fabricloader": ">=0.19.3", - "minecraft": "~26.2", + "fabricloader": ">=0.19.5", + "minecraft": "~26.3", "java": ">=25", "fabric-api": "*" }, |
| Migrate to Minecraft 26.2 (Fabric API 0.161.0+26.2, ModMenu 20.0.2) - Bump minecraft_version 26.1.2 -> 26.2, mod_version 2.5.3 -> 2.6.0
- Gui/Hud split: setScreen/screen/getChat/setTitle repathed via gui/gui.hud
- Replace removed net.minecraft.util.Tuple with datafixerupper Pair
- BlockPos.getCenter -> Vec3.atCenterOf; ChatFormatting accessors via TextColor
- Rebuild custom RenderPipelines on 26.2 Blaze3D API (withVertexBinding,
withPrimitiveTopology, BindGroupLayouts); explicit snippet rebuilds
- Replace removed MultiBufferSource/bufferSource with submitNodeCollector
submitCustomGeometry (recording consumer); drawInBatch -> submitText
- Register all render handlers on COLLECT_SUBMITS (collection closes before
AFTER_TRANSLUCENT_FEATURES in 26.2)
- Mixin retargets for 26.2: new HudMixin, GuiMixin setScreen, ArrowLayerMixin
AvatarRenderState, EnderPearlItemMixin InteractionResult, ChatScreenMixin
- practical-config: local patched build (minecraft ~26.2) served from
project-local maven repo (libs-local), nested via include
- Drop hypixel-mod-api from depends (bundled jar ships no mod metadata)
- Verified: ./gradlew build green; client boots and renders on OpenGL and
Vulkan (custom pipeline GLSL->SPIR-V compile clean) 查看变更README.md | 2 +- build.gradle | 7 ++-- gradle.properties | 8 ++--- .../maven/com/github/BladeMasterGabe/practical-config/26.2-patched/practical-config-26.2-patched.jar | Bin 0 -> 107039 bytes .../maven/com/github/BladeMasterGabe/practical-config/26.2-patched/practical-config-26.2-patched.pom | 8 +++++ src/main/java/blade/addon/features/filter/FilterEntry.java | 14 ++++---- src/main/java/blade/addon/features/filter/FilterList.java | 18 +++++----- src/main/java/blade/addon/features/notifications/NotificationEditScreen.java | 4 +-- src/main/java/blade/addon/features/notifications/NotificationEntry.java | 16 ++++----- src/main/java/blade/addon/features/notifications/NotificationList.java | 4 +-- src/main/java/blade/addon/features/other/PracticeSS.java | 3 +- src/main/java/blade/addon/mixin/ArrowLayerMixin.java | 3 +- src/main/java/blade/addon/mixin/ChatScreenMixin.java | 2 +- src/main/java/blade/addon/mixin/EnderPearlItemMixin.java | 3 +- src/main/java/blade/addon/mixin/GuiMixin.java | 91 ++++-------------------------------------------- src/main/java/blade/addon/mixin/HudMixin.java | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/MinecraftMixin.java | 6 ---- src/main/java/blade/addon/utils/Keybinds.java | 2 +- src/main/java/blade/addon/utils/Misc.java | 4 +-- src/main/java/blade/addon/utils/Scheduler.java | 2 +- src/main/java/blade/addon/utils/config/Config.java | 4 +-- src/main/java/blade/addon/utils/data/TextUtil.java | 8 ++--- src/main/java/blade/addon/utils/rendering/RenderHandler.java | 70 ++++++++++++++++++++++++++++++++++--- src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 70 +++++++++++++++++++++++++++++-------- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 2 +- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 12 ++++--- src/main/resources/blade-addons.mixins.json | 1 + src/main/resources/fabric.mod.json | 5 ++- 28 files changed, 296 insertions(+), 169 deletions(-) @@ -4,7 +4,7 @@ A dungeons mod made to port dungeons features to the newer Minecraft versions. H his amazing mods like Valley addons. # Current Version -26.1.2 +26.2 # Dependencies - Hypixel Mod API https://modrinth.com/mod/hypixel-mod-api @@ -23,9 +23,9 @@ loom { setIdeConfigGenerated(true) vmArgs("-XX:+IgnoreUnrecognizedVMOptions", "-Dmixin.debug.export=true", - "-Ddevauth.enabled=true", - "-Ddevauth.account=main", "-XX:+AllowEnhancedClassRedefinition") +// "-Ddevauth.enabled=true", +// "-Ddevauth.account=main") } runConfigs.named("server") { @@ -34,6 +34,7 @@ loom { } repositories { + maven { url = uri("libs-local/maven") } mavenCentral() maven { url = "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" } maven { url = 'https://jitpack.io' } @@ -47,7 +48,7 @@ dependencies { implementation "net.fabricmc:fabric-loader:${project.loader_version}" implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" include implementation("net.hypixel:mod-api:${project.hypixel_api_version}") - include implementation("com.github.BladeMasterGabe:practical-config:${project.practical_config}") + include implementation("com.github.BladeMasterGabe:practical-config:26.2-patched") runtimeOnly("me.djtheredstoner:DevAuth-fabric:${project.dev_auth_version}") compileOnly("com.terraformersmc:modmenu:${project.modmenu_version}") @@ -5,17 +5,17 @@ org.gradle.parallel=true org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=26.1.2 +minecraft_version=26.2 loader_version=0.19.3 loom_version=1.17-SNAPSHOT # Mod Properties -mod_version=2.5.3 +mod_version=2.6.0 maven_group=blade.addon archives_base_name=blade-addons # Dependencies -fabric_api_version=0.155.2+26.1.2 +fabric_api_version=0.161.0+26.2 # I love dependencies sometimes breaking practical_config=757ad46ab1b257d494cc150261736b6f9b0e131c -modmenu_version=18.0.0-beta.1 +modmenu_version=20.0.2 hypixel_api_version=1.0.2 dev_auth_version=1.2.2 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.github.BladeMasterGabe</groupId> + <artifactId>practical-config</artifactId> + <version>26.2-patched</version> + <packaging>jar</packaging> +</project> @@ -11,7 +11,7 @@ import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.util.Mth; -import net.minecraft.util.Tuple; +import com.mojang.datafixers.util.Pair; import java.util.function.Consumer; import java.util.function.Supplier; @@ -44,8 +44,8 @@ public class FilterEntry extends EditBox { @Override public void extractWidgetRenderState(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float deltaTicks) { DrawHelper.drawBackground(graphics, getX(), super.getY(), width - SPRITE_WIDTH_AREA, height, INPUT_COLOR); - Tuple<Integer, Integer> pos = getRemovePos(); - graphics.blitSprite(RenderPipelines.GUI_TEXTURED, CROSS, pos.getA(), pos.getB(), SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); + Pair<Integer, Integer> pos = getRemovePos(); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, CROSS, pos.getFirst(), pos.getSecond(), SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); super.extractWidgetRenderState(graphics, mouseX, mouseY, deltaTicks); } @@ -130,13 +130,13 @@ public class FilterEntry extends EditBox { return false; } - private Tuple<Integer, Integer> getRemovePos() { - return new Tuple<>(getX() + width - SPRITE_SIZE - 5, getY() + (height - SPRITE_SIZE) / 2); + private Pair<Integer, Integer> getRemovePos() { + return Pair.of(getX() + width - SPRITE_SIZE - 5, getY() + (height - SPRITE_SIZE) / 2); } private boolean inRemovalBounds(double x, double y) { - Tuple<Integer, Integer> pos = getRemovePos(); - return x >= pos.getA() && x <= pos.getA() + SPRITE_SIZE && y >= pos.getB() && y <= pos.getB() + SPRITE_SIZE; + Pair<Integer, Integer> pos = getRemovePos(); + return x >= pos.getFirst() && x <= pos.getFirst() + SPRITE_SIZE && y >= pos.getSecond() && y <= pos.getSecond() + SPRITE_SIZE; } @Override @@ -2,6 +2,7 @@ package blade.addon.features.filter; import blade.addon.features.notifications.Notifications; import com.mojang.blaze3d.platform.Window; +import com.mojang.datafixers.util.Pair; import config.practical.ConfigScroll; import config.practical.utilities.Constants; import net.minecraft.client.Minecraft; @@ -9,7 +10,6 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; -import net.minecraft.util.Tuple; import org.joml.Matrix3x2fStack; import org.jspecify.annotations.NonNull; @@ -33,11 +33,11 @@ public class FilterList extends Screen { super(Component.literal("Filter")); Minecraft client = Minecraft.getInstance(); - parent = client.screen; + parent = client.gui.screen(); Window window = client.getWindow(); - Tuple<Integer, Integer> pos = getButtonPos(); - addFilter = Button.builder(Component.literal("Add Filter"), this::addFilter).pos(pos.getA(), pos.getB()).width(BUTTON_WIDTH).build(); + Pair<Integer, Integer> pos = getButtonPos(); + addFilter = Button.builder(Component.literal("Add Filter"), this::addFilter).pos(pos.getFirst(), pos.getSecond()).width(BUTTON_WIDTH).build(); scroll = new ConfigScroll(0, BUTTON_HEIGHT + TITLE_Y_OFFSET + 16, window.getGuiScaledWidth(), window.getGuiScaledHeight() - BUTTON_HEIGHT, Constants.WIDGET_WIDTH); } @@ -53,8 +53,8 @@ public class FilterList extends Screen { graphics.text(this.font, this.title, 0, 0, TITLE_COLOR, true); stack.popMatrix(); - Tuple<Integer, Integer> pos = getButtonPos(); - graphics.textWithWordWrap( this.font, INFO_TEXT, pos.getA() + BUTTON_WIDTH + 5, pos.getB(), 245, 0xffffffff, true); + Pair<Integer, Integer> pos = getButtonPos(); + graphics.textWithWordWrap( this.font, INFO_TEXT, pos.getFirst() + BUTTON_WIDTH + 5, pos.getSecond(), 245, 0xffffffff, true); } @Override @@ -65,10 +65,10 @@ public class FilterList extends Screen { updateList(); } - private Tuple<Integer, Integer> getButtonPos() { + private Pair<Integer, Integer> getButtonPos() { Minecraft client = Minecraft.getInstance(); Window window = client.getWindow(); - return new Tuple<>((window.getGuiScaledWidth() - Constants.WIDGET_WIDTH) / 2, TITLE_Y_OFFSET + 16); + return Pair.of((window.getGuiScaledWidth() - Constants.WIDGET_WIDTH) / 2, TITLE_Y_OFFSET + 16); } @@ -92,7 +92,7 @@ public class FilterList extends Screen { public void onClose() { assert this.minecraft != null; Notifications.save(); - this.minecraft.setScreen(this.parent); + this.minecraft.gui.setScreen(this.parent); Filters.filterManager.save(); } @@ -22,7 +22,7 @@ public class NotificationEditScreen extends Screen { super(Component.empty()); Minecraft client = Minecraft.getInstance(); - parent = client.screen; + parent = client.gui.screen(); Window window = client.getWindow(); scroll = new ConfigScroll(0, 30, window.getGuiScaledWidth(), window.getGuiScaledHeight(), Constants.WIDGET_WIDTH); this.notification = notification; @@ -51,6 +51,6 @@ public class NotificationEditScreen extends Screen { @Override public void onClose() { assert this.minecraft != null; - this.minecraft.setScreen(this.parent); + this.minecraft.gui.setScreen(this.parent); } } @@ -1,5 +1,6 @@ package blade.addon.features.notifications; +import com.mojang.datafixers.util.Pair; import config.practical.utilities.Constants; import config.practical.utilities.DrawHelper; import net.minecraft.client.Minecraft; @@ -11,7 +12,6 @@ import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; -import net.minecraft.util.Tuple; class NotificationEntry extends AbstractWidget { @@ -47,8 +47,8 @@ class NotificationEntry extends AbstractWidget { drawText(graphics, textRenderer, notification.getMatchString(), x + PADDING, y); drawText(graphics, textRenderer, notification.getNotificationString(), x + PADDING * 2 + TEXT_SPACE, y); - Tuple<Integer, Integer> pos = getRemovePos(); - graphics.blitSprite(RenderPipelines.GUI_TEXTURED, CROSS, pos.getA(), pos.getB(), SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); + Pair<Integer, Integer> pos = getRemovePos(); + graphics.blitSprite(RenderPipelines.GUI_TEXTURED, CROSS, pos.getFirst(), pos.getSecond(), SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); } private void drawText(GuiGraphicsExtractor context, Font textRenderer, String string, int x, int y) { @@ -67,13 +67,13 @@ class NotificationEntry extends AbstractWidget { context.disableScissor(); } - private Tuple<Integer, Integer> getRemovePos() { - return new Tuple<>(getX() + width - SPRITE_SIZE - 5, getY() + (height - SPRITE_SIZE) / 2); + private Pair<Integer, Integer> getRemovePos() { + return Pair.of(getX() + width - SPRITE_SIZE - 5, getY() + (height - SPRITE_SIZE) / 2); } private boolean inRemovalBounds(double x, double y) { - Tuple<Integer, Integer> pos = getRemovePos(); - return x >= pos.getA() && x <= pos.getA() + SPRITE_SIZE && y >= pos.getB() && y <= pos.getB() + SPRITE_SIZE; + Pair<Integer, Integer> pos = getRemovePos(); + return x >= pos.getFirst() && x <= pos.getFirst() + SPRITE_SIZE && y >= pos.getSecond() && y <= pos.getSecond() + SPRITE_SIZE; } @Override @@ -89,7 +89,7 @@ class NotificationEntry extends AbstractWidget { //make sure you cant click around the button accidentally if (width + getX() - SPRITE_WIDTH_AREA < x) return; - Minecraft.getInstance().setScreen(new NotificationEditScreen(notification)); + Minecraft.getInstance().gui.setScreen(new NotificationEditScreen(notification)); } @Override @@ -28,7 +28,7 @@ public class NotificationList extends Screen { super(Component.literal("Notifications")); Minecraft client = Minecraft.getInstance(); - parent = client.screen; + parent = client.gui.screen(); Window window = client.getWindow(); scroll = new ConfigScroll(0, BUTTON_HEIGHT + TITLE_Y_OFFSET + 16, window.getGuiScaledWidth(), window.getGuiScaledHeight() - BUTTON_HEIGHT, Constants.WIDGET_WIDTH); @@ -59,7 +59,7 @@ public class NotificationList extends Screen { @Override public void onClose() { Notifications.save(); - this.minecraft.setScreen(this.parent); + this.minecraft.gui.setScreen(this.parent); } private void updateList() { @@ -24,6 +24,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; import java.util.Collections; import java.util.List; @@ -387,7 +388,7 @@ public class PracticeSS { private static void renderBackground(int backgroundIndex) { if (buttons.size() > backgroundIndex && backgroundIndex >= 0) { - AABB box = AABB.ofSize(buttons.get(backgroundIndex).getCenter(), 1, 1, 1); + AABB box = AABB.ofSize(Vec3.atCenterOf(buttons.get(backgroundIndex)), 1, 1, 1); int dx, dz; switch (direction) { case SOUTH -> { @@ -2,6 +2,7 @@ package blade.addon.mixin; import blade.addon.utils.config.values.Visual; import net.minecraft.client.renderer.entity.layers.ArrowLayer; +import net.minecraft.client.renderer.entity.state.AvatarRenderState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -11,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class ArrowLayerMixin { @Inject(method = "numStuck", at=@At("TAIL"), cancellable = true) - public void shouldRender(CallbackInfoReturnable<Integer> cir) { + public void shouldRender(AvatarRenderState state, CallbackInfoReturnable<Integer> cir) { if (Visual.hideStuckArrows) { cir.setReturnValue(0); } @@ -28,7 +28,7 @@ public class ChatScreenMixin { if (!ExtraOptions.copyChat || click.button() != GLFW.GLFW_MOUSE_BUTTON_RIGHT) return; Minecraft mc = Minecraft.getInstance(); - ChatComponent chatHud = mc.gui.getChat(); + ChatComponent chatHud = mc.gui.hud.getChat(); ChatComponentMixin hudAccessor = (ChatComponentMixin) chatHud; if (chatHud == null) return; @@ -4,6 +4,7 @@ import blade.addon.features.other.SwingAnimation; import blade.addon.utils.config.values.Visual; import blade.addon.utils.data.EntityUtil; import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.EnderpearlItem; import net.minecraft.world.level.Level; @@ -16,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; public class EnderPearlItemMixin { @Inject(method = "use", at=@At("HEAD")) - private void use(Level world, Player user, InteractionHand hand, CallbackInfoReturnable<Boolean> cir) { + private void use(Level world, Player user, InteractionHand hand, CallbackInfoReturnable<InteractionResult> cir) { if (Visual.stopPearlSwing && EntityUtil.isClientPlayer(user)) { SwingAnimation.ignoreNext(2); } @@ -1,96 +1,19 @@ package blade.addon.mixin; -import blade.addon.features.dungeon.f7.terms.TitleHider; -import blade.addon.features.dungeon.f7.terms.device.DeviceNotifier; -import blade.addon.utils.config.components.Components; -import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.config.values.Visual; -import blade.addon.utils.interfaces.GameHud; -import blade.addon.utils.rendering.DrawEvents; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.DeltaTracker; +import blade.addon.utils.events.Events; +import blade.addon.utils.events.interfaces.ScreenEvent; import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiGraphicsExtractor; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.util.profiling.Profiler; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; +import net.minecraft.client.gui.screens.Screen; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Gui.class) -public class GuiMixin implements GameHud { +public class GuiMixin { - @Shadow - private Component title; - @Shadow - private Component subtitle; - @Shadow - private int titleFadeInTime; - @Shadow - private int titleStayTime; - @Shadow - private int titleFadeOutTime; - @Shadow - private int titleTime; - - @Shadow - private int toolHighlightTimer; - - @Inject(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V"), order = 2000) - public void drawBackground(GuiGraphicsExtractor context, int x, int y, DeltaTracker tickCounter, Player player, ItemStack stack, int seed, CallbackInfo ci) { - DrawEvents.HUD_SLOT_BEFORE.invoke(slotEvent -> slotEvent.draw(context, stack, x, y)); - } - - @Inject(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", shift = At.Shift.AFTER), order = 2000) - public void drawStar(GuiGraphicsExtractor context, int x, int y, DeltaTracker tickCounter, Player player, ItemStack stack, int seed, CallbackInfo ci) { - DrawEvents.HUD_SLOT_AFTER.invoke(slotEvent -> slotEvent.draw(context, stack, x, y)); - } - - @Inject(method = "extractEffects", at = @At("HEAD"), cancellable = true, order = 2000) - public void renderStatusEffectsOverLay(GuiGraphicsExtractor context, DeltaTracker tickCounter, CallbackInfo ci) { - if (Visual.hideStatusOverLay) { - ci.cancel(); - } - } - - @Inject(method = "setTitle", at = @At("HEAD"), cancellable = true, order = 2000) - public void setTitle(Component title, CallbackInfo ci) { - if (TitleHider.shouldHideTitle(title)) ci.cancel(); - else if (DeviceNotifier.disableTitles(title)) ci.cancel(); - } - - @Inject(method = "setSubtitle", at = @At("HEAD"), cancellable = true, order = 2000) - public void setSubtitle(Component subtitle, CallbackInfo ci) { - if (TitleHider.shouldHideTitle(subtitle)) ci.cancel(); - else if (DeviceNotifier.disableTitles(subtitle)) ci.cancel(); - } - - @Inject(method = "extractSelectedItemName", at=@At("HEAD")) - private void getFadeDuration(GuiGraphicsExtractor graphics, CallbackInfo ci) { - if (!ExtraOptions.moveToolTip) return; - Components.toolTipDisplay.setFade(toolHighlightTimer); - } - - @Inject(method = "extractSelectedItemName", at= @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;textWithBackdrop(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;IIII)V"), cancellable = true) - private void renderHeldItemTooltip(GuiGraphicsExtractor graphics, CallbackInfo ci, @Local(name = "str") MutableComponent mutableText, @Local(name = "alpha") int color) { - if (!ExtraOptions.moveToolTip) return; - ci.cancel(); - Components.toolTipDisplay.setText(mutableText); - Components.toolTipDisplay.setColor(color); - Profiler.get().pop(); - } - - - @Unique - public void blade_addons$forceTitle(Component title, Component subtitle) { - this.title = title; - this.subtitle = subtitle; - this.titleTime = this.titleFadeInTime + this.titleStayTime + this.titleFadeOutTime; + @Inject(method = "setScreen", at = @At("HEAD")) + public void onClose(Screen screen, CallbackInfo ci) { + if (screen == null) Events.ON_SCREEN.invoke(screenEvent -> screenEvent.onScreen(null)); } } @@ -0,0 +1,96 @@ +package blade.addon.mixin; + +import blade.addon.features.dungeon.f7.terms.TitleHider; +import blade.addon.features.dungeon.f7.terms.device.DeviceNotifier; +import blade.addon.utils.config.components.Components; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.interfaces.GameHud; +import blade.addon.utils.rendering.DrawEvents; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.DeltaTracker; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.Hud; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.profiling.Profiler; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Hud.class) +public class HudMixin implements GameHud { + + @Shadow + private Component title; + @Shadow + private Component subtitle; + @Shadow + private int titleFadeInTime; + @Shadow + private int titleStayTime; + @Shadow + private int titleFadeOutTime; + @Shadow + private int titleTime; + + @Shadow + private int toolHighlightTimer; + + @Inject(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V"), order = 2000) + public void drawBackground(GuiGraphicsExtractor context, int x, int y, DeltaTracker tickCounter, Player player, ItemStack stack, int seed, CallbackInfo ci) { + DrawEvents.HUD_SLOT_BEFORE.invoke(slotEvent -> slotEvent.draw(context, stack, x, y)); + } + + @Inject(method = "extractSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", shift = At.Shift.AFTER), order = 2000) + public void drawStar(GuiGraphicsExtractor context, int x, int y, DeltaTracker tickCounter, Player player, ItemStack stack, int seed, CallbackInfo ci) { + DrawEvents.HUD_SLOT_AFTER.invoke(slotEvent -> slotEvent.draw(context, stack, x, y)); + } + + @Inject(method = "extractEffects", at = @At("HEAD"), cancellable = true, order = 2000) + public void renderStatusEffectsOverLay(GuiGraphicsExtractor context, DeltaTracker tickCounter, CallbackInfo ci) { + if (Visual.hideStatusOverLay) { + ci.cancel(); + } + } + + @Inject(method = "setTitle", at = @At("HEAD"), cancellable = true, order = 2000) + public void setTitle(Component title, CallbackInfo ci) { + if (TitleHider.shouldHideTitle(title)) ci.cancel(); + else if (DeviceNotifier.disableTitles(title)) ci.cancel(); + } + + @Inject(method = "setSubtitle", at = @At("HEAD"), cancellable = true, order = 2000) + public void setSubtitle(Component subtitle, CallbackInfo ci) { + if (TitleHider.shouldHideTitle(subtitle)) ci.cancel(); + else if (DeviceNotifier.disableTitles(subtitle)) ci.cancel(); + } + + @Inject(method = "extractSelectedItemName", at=@At("HEAD")) + private void getFadeDuration(GuiGraphicsExtractor graphics, CallbackInfo ci) { + if (!ExtraOptions.moveToolTip) return; + Components.toolTipDisplay.setFade(toolHighlightTimer); + } + + @Inject(method = "extractSelectedItemName", at= @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/GuiGraphicsExtractor;textWithBackdrop(Lnet/minecraft/client/gui/Font;Lnet/minecraft/network/chat/Component;IIII)V"), cancellable = true) + private void renderHeldItemTooltip(GuiGraphicsExtractor graphics, CallbackInfo ci, @Local(name = "str") MutableComponent mutableText, @Local(name = "alpha") int color) { + if (!ExtraOptions.moveToolTip) return; + ci.cancel(); + Components.toolTipDisplay.setText(mutableText); + Components.toolTipDisplay.setColor(color); + Profiler.get().pop(); + } + + + @Unique + public void blade_addons$forceTitle(Component title, Component subtitle) { + this.title = title; + this.subtitle = subtitle; + this.titleTime = this.titleFadeInTime + this.titleStayTime + this.titleFadeOutTime; + } +} @@ -5,7 +5,6 @@ import blade.addon.utils.events.Events; import blade.addon.utils.events.interfaces.WorldEvent; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.BlockHitResult; @@ -43,9 +42,4 @@ public class MinecraftMixin { private void onWorld(ClientLevel world, CallbackInfo ci) { Events.ON_WORLD_CHANGE.invoke(WorldEvent::onWorldSwap); } - - @Inject(method = "setScreen", at=@At("HEAD")) - public void onClose(Screen screen, CallbackInfo ci) { - if (screen == null) Events.ON_SCREEN.invoke(screenEvent -> screenEvent.onScreen(null)); - } } @@ -85,7 +85,7 @@ public class Keybinds { public static void checkInputs(Minecraft client) { if (openConfig.consumeClick()) { - client.setScreen(Config.createScreen(null)); + client.gui.setScreen(Config.createScreen(null)); } if (trades.consumeClick()) { @@ -40,7 +40,7 @@ public class Misc { try { if (INSTANCE == null) return; Gui gameHud = INSTANCE.gui; - ChatComponent hud = gameHud.getChat(); + ChatComponent hud = gameHud.hud.getChat(); forceMainThread(() -> hud.addClientSystemMessage(Component.literal(ExtraOptions.textPrefix).append(text))); } catch (IndexOutOfBoundsException ignored) { Debug.LOGGER.error("Chat message failed to get added"); @@ -52,7 +52,7 @@ public class Misc { } public static void setTitle(Component text) { - forceMainThread(() -> INSTANCE.gui.setTitle(text)); + forceMainThread(() -> INSTANCE.gui.hud.setTitle(text)); } public static void forceTitle(Component title, Component subtitle) { @@ -32,7 +32,7 @@ public class Scheduler { if (scheduledScreen != null) { screenTicks--; if (screenTicks <= 0) { - minecraftClient.setScreen(scheduledScreen); + minecraftClient.gui.setScreen(scheduledScreen); scheduledScreen = null; } } @@ -53,13 +53,13 @@ public class Config { general.add(new ConfigString(Component.literal("Message prefix"), () -> ExtraOptions.textPrefix, str -> ExtraOptions.textPrefix = str)); ConfigSection notifications = new ConfigSection(Component.literal("Chat Notifications")); - notifications.add(new ConfigButton(Component.literal("Edit Notifications"), () -> Minecraft.getInstance().setScreen(new NotificationList()))); + notifications.add(new ConfigButton(Component.literal("Edit Notifications"), () -> Minecraft.getInstance().gui.setScreen(new NotificationList()))); notifications.add(new ConfigBool(Component.literal("Ignore color codes"), () -> ExtraOptions.ignoreColorCodesNotification, bool -> ExtraOptions.ignoreColorCodesNotification = bool)); general.add(notifications); ConfigSection chatFilter = new ConfigSection(Component.literal("Chat filter")); - chatFilter.add(new ConfigButton(Component.literal("Edit"), () -> Minecraft.getInstance().setScreen(new FilterList()))); + chatFilter.add(new ConfigButton(Component.literal("Edit"), () -> Minecraft.getInstance().gui.setScreen(new FilterList()))); chatFilter.add(new ConfigBool(Component.literal("Ignore color codes"), () -> ExtraOptions.ignoreColorCodesFilter, bool -> ExtraOptions.ignoreColorCodesFilter = bool)); chatFilter.add(new ConfigBool(Component.literal("Disable all filters"), () -> ExtraOptions.disableAllFilters, bool -> ExtraOptions.disableAllFilters = bool)); general.add(chatFilter); @@ -106,11 +106,11 @@ public class TextUtil { private static char getFormatChar(int color) { for (ChatFormatting format: ChatFormatting.values()) { - Integer colorValue = format.getColor(); - if (colorValue == null) continue; + TextColor textColor = TextColor.fromLegacyFormat(format); + if (textColor == null) continue; - if (colorValue == color) { - return format.getChar(); + if (textColor.getValue() == color) { + return format.toString().charAt(1); } } @@ -3,7 +3,6 @@ package blade.addon.utils.rendering; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.rendertype.RenderType; import net.minecraft.client.renderer.state.level.LevelRenderState; import net.minecraft.world.phys.Vec3; @@ -39,15 +38,76 @@ public class RenderHandler { Vec3 camera = worldState.cameraRenderState.pos; PoseStack matrices = context.poseStack(); if (matrices == null) return; + if (listeners.isEmpty()) return; matrices.pushPose(); matrices.translate(-camera.x, -camera.y, -camera.z); - MultiBufferSource consumers = context.bufferSource(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(renderType); + // Listeners run during the submit-collection phase (they also submit Gizmos and text, which + // are only accepted while collecting). Their vertex output is recorded and replayed into the + // real per-frame consumer when the custom geometry submit is drawn. + RecordingVertexConsumer recording = new RecordingVertexConsumer(); + invoke(renderingEvent -> renderingEvent.render(context, matrices, recording)); - invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); + context.submitNodeCollector().submitCustomGeometry(matrices, renderType, (pose, consumer) -> recording.replay(consumer)); matrices.popPose(); } + private static final class RecordingVertexConsumer implements VertexConsumer { + private final List<Consumer<VertexConsumer>> ops = new ArrayList<>(); + + @Override + public VertexConsumer addVertex(float x, float y, float z) { + ops.add(consumer -> consumer.addVertex(x, y, z)); + return this; + } + + @Override + public VertexConsumer setColor(int r, int g, int b, int a) { + ops.add(consumer -> consumer.setColor(r, g, b, a)); + return this; + } + + @Override + public VertexConsumer setColor(int rgba) { + ops.add(consumer -> consumer.setColor(rgba)); + return this; + } + + @Override + public VertexConsumer setUv(float u, float v) { + ops.add(consumer -> consumer.setUv(u, v)); + return this; + } + + @Override + public VertexConsumer setUv1(int u, int v) { + ops.add(consumer -> consumer.setUv1(u, v)); + return this; + } + + @Override + public VertexConsumer setUv2(int u, int v) { + ops.add(consumer -> consumer.setUv2(u, v)); + return this; + } + + @Override + public VertexConsumer setNormal(float x, float y, float z) { + ops.add(consumer -> consumer.setNormal(x, y, z)); + return this; + } + + @Override + public VertexConsumer setLineWidth(float width) { + ops.add(consumer -> consumer.setLineWidth(width)); + return this; + } + + private void replay(VertexConsumer consumer) { + for (Consumer<VertexConsumer> op : ops) { + op.accept(consumer); + } + } + } + } @@ -1,56 +1,96 @@ package blade.addon.utils.rendering; import blade.addon.utils.Constants; +import com.mojang.blaze3d.PrimitiveTopology; +import com.mojang.blaze3d.pipeline.BlendFunction; +import com.mojang.blaze3d.pipeline.ColorTargetState; import com.mojang.blaze3d.pipeline.DepthStencilState; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.platform.CompareOp; import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.BindGroupLayouts; import net.minecraft.resources.Identifier; public class RenderPipelines { - public static final RenderPipeline FILLED_DEBUG = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + + // Vanilla's DEBUG_FILLED_SNIPPET / LINES_SNIPPET are private in 26.2; rebuilt here with identical + // composition (see net.minecraft.client.renderer.RenderPipelines static initializer). + private static final RenderPipeline.Snippet GLOBALS_SNIPPET = RenderPipeline.builder() + .withBindGroupLayout(BindGroupLayouts.GLOBALS) + .buildSnippet(); + + private static final RenderPipeline.Snippet DEBUG_FILLED_SNIPPET = RenderPipeline.builder(GLOBALS_SNIPPET) + .withBindGroupLayout(BindGroupLayouts.MATRICES_PROJECTION) + .withVertexShader("core/position_color") + .withFragmentShader("core/position_color") + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) + .withDepthStencilState(new DepthStencilState(CompareOp.GREATER_THAN_OR_EQUAL, false)) + .withCull(false) + .buildSnippet(); + + private static final RenderPipeline.Snippet LINES_SNIPPET = RenderPipeline.builder(GLOBALS_SNIPPET) + .withBindGroupLayout(BindGroupLayouts.MATRICES_PROJECTION) + .withBindGroupLayout(BindGroupLayouts.FOG) + .withVertexShader("core/rendertype_lines") + .withFragmentShader("core/rendertype_lines") + .withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT)) + .withCull(false) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) + .withPrimitiveTopology(PrimitiveTopology.LINES) + .withDepthStencilState(DepthStencilState.DEFAULT) + .buildSnippet(); + + public static final RenderPipeline FILLED_DEBUG = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) .withDepthStencilState(DepthStencilState.DEFAULT) .build()); - public static final RenderPipeline FILLED_DEBUG_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + public static final RenderPipeline FILLED_DEBUG_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug-no-depth-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) .build()); - public static final RenderPipeline FILLED = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + public static final RenderPipeline FILLED = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) .withDepthStencilState(DepthStencilState.DEFAULT) .build()); - public static final RenderPipeline LINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) + public static final RenderPipeline LINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(LINES_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "line-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) + .withPrimitiveTopology(PrimitiveTopology.LINES) .withDepthStencilState(DepthStencilState.DEFAULT) .build()); - public static final RenderPipeline FILLED_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + public static final RenderPipeline FILLED_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-no-depth-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR) + .withPrimitiveTopology(PrimitiveTopology.QUADS) .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) .build()); - public static final RenderPipeline LINE_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) + public static final RenderPipeline LINE_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(LINES_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(blade.addon.utils.Constants.NAMESPACE, "line-no-depth-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) + .withPrimitiveTopology(PrimitiveTopology.LINES) .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) .build()); - public static final RenderPipeline TEXT = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) + public static final RenderPipeline TEXT = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(LINES_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(blade.addon.utils.Constants.NAMESPACE, "text-pipe")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) + .withVertexBinding(0, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH) + .withPrimitiveTopology(PrimitiveTopology.LINES) .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) .build()); } @@ -103,7 +103,7 @@ public class RenderUtils { float halfWidth = textRenderer.width(text.getString()) / 2f; - textRenderer.drawInBatch(text, -halfWidth, 0, 0xffffffff, true, matrices.last().pose(), context.bufferSource(), Font.DisplayMode.SEE_THROUGH, 0, 15728880); + context.submitNodeCollector().submitText(matrices, -halfWidth, 0, text.getVisualOrderText(), true, Font.DisplayMode.SEE_THROUGH, 15728880, 0xffffffff, 0, 0); matrices.popPose(); } @@ -14,12 +14,14 @@ public class RenderingEvents { public static void init() { + // 26.2 only accepts submits while the node collection is open; AFTER_TRANSLUCENT_FEATURES fires + // during the draw passes, after the collection has been prepared, so everything must register here. LevelRenderEvents.COLLECT_SUBMITS.register(FILLED_DEBUG::init); LevelRenderEvents.COLLECT_SUBMITS.register(FILLED_DEBUG_NO_DEPTH::init); - LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(FILLED::init); - LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(LINE::init); - LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(FILLED_NO_DEPTH::init); - LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(LINE_NO_DEPTH::init); - LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(TEXT::init); + LevelRenderEvents.COLLECT_SUBMITS.register(FILLED::init); + LevelRenderEvents.COLLECT_SUBMITS.register(LINE::init); + LevelRenderEvents.COLLECT_SUBMITS.register(FILLED_NO_DEPTH::init); + LevelRenderEvents.COLLECT_SUBMITS.register(LINE_NO_DEPTH::init); + LevelRenderEvents.COLLECT_SUBMITS.register(TEXT::init); } } @@ -32,6 +32,7 @@ "GuiGraphicsExtractorMixin", "GuiMixin", "HeldItemRendererMixin", + "HudMixin", "InventoryScreenMixin", "KeyboardHandlerMixin", "LocalPlayerMixin", @@ -27,10 +27,9 @@ ], "depends": { "fabricloader": ">=0.19.3", - "minecraft": "~26.1.2", + "minecraft": "~26.2", "java": ">=25", - "fabric-api": "*", - "hypixel-mod-api": "*" + "fabric-api": "*" }, "suggests": { "another-mod": "*" |
- fixed splits - fixed capitalisation in rerollblocker查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 2 +- src/main/resources/data/splits.json | 88 ++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------- 2 files changed, 45 insertions(+), 45 deletions(-) @@ -14,7 +14,7 @@ import net.minecraft.world.item.Items; public class RerollBlocker { - private static final String[] BLOCKED_REROLLS = {"Recombobulator ", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; + private static final String[] BLOCKED_REROLLS = {"Recombobulator ", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow Fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; @@ -2,7 +2,7 @@ "E": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Congratulations, you made it through the Entrance.", "color": 11141120 }, @@ -14,7 +14,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -22,7 +22,7 @@ "F1": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Ah, you've finally arrived.", "color": 11141120 }, @@ -40,7 +40,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Bonzo: Gratz for making it this far, but I'm basically unbeatable.", "color": 5592575 }, @@ -52,7 +52,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -60,7 +60,7 @@ "M1": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Ah, you've finally arrived.", "color": 11141120 }, @@ -78,7 +78,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Bonzo: Gratz for making it this far, but I'm basically unbeatable.", "color": 5592575 }, @@ -90,7 +90,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -98,7 +98,7 @@ "F2": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Ah, we meet again...", "color": 11141120 }, @@ -116,7 +116,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Scarf: This is where the journey ends for you, Adventurers.", "color": 5592575 }, @@ -128,7 +128,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -136,7 +136,7 @@ "M2": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Ah, we meet again...", "color": 11141120 }, @@ -154,7 +154,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Scarf: This is where the journey ends for you, Adventurers.", "color": 5592575 }, @@ -166,7 +166,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -174,7 +174,7 @@ "F3": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: So you made it this far... interesting.", "color": 11141120 }, @@ -192,7 +192,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Professor: I was burdened with terrible news recently...", "color": 5592575 }, @@ -204,7 +204,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -212,7 +212,7 @@ "M3": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: So you made it this far... interesting.", "color": 11141120 }, @@ -230,7 +230,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Professor: I was burdened with terrible news recently...", "color": 5592575 }, @@ -242,7 +242,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -250,7 +250,7 @@ "F4": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: You've managed to scratch and claw your way here, eh?", "color": 11141120 }, @@ -268,7 +268,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Thorn: Welcome Adventurers! I am Thorn, the Spirit! And host of the Vegan Trials!", "color": 5592575 }, @@ -280,7 +280,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -288,7 +288,7 @@ "M4": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: You've managed to scratch and claw your way here, eh?", "color": 11141120 }, @@ -306,7 +306,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Thorn: Welcome Adventurers! I am Thorn, the Spirit! And host of the Vegan Trials!", "color": 5592575 }, @@ -318,7 +318,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -326,7 +326,7 @@ "F5": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: I'm starting to get tired of seeing you around here...", "color": 11141120 }, @@ -344,7 +344,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Livid: Welcome, you've arrived right on time. I am Livid, the Master of Shadows.", "color": 5592575 }, @@ -356,7 +356,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -364,7 +364,7 @@ "M5": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: I'm starting to get tired of seeing you around here...", "color": 11141120 }, @@ -382,7 +382,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Livid: Welcome, you've arrived right on time. I am Livid, the Master of Shadows.", "color": 5592575 }, @@ -394,7 +394,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -402,7 +402,7 @@ "F6": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Oh.. hello?", "color": 11141120 }, @@ -420,7 +420,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Sadan: So you made it all the way here... Now you wish to defy me? Sadan?!", "color": 5592575 }, @@ -444,7 +444,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -452,7 +452,7 @@ "M6": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Oh.. hello?", "color": 11141120 }, @@ -470,7 +470,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Sadan: So you made it all the way here... Now you wish to defy me? Sadan?!", "color": 5592575 }, @@ -494,7 +494,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -502,7 +502,7 @@ "F7": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Things feel a little more roomy now, eh?", "color": 11141120 }, @@ -520,7 +520,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Maxor: WELL! WELL! WELL! LOOK WHO'S HERE!", "color": 5592575 }, @@ -556,7 +556,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } @@ -564,7 +564,7 @@ "M7": [ { "name": "Blood Open", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] The Watcher: Things feel a little more roomy now, eh?", "color": 11141120 }, @@ -582,7 +582,7 @@ }, { "name": "Boss Entry", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "[BOSS] Maxor: WELL! WELL! WELL! LOOK WHO'S HERE!", "color": 5592575 }, @@ -624,7 +624,7 @@ }, { "name": "Run Time", - "start": "§e[NPC] §bMort§f: Here, I found this map when I first entered the dungeon.", + "start": "[NPC] Mort: Here, I found this map when I first entered the dungeon.", "end": "some dummy string", "color": 4279733527 } |
- made rerollblocker on click instead of scanning查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 81 +++++++++++++++++++++++++++++++++++---------------------------------------------- src/main/java/blade/addon/features/other/BlockPetMenu.java | 2 +- src/main/java/blade/addon/mixin/AbstractContainerScreenMixin.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/SlotClickEvent.java | 3 ++- 4 files changed, 39 insertions(+), 49 deletions(-) @@ -6,7 +6,7 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.world.Container; import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.item.ItemStack; @@ -14,67 +14,38 @@ import net.minecraft.world.item.Items; public class RerollBlocker { - //,"Emerald", "Diamond", "Gold", "Wood" - private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Recombobulator", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; + private static final String[] BLOCKED_REROLLS = {"Recombobulator ", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; public static void init() { - Events.ON_SCREEN.register(screen -> { - if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; - - blockClick = false; + Events.ON_SCREEN.register(_ -> { containerId = Integer.MIN_VALUE; - - if (screen instanceof ContainerScreen containerScreen) { - - Component title = containerScreen.getTitle(); - if (title == null) return false; - - if (!isValidGUI(title.getString())) return false; - - ChestMenu menu = containerScreen.getMenu(); - containerId = menu.containerId; - } return false; }); - Events.ON_PACKET.register(packet -> { + Events.ON_SLOT_CLICKED.register((slot, slotId, _, containerInput, screen) -> { if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; + if (containerInput == ContainerInput.THROW) return false; + if (slotId != 50 || slot.getItem().getItem() != Items.FEATHER) return false; - if (blockClick) return false; - if (packet instanceof ClientboundContainerSetSlotPacket containerSetSlotPacket) { - if (containerSetSlotPacket.getContainerId() != containerId) return false; - if (containerSetSlotPacket.getSlot() >= 54) return false; - - ItemStack itemStack = containerSetSlotPacket.getItem(); - Component component = itemStack.getCustomName(); - if (component == null) return false; + if (screen instanceof ContainerScreen containerScreen) { + ChestMenu menu = containerScreen.getMenu(); + if (menu == null) return false; + Container container = menu.getContainer(); + if (container == null) return false; - String blocked = getBlockedItem(component.getString()); - if (blocked != null) { - blockClick = true; - Misc.addChatMessage(Component.literal("Blocked reroll {name: " + blocked + "} {Item name: " + component.getString() + "}")); + if (menu.containerId != containerId) { + scanContainer(container); + containerId = menu.containerId; } - } - return false; - }); - - Events.ON_SLOT_CLICKED.register((slot, slotId, _, containerInput) -> { - Misc.addChatMessage(Component.literal(slotId + " " + containerInput)); - if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; - if (containerInput == ContainerInput.THROW) return false; - Misc.addChatMessage(Component.literal(slot.getItem().getItem().toString())); - if (slotId != 50 || slot.getItem().getItem() != Items.FEATHER) return false; ItemStack itemStack = slot.getItem(); Component customName = itemStack.getCustomName(); if (customName == null) return false; - Misc.addChatMessage(customName); if (!customName.getString().contains("Reroll Chest")) return false; return blockClick; @@ -82,10 +53,28 @@ public class RerollBlocker { } - private static boolean isValidGUI(String title) { - for (String name : CHESTS) { - if (name.equalsIgnoreCase(title)) return true; + private static void scanContainer(Container container) { + for (int i = 0; i < 54; i++) { + ItemStack itemStack = container.getItem(i); + if (scanItem(itemStack)) { + blockClick = true; + return; + } } + + blockClick = false; + } + + private static boolean scanItem(ItemStack itemStack) { + Component component = itemStack.getCustomName(); + if (component == null) return false; + + String blocked = getBlockedItem(component.getString()); + if (blocked != null) { + Misc.addChatMessage(Component.literal("Blocked reroll {name: " + blocked + "} {Item name: " + component.getString() + "}")); + return true; + } + return false; } @@ -19,7 +19,7 @@ public class BlockPetMenu { return false; }); - Events.ON_SLOT_CLICKED.register((slot,slotId, button, containerInput) -> { + Events.ON_SLOT_CLICKED.register((_,slotId, button, _, _) -> { if (inPetMenu && button == 1 && Dungeons.blockRemovingPet && Location.inDungeon()) { return slotId >= 9 && slotId <= 44; } @@ -95,7 +95,7 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe @Inject(method = "slotClicked", at = @At("HEAD"), cancellable = true) public void slotClicked(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) { - if (Events.ON_SLOT_CLICKED.invoke(slotEvent -> slotEvent.onSlot(slot, slotId, buttonNum, containerInput))) { + if (Events.ON_SLOT_CLICKED.invoke(slotEvent -> slotEvent.onSlot(slot, slotId, buttonNum, containerInput, this))) { ci.cancel(); } } @@ -1,8 +1,9 @@ package blade.addon.utils.events.interfaces; +import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; public interface SlotClickEvent { - boolean onSlot(Slot slot, int slotId, int button, ContainerInput containerInput); + boolean onSlot(Slot slot, int slotId, int button, ContainerInput containerInput, Screen container); } |
- added a bunch of debug messages temp查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) @@ -16,7 +16,7 @@ public class RerollBlocker { //,"Emerald", "Diamond", "Gold", "Wood" private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Recombobulator ", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; + private static final String[] BLOCKED_REROLLS = {"Recombobulator", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; @@ -66,14 +66,15 @@ public class RerollBlocker { }); Events.ON_SLOT_CLICKED.register((slot, slotId, _, containerInput) -> { + Misc.addChatMessage(Component.literal(slotId + " " + containerInput)); if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; if (containerInput == ContainerInput.THROW) return false; + Misc.addChatMessage(Component.literal(slot.getItem().getItem().toString())); if (slotId != 50 || slot.getItem().getItem() != Items.FEATHER) return false; - ItemStack itemStack = slot.getItem(); Component customName = itemStack.getCustomName(); if (customName == null) return false; - + Misc.addChatMessage(customName); if (!customName.getString().contains("Reroll Chest")) return false; return blockClick; |
- added a space so it hopefully skips auto recombs查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -16,7 +16,7 @@ public class RerollBlocker { //,"Emerald", "Diamond", "Gold", "Wood" private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Recombobulator", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; + private static final String[] BLOCKED_REROLLS = {"Recombobulator ", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; |
- testing if removing number stops stupid shit查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -16,7 +16,7 @@ public class RerollBlocker { //,"Emerald", "Diamond", "Gold", "Wood" private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Recombobulator 3000", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; + private static final String[] BLOCKED_REROLLS = {"Recombobulator", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; |
- changed override for blockedreroll to the drop key - fixed it checking inventory for blocked items查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 5 +++-- src/main/java/blade/addon/mixin/GuiGraphicsExtractorMixin.java | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) @@ -16,7 +16,7 @@ public class RerollBlocker { //,"Emerald", "Diamond", "Gold", "Wood" private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; + private static final String[] BLOCKED_REROLLS = {"Recombobulator 3000", "Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; @@ -48,6 +48,7 @@ public class RerollBlocker { if (blockClick) return false; if (packet instanceof ClientboundContainerSetSlotPacket containerSetSlotPacket) { if (containerSetSlotPacket.getContainerId() != containerId) return false; + if (containerSetSlotPacket.getSlot() >= 54) return false; ItemStack itemStack = containerSetSlotPacket.getItem(); Component component = itemStack.getCustomName(); @@ -66,7 +67,7 @@ public class RerollBlocker { Events.ON_SLOT_CLICKED.register((slot, slotId, _, containerInput) -> { if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; - if (containerInput == ContainerInput.QUICK_MOVE) return false; + if (containerInput == ContainerInput.THROW) return false; if (slotId != 50 || slot.getItem().getItem() != Items.FEATHER) return false; ItemStack itemStack = slot.getItem(); @@ -76,6 +76,7 @@ public abstract class GuiGraphicsExtractorMixin { float newX = xo + 6; float newY = yo - ((float) h / 2) * Visual.tooltipSize + 4; + //remove bottom overflow hopefully if ((h + newY) * Visual.tooltipSize > this.guiHeight()) { newY = this.guiHeight() - h - 4; } |
- reworked tooltip scalar查看变更src/main/java/blade/addon/mixin/GuiGraphicsExtractorMixin.java | 49 ++++++++++++++++++++++++++++++------------------- src/main/java/blade/addon/utils/config/Config.java | 2 +- 2 files changed, 31 insertions(+), 20 deletions(-) @@ -1,6 +1,8 @@ package blade.addon.mixin; import blade.addon.utils.config.values.Visual; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; @@ -16,20 +18,21 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArgs; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.invoke.arg.Args; import java.util.List; @Mixin(GuiGraphicsExtractor.class) -public class GuiGraphicsExtractorMixin { +public abstract class GuiGraphicsExtractorMixin { @Final @Shadow private Matrix3x2fStack pose; + @Shadow + public abstract int guiHeight(); + @ModifyVariable(method = "itemCooldown", at = @At("STORE"), ordinal = 0) private float noCooldown(float f) { return Visual.hideCooldown ? 0 : f; @@ -54,27 +57,35 @@ public class GuiGraphicsExtractorMixin { } } - @Inject(method = "tooltip", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;pushMatrix()Lorg/joml/Matrix3x2fStack;")) - private void scaleUpTooltip_head(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, @Nullable Identifier style, CallbackInfo ci) { - - float scaledX = xo - (float) xo * Visual.tooltipSize; - float scaledY = yo - (float) yo * Visual.tooltipSize; - - pose.translate(scaledX, scaledY); - pose.scale(Visual.tooltipSize); + @ModifyExpressionValue(method = "tooltip", at = @At(value = "INVOKE", target = "Lorg/joml/Vector2ic;x()I")) + private int modifyTooltipX(int x) { + if (Visual.tooltipSize == 1) return x; + return 0; } - @ModifyArgs(method = "tooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;positionTooltip(IIIIII)Lorg/joml/Vector2ic;")) - private void scaleUpTooltip(Args args) { + @ModifyExpressionValue(method = "tooltip", at = @At(value = "INVOKE", target = "Lorg/joml/Vector2ic;y()I")) + private int modifyTooltipY(int y) { + if (Visual.tooltipSize == 1) return y; + return 0; + } - int w = args.get(4); - int h = args.get(5); + @Inject(method = "tooltip", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;pushMatrix()Lorg/joml/Matrix3x2fStack;")) + private void scaleUpTooltip_head(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, + @Nullable Identifier style, CallbackInfo ci, @Local(name = "h") int h) { + if (Visual.tooltipSize == 1) return; + float newX = xo + 6; + float newY = yo - ((float) h / 2) * Visual.tooltipSize + 4; + + if ((h + newY) * Visual.tooltipSize > this.guiHeight()) { + newY = this.guiHeight() - h - 4; + } - float scaledW = (float) w * Visual.tooltipSize; - float scaledH = (float) h * Visual.tooltipSize; + //remove top and left overflow + if (newX < 0) newX = 6; + if (newY < 0) newY = 4; - args.set(4, (int) scaledW); - args.set(5, (int) scaledH); + pose.translate(newX, newY); + pose.scale(Visual.tooltipSize); } } @@ -424,7 +424,7 @@ public class Config { ConfigSection toolTip = new ConfigSection(Component.literal("ToolTips")); toolTip.add(new ConfigBool(Component.literal("Item quality"), () -> Visual.itemQuality, bool -> Visual.itemQuality = bool)); toolTip.add(new ConfigBool(Component.literal("Pet candy"), () -> Visual.petCandy, bool -> Visual.petCandy = bool)); - toolTip.add(new ConfigFloat(Component.literal("Tooltip size"), () -> Visual.tooltipSize, num -> Visual.tooltipSize = num, 0.01f, 0.25f, 2)); + toolTip.add(new ConfigFloat(Component.literal("Tooltip size"), () -> Visual.tooltipSize, num -> Visual.tooltipSize = num, 0.01f, 0.25f, 1)); visual.add(toolTip); visual.add(new ConfigBool(Component.literal("Hide non crits"), () -> Visual.hideNoneCrits, bool -> Visual.hideNoneCrits = bool)); |
- made tooltipSize's range be bigger and allowed more precision - hopefully fixed rerollblocker having reversed logic - made tooltip scale not make the text fucked up查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 4 ++-- src/main/java/blade/addon/mixin/GuiGraphicsExtractorMixin.java | 45 ++++++++++++++++++--------------------------- src/main/java/blade/addon/utils/config/Config.java | 2 +- 3 files changed, 21 insertions(+), 30 deletions(-) @@ -16,7 +16,7 @@ public class RerollBlocker { //,"Emerald", "Diamond", "Gold", "Wood" private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Claymore"}; + private static final String[] BLOCKED_REROLLS = {"Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Dark Claymore", "Dye", "Giant's Sword", "Shadow fury"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; @@ -89,7 +89,7 @@ public class RerollBlocker { private static String getBlockedItem(String itemName) { for (String name : BLOCKED_REROLLS) { - if (name.contains(itemName)) return name; + if (itemName.contains(name)) return name; } return null; } @@ -29,17 +29,17 @@ public class GuiGraphicsExtractorMixin { @Final @Shadow private Matrix3x2fStack pose; - - @ModifyVariable(method = "itemCooldown", at=@At("STORE"), ordinal = 0) + + @ModifyVariable(method = "itemCooldown", at = @At("STORE"), ordinal = 0) private float noCooldown(float f) { - return Visual.hideCooldown? 0: f; + return Visual.hideCooldown ? 0 : f; } - @Inject(method = "item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", at=@At("HEAD")) + @Inject(method = "item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", at = @At("HEAD")) private void scaleUp(LivingEntity owner, ItemStack stack, int x, int y, int seed, CallbackInfo ci) { if (Visual.oldPlayerHead && stack.getItem() == Items.PLAYER_HEAD) { float scale = 0.875f; - int offset = (16 - (int)(scale * 16)) / 2; + int offset = (16 - (int) (scale * 16)) / 2; pose.pushMatrix(); pose.translate(x * (1 - scale) + offset, y * (1 - scale) + offset); @@ -47,43 +47,34 @@ public class GuiGraphicsExtractorMixin { } } - @Inject(method = "item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", at=@At("TAIL")) + @Inject(method = "item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", at = @At("TAIL")) private void scaleDown(LivingEntity owner, ItemStack stack, int x, int y, int seed, CallbackInfo ci) { if (Visual.oldPlayerHead && stack.getItem() == Items.PLAYER_HEAD) { pose.popMatrix(); } } - @Inject(method = "tooltip", at= @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;pushMatrix()Lorg/joml/Matrix3x2fStack;")) + @Inject(method = "tooltip", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;pushMatrix()Lorg/joml/Matrix3x2fStack;")) private void scaleUpTooltip_head(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, @Nullable Identifier style, CallbackInfo ci) { + + float scaledX = xo - (float) xo * Visual.tooltipSize; + float scaledY = yo - (float) yo * Visual.tooltipSize; + + pose.translate(scaledX, scaledY); pose.scale(Visual.tooltipSize); } - @ModifyArgs(method = "tooltip", at= @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;positionTooltip(IIIIII)Lorg/joml/Vector2ic;")) + @ModifyArgs(method = "tooltip", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;positionTooltip(IIIIII)Lorg/joml/Vector2ic;")) private void scaleUpTooltip(Args args) { - //Yeah, this is a bad way to do this, but I'm lazy - - int sw = args.get(0); - int sh = args.get(1); - int x = args.get(2); - int y = args.get(3); int w = args.get(4); int h = args.get(5); - float scaledSW = (float)sw / Visual.tooltipSize; - float scaledSH = (float)sh / Visual.tooltipSize; - float scaledX = (float)x / Visual.tooltipSize; - float scaledY = (float)y / Visual.tooltipSize; - float scaledW = (float)w / Visual.tooltipSize; - float scaledH = (float)h / Visual.tooltipSize; - - args.set(0, (int)scaledSW); - args.set(1, (int)scaledSH); - args.set(2, (int)scaledX); - args.set(3, (int)scaledY); - args.set(4, (int)scaledW); - args.set(5, (int)scaledH); + float scaledW = (float) w * Visual.tooltipSize; + float scaledH = (float) h * Visual.tooltipSize; + + args.set(4, (int) scaledW); + args.set(5, (int) scaledH); } } @@ -424,7 +424,7 @@ public class Config { ConfigSection toolTip = new ConfigSection(Component.literal("ToolTips")); toolTip.add(new ConfigBool(Component.literal("Item quality"), () -> Visual.itemQuality, bool -> Visual.itemQuality = bool)); toolTip.add(new ConfigBool(Component.literal("Pet candy"), () -> Visual.petCandy, bool -> Visual.petCandy = bool)); - toolTip.add(new ConfigFloat(Component.literal("Tooltip size"), () -> Visual.tooltipSize, num -> Visual.tooltipSize = num, 0.1f, 0.5f, 2)); + toolTip.add(new ConfigFloat(Component.literal("Tooltip size"), () -> Visual.tooltipSize, num -> Visual.tooltipSize = num, 0.01f, 0.25f, 2)); visual.add(toolTip); visual.add(new ConfigBool(Component.literal("Hide non crits"), () -> Visual.hideNoneCrits, bool -> Visual.hideNoneCrits = bool)); |
- added temp debug message and added some blocked items查看变更src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) @@ -1,19 +1,22 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; public class RerollBlocker { + //,"Emerald", "Diamond", "Gold", "Wood" private static final String[] CHESTS = {"Bedrock", "Obsidian"}; - private static final String[] BLOCKED_REROLLS = {"Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Wither Helmet"}; + private static final String[] BLOCKED_REROLLS = {"Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Star", "Claymore"}; private static boolean blockClick = false; private static int containerId = Integer.MIN_VALUE; @@ -50,14 +53,20 @@ public class RerollBlocker { Component component = itemStack.getCustomName(); if (component == null) return false; - if (isBlockedReroll(component.getString())) blockClick = true; + String blocked = getBlockedItem(component.getString()); + if (blocked != null) { + blockClick = true; + Misc.addChatMessage(Component.literal("Blocked reroll {name: " + blocked + "} {Item name: " + component.getString() + "}")); + } + } return false; }); - Events.ON_SLOT_CLICKED.register((slot, slotId, _, _) -> { + Events.ON_SLOT_CLICKED.register((slot, slotId, _, containerInput) -> { if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; + if (containerInput == ContainerInput.QUICK_MOVE) return false; if (slotId != 50 || slot.getItem().getItem() != Items.FEATHER) return false; ItemStack itemStack = slot.getItem(); @@ -78,11 +87,11 @@ public class RerollBlocker { return false; } - private static boolean isBlockedReroll(String itemName) { + private static String getBlockedItem(String itemName) { for (String name : BLOCKED_REROLLS) { - if (name.contains(itemName)) return true; + if (name.contains(itemName)) return name; } - return false; + return null; } } |
- added block expensive rerolls查看变更src/main/java/blade/addon/Bladeaddons.java | 1 + src/main/java/blade/addon/features/dungeon/RerollBlocker.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 1 + src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ 4 files changed, 93 insertions(+) @@ -112,5 +112,6 @@ public class Bladeaddons implements ModInitializer { ToolTip.init(); CompactDamageNumbers.init(); LoadoutData.init(); + RerollBlocker.init(); } } \ No newline at end of file @@ -0,0 +1,88 @@ +package blade.addon.features.dungeon; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.events.Events; +import net.minecraft.client.gui.screens.inventory.ContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; +import net.minecraft.world.inventory.ChestMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; + +public class RerollBlocker { + + private static final String[] CHESTS = {"Bedrock", "Obsidian"}; + private static final String[] BLOCKED_REROLLS = {"Wither Shield", "Implosion", "Shadow Warp", "Necron's Handle", "Wither Helmet"}; + + private static boolean blockClick = false; + private static int containerId = Integer.MIN_VALUE; + + public static void init() { + + Events.ON_SCREEN.register(screen -> { + if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; + + blockClick = false; + containerId = Integer.MIN_VALUE; + + if (screen instanceof ContainerScreen containerScreen) { + + Component title = containerScreen.getTitle(); + if (title == null) return false; + + if (!isValidGUI(title.getString())) return false; + + ChestMenu menu = containerScreen.getMenu(); + containerId = menu.containerId; + } + return false; + }); + + Events.ON_PACKET.register(packet -> { + if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; + + if (blockClick) return false; + if (packet instanceof ClientboundContainerSetSlotPacket containerSetSlotPacket) { + if (containerSetSlotPacket.getContainerId() != containerId) return false; + + ItemStack itemStack = containerSetSlotPacket.getItem(); + Component component = itemStack.getCustomName(); + if (component == null) return false; + + if (isBlockedReroll(component.getString())) blockClick = true; + } + + return false; + }); + + Events.ON_SLOT_CLICKED.register((slot, slotId, _, _) -> { + if (!Dungeons.blockExpensiveRerolls || !Location.in(Location.DUNGEON_HUB)) return false; + if (slotId != 50 || slot.getItem().getItem() != Items.FEATHER) return false; + + ItemStack itemStack = slot.getItem(); + Component customName = itemStack.getCustomName(); + if (customName == null) return false; + + if (!customName.getString().contains("Reroll Chest")) return false; + + return blockClick; + }); + + } + + private static boolean isValidGUI(String title) { + for (String name : CHESTS) { + if (name.equalsIgnoreCase(title)) return true; + } + return false; + } + + private static boolean isBlockedReroll(String itemName) { + for (String name : BLOCKED_REROLLS) { + if (name.contains(itemName)) return true; + } + return false; + } + +} @@ -119,6 +119,7 @@ public class Config { chests.add(new ConfigBool(Component.literal("Only display after run is over"), () -> Dungeons.onlyAfterRunOver, bool -> Dungeons.onlyAfterRunOver = bool)); chests.add(new ConfigBool(Component.literal("Send chest count warning"), () -> Dungeons.sendChestWarning, bool -> Dungeons.sendChestWarning = bool)); chests.add(new ConfigInt(Component.literal("Warning at chest"), () -> Dungeons.chestWarningCount, num -> Dungeons.chestWarningCount = num, 1, 1, 60)); + chests.add(new ConfigBool(Component.literal("Block expensive rerolls"), () -> Dungeons.blockExpensiveRerolls, bool -> Dungeons.blockExpensiveRerolls = bool)); dungeons.add(chests); dungeons.add(new ConfigBool(Component.literal("Leap message"), () -> Dungeons.enableLeapMessages, bool -> Dungeons.enableLeapMessages = bool)); @@ -168,4 +168,7 @@ public class Dungeons { @ConfigValue public static SoundData invincibilitySound = new SoundData(SoundEvents.NOTE_BLOCK_PLING.value(), 0, 1); + + @ConfigValue + public static boolean blockExpensiveRerolls = false; } |
- removed wither essence fix (was fixed by admins so not needed) - fixed key notification - fixed compactNumbers not working with overload - hopefully fixed relics not working when holding a term查看变更src/main/java/blade/addon/features/dungeon/KeyNotification.java | 63 ++++++++++++++++++++++----------------------------------------- src/main/java/blade/addon/features/dungeon/f7/relic/RelicSpawn.java | 4 ++-- src/main/java/blade/addon/features/other/CompactDamageNumbers.java | 7 ++++--- src/main/java/blade/addon/mixin/SkullBlockRendererMixin.java | 44 -------------------------------------------- src/main/java/blade/addon/utils/config/Config.java | 1 - src/main/java/blade/addon/utils/config/values/Visual.java | 3 --- src/main/resources/assets/blade-addons/textures/entity/essence.png | Bin 1018 -> 0 bytes src/main/resources/blade-addons.mixins.json | 3 +-- 8 files changed, 29 insertions(+), 96 deletions(-) @@ -9,18 +9,11 @@ import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDCategory; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.ResolvableProfile; import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,15 +22,9 @@ public class KeyNotification extends CombineableNotification { private final static Component BLOOD_KEY = Component.literal("§l§cBlood Key Dropped"); private final static Component WITHER_KEY = Component.literal("§l§7Wither Key Dropped"); - //Thanks to mio for this key detection system - private final static String WITHER_UUID = "2865274b-3097-394e-8149-ec629c72d850"; - private final static String BLOOD_UUID = "73f6d1f9-df41-3d1d-b98c-e1442d915885"; - private final static Pattern AUTOMATIC_PICKUP_PATTERN = Pattern.compile("A (Wither|Blood) Key was picked up!"); private final static Pattern NORMAL_PICKUP_PATTERN = Pattern.compile("has obtained (Wither|Blood) Key!"); - private final CopyOnWriteArrayList<Entity> foundKeys = new CopyOnWriteArrayList<>(); - private boolean hasKey = false; private boolean isBloodKey = false; @@ -46,38 +33,33 @@ public class KeyNotification extends CombineableNotification { } public void init() { - ClientTickEvents.END_LEVEL_TICK.register((world) -> { - if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier || Phase.inBoss()) return; - - for (Entity entity : world.entitiesForRendering()) { - if (entity instanceof ArmorStand armorStand && !foundKeys.contains(entity)) { - ItemStack head = armorStand.getItemBySlot(EquipmentSlot.HEAD); - ResolvableProfile profile = head.get(DataComponents.PROFILE); - if (profile == null) continue; - String uuid = profile.partialProfile().id().toString(); - if (uuid == null) continue; - - if (uuid.equals(WITHER_UUID)) { - foundKeys.add(entity); - hasKey = true; - if (isValidClass()) { - Scheduler.scheduleSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0.5f); - } - return; - } - if (uuid.equals(BLOOD_UUID)) { - foundKeys.add(entity); - isBloodKey = true; - hasKey = true; + Events.ON_ENTITY_TRACKED.register((entity, _) -> { + if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier || Phase.inBoss()) return false; + + if (entity instanceof ArmorStand possibleKey) { + + Component customName = possibleKey.getCustomName(); + if (customName == null) return false; - if (isValidClass()) { - Scheduler.scheduleSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0.5f); - } - return; + String name = customName.getString(); + if (name.equals("Wither Key")) { + hasKey = true; + if (isValidClass()) { + Scheduler.scheduleSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0.5f); + } + } else if (name.equals("Blood Key")) { + isBloodKey = true; + hasKey = true; + + if (isValidClass()) { + Scheduler.scheduleSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0.5f); } } + } + + return false; }); Events.ON_GAME_MESSAGE.register(message -> { @@ -104,7 +86,6 @@ public class KeyNotification extends CombineableNotification { if (Location.inDungeon()) { isBloodKey = false; hasKey = false; - foundKeys.clear(); } return false; }); @@ -76,7 +76,7 @@ public class RelicSpawn { return false; }); - Events.ON_LOCATION_CHANGE.register(newLocation -> { + Events.ON_LOCATION_CHANGE.register(_ -> { if (Location.inDungeon()) { reset(); } @@ -158,7 +158,7 @@ public class RelicSpawn { if (!isARelicPos(pos)) return false; //skyblock menu check is there incase the item doesnt get updated - if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu")) { + if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu") && !ItemUtil.itemHasName(itemStack, "Arrow")) { if (Floor7.blockIncorrectRelicPlace) { Debug.sendDebugMessage(Component.literal("Name: " + itemStack.getHoverName() + " Item: " + itemStack)); Misc.addChatMessage(Component.literal("Blocked a weird click")); @@ -14,7 +14,7 @@ import java.util.regex.Pattern; public class CompactDamageNumbers { - private static final Pattern DAMAGE_PATTERN = Pattern.compile("^✧?((?:\\d+,?)*)✧?❤?$"); + private static final Pattern DAMAGE_PATTERN = Pattern.compile("^✧?✯?((?:\\d+,?)*)✧?✯?❤?$"); private static final String[] CRIT_COLORS = {"§e", "§f", "§c", "§6"}; @@ -33,7 +33,7 @@ public class CompactDamageNumbers { if (!matcher.find()) return false; String numFound = matcher.group(1); - boolean isCrit = name.contains("✧"); + boolean isCrit = name.contains("✧") || name.contains("✯"); boolean loveHit = name.contains("❤"); if ((isCrit && Visual.hideCrits) || (!isCrit && Visual.hideNoneCrits)) { @@ -44,7 +44,8 @@ public class CompactDamageNumbers { String formatted = compact(numFound); if (isCrit) { - formatted = "✧ " + formatted + " ✧"; + char symbol = name.charAt(0); + formatted = symbol + " " + formatted + " " + symbol; formatted = styleCrit(formatted); if (loveHit) formatted += " §d❤"; target.setCustomName(Component.literal(formatted)); @@ -1,44 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.utils.Constants; -import blade.addon.utils.config.values.Visual; -import com.mojang.authlib.GameProfile; -import net.minecraft.client.renderer.blockentity.SkullBlockRenderer; -import net.minecraft.client.renderer.rendertype.RenderType; -import net.minecraft.resources.Identifier; -import net.minecraft.world.item.component.ResolvableProfile; -import net.minecraft.world.level.block.SkullBlock; -import net.minecraft.world.level.block.entity.SkullBlockEntity; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(SkullBlockRenderer.class) -public abstract class SkullBlockRendererMixin { - - @Unique - private static final Identifier ESSENCE_TEXTURE = Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "/textures/entity/essence.png"); - - @Shadow - public static RenderType getSkullRenderType(SkullBlock.Type type, @Nullable Identifier texture) { - return null; - } - - @Inject(method = "resolveSkullRenderType", at = @At("HEAD"), cancellable = true) - private void renderEssence(SkullBlock.Type skullType, SkullBlockEntity blockEntity, CallbackInfoReturnable<RenderType> cir) { - if (!Visual.fixWitherEssence || skullType != SkullBlock.Types.PLAYER) return; - - ResolvableProfile profileComponent = blockEntity.getOwnerProfile(); - if (profileComponent == null) return; - - GameProfile profile = profileComponent.partialProfile(); - - if (profile.id().toString().equals("e0f3e929-869e-3dca-9504-54c666ee6f23")) { - cir.setReturnValue(getSkullRenderType(SkullBlock.Types.PLAYER, ESSENCE_TEXTURE)); - } - } -} @@ -416,7 +416,6 @@ public class Config { visual.add(new ConfigBool(Component.literal("Compact hoppity messages"), () -> Visual.compactHoppityMsgs, bool -> Visual.compactHoppityMsgs = bool)); visual.add(new ConfigBool(Component.literal("Hide cooldown"), () -> Visual.hideCooldown, bool -> Visual.hideCooldown = bool)); visual.add(new ConfigBool(Component.literal("Old player head size"), () -> Visual.oldPlayerHead, bool -> Visual.oldPlayerHead = bool)); - visual.add(new ConfigBool(Component.literal("Fix wither essence"), () -> Visual.fixWitherEssence, bool -> Visual.fixWitherEssence = bool)); visual.add(new ConfigBool(Component.literal("1.8.9 like fishing bobber"), () -> Visual.oldFishingRod, bool -> Visual.oldFishingRod = bool)); visual.add(new ConfigBool(Component.literal("Stop shovel swing when flattening dirt"), () -> Visual.stopShovelFlattening, bool -> Visual.stopShovelFlattening = bool)); visual.add(new ConfigBool(Component.literal("Stop swinging when throwing a pearl"), () -> Visual.stopPearlSwing, bool -> Visual.stopPearlSwing = bool)); @@ -40,9 +40,6 @@ public class Visual { @ConfigValue public static boolean oldPlayerHead = false; - @ConfigValue - public static boolean fixWitherEssence = false; - @ConfigValue public static boolean oldFishingRod = false; @@ -39,7 +39,6 @@ "MouseHandlerMixin", "MultiPlayerGameModeMixin", "RecipeBookComponentMixin", - "RecipeBookScreenMixin", - "SkullBlockRendererMixin" + "RecipeBookScreenMixin" ] } \ No newline at end of file |
- added compact damage numbers - added hide non crit and crit - added loadout display, notification and sound查看变更src/main/java/blade/addon/Bladeaddons.java | 3 +++ src/main/java/blade/addon/features/other/CompactDamageNumbers.java | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/SwingAnimation.java | 1 - src/main/java/blade/addon/features/other/loadout/LoadoutData.java | 46 +++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/loadout/LoadoutDisplay.java | 51 +++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/loadout/LoadoutNotification.java | 35 ++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 12 +++++++++- src/main/java/blade/addon/utils/config/components/Components.java | 10 +++++++- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 10 ++++++++ src/main/java/blade/addon/utils/config/values/Visual.java | 9 ++++++++ 10 files changed, 273 insertions(+), 3 deletions(-) @@ -20,6 +20,7 @@ import blade.addon.features.item.*; import blade.addon.features.notifications.Notifications; import blade.addon.features.other.*; import blade.addon.features.other.arrow.ArrowSwapper; +import blade.addon.features.other.loadout.LoadoutData; import blade.addon.features.other.pet.SelectedPet; import blade.addon.features.sound.BonzoSound; import blade.addon.features.sound.TubaSound; @@ -109,5 +110,7 @@ public class Bladeaddons implements ModInitializer { DeathMessage.init(); BlockPetMenu.init(); ToolTip.init(); + CompactDamageNumbers.init(); + LoadoutData.init(); } } \ No newline at end of file @@ -0,0 +1,99 @@ +package blade.addon.features.other; + +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.Style; +import net.minecraft.world.entity.decoration.ArmorStand; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CompactDamageNumbers { + + private static final Pattern DAMAGE_PATTERN = Pattern.compile("^✧?((?:\\d+,?)*)✧?❤?$"); + + private static final String[] CRIT_COLORS = {"§e", "§f", "§c", "§6"}; + + public static void init() { + + Events.ON_ENTITY_TRACKED.register((entity, _) -> { + + if (entity instanceof ArmorStand target) { + if (!target.hasCustomName() || !target.isCustomNameVisible()) return false; + + Component component = target.getCustomName(); + assert component != null; + String name = component.getString(); + + Matcher matcher = DAMAGE_PATTERN.matcher(name); + if (!matcher.find()) return false; + + String numFound = matcher.group(1); + boolean isCrit = name.contains("✧"); + boolean loveHit = name.contains("❤"); + + if ((isCrit && Visual.hideCrits) || (!isCrit && Visual.hideNoneCrits)) { + target.setCustomNameVisible(false); + return false; + + } else if (Visual.compactDamage) { + String formatted = compact(numFound); + + if (isCrit) { + formatted = "✧ " + formatted + " ✧"; + formatted = styleCrit(formatted); + if (loveHit) formatted += " §d❤"; + target.setCustomName(Component.literal(formatted)); + + } else { + MutableComponent newNum = Component.literal(formatted); + Style style = getStyle(component); + if (style != null) { + newNum.setStyle(style); + } + target.setCustomName(newNum); + + } + } + } + + return false; + }); + } + + private static String compact(String numFound) { + String numOnly = numFound.replace(",", ""); + + try { + float num = Float.parseFloat(numOnly); + return RenderUtils.formatNumber(num); + } catch (NumberFormatException e) { + return numFound; + } + } + + private static Style getStyle(Component component) { + List<Component> siblings = component.getSiblings(); + if (siblings.isEmpty()) return null; + return siblings.getFirst().getStyle(); + } + + private static String styleCrit(String crit) { + StringBuilder styledCrit = new StringBuilder(); + int cnt = 0; + for (char c : crit.toCharArray()) { + if (c != ' ') { + styledCrit.append(CRIT_COLORS[cnt % CRIT_COLORS.length]); + cnt ++; + } + styledCrit.append(c); + } + + return styledCrit.toString(); + } + +} @@ -20,7 +20,6 @@ public class SwingAnimation { public static void consumeSwing() { if (ignoreCount > 0) { ignoreCount--; - System.out.println("Consumed a swing, now at count: " + ignoreCount); } } @@ -0,0 +1,46 @@ +package blade.addon.features.other.loadout; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LoadoutData { + + private static final Pattern LOADOUT_PATTERN = Pattern.compile("^You equipped (.+)!$"); + + private static final long DURATION = 1000; + + private static String current = "Unknown"; + private static long prevTime = 0; + + public static void init() { + + Events.ON_GAME_MESSAGE.register(text -> { + + if (!ExtraOptions.enableLoadoutDisplay) return false; + + String string = text.getString(); + Matcher matcher = LOADOUT_PATTERN.matcher(string); + if (!matcher.find()) return false; + + current = matcher.group(1); + prevTime = System.currentTimeMillis(); + Misc.sendSound(ExtraOptions.loadoutSound); + + return false; + }); + + } + + public static String getCurrentLoadout() { + return current; + } + + public static boolean shouldDisplayNotification() { + return System.currentTimeMillis() - prevTime < DURATION; + } + +} @@ -0,0 +1,51 @@ +package blade.addon.features.other.loadout; + +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; +import config.practical.hud.HUDComponent; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class LoadoutDisplay extends HUDComponent { + + public LoadoutDisplay() { + super("Loadout display"); + } + + @Override + public int getWidth() { + return 110; + } + + @Override + public int getHeight() { + return 10; + } + + @Override + public boolean editable() { + return ExtraOptions.enableLoadoutDisplay; + } + + @Override + public boolean shouldRender() { + return ExtraOptions.enableLoadoutDisplay; + } + + @Override + public List<HUDCategory> categories() { + return null; + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { + Font textRenderer = Minecraft.getInstance().font; + if (textRenderer == null) return; + RenderUtils.drawPrefixedText(this, guiGraphicsExtractor, "Loadout", LoadoutData.getCurrentLoadout()); + } +} @@ -0,0 +1,35 @@ +package blade.addon.features.other.loadout; + +import blade.addon.utils.config.components.CombineableNotification; +import blade.addon.utils.config.values.ExtraOptions; +import config.practical.hud.HUDCategory; +import net.minecraft.network.chat.Component; + +import java.util.List; + +public class LoadoutNotification extends CombineableNotification { + + public LoadoutNotification() { + super("Loadout notification"); + } + + @Override + public boolean enabled() { + return ExtraOptions.enableLoadoutNotification; + } + + @Override + public Component getText() { + return Component.literal("§a" + LoadoutData.getCurrentLoadout()); + } + + @Override + public boolean shouldRender() { + return LoadoutData.shouldDisplayNotification(); + } + + @Override + public List<HUDCategory> categories() { + return null; + } +} @@ -390,8 +390,14 @@ public class Config { ss.add(new ConfigDouble(Component.literal("Lucky button rng (0.1)"), () -> ExtraOptions.luckyButtonRng, num -> ExtraOptions.luckyButtonRng = num, 0.01, 0, 1)); ss.add(new ConfigColor(Component.literal("Lucky button color"), () -> ExtraOptions.luckyButtonColor, color -> ExtraOptions.luckyButtonColor = color, "lucky-button-color", true)); ss.add(new ConfigSound(Component.literal("Button sound"), ExtraOptions.ssSound)); - extra.add(ss); + + ConfigSection loadout = new ConfigSection(Component.literal("Loadout")); + loadout.add(new ConfigBool(Component.literal("Enable display"), () -> ExtraOptions.enableLoadoutDisplay, bool -> ExtraOptions.enableLoadoutDisplay = bool)); + loadout.add(new ConfigBool(Component.literal("Enable notification"), () -> ExtraOptions.enableLoadoutNotification, bool -> ExtraOptions.enableLoadoutNotification = bool)); + loadout.add(new ConfigSound(Component.literal("Loadout swap sound"), ExtraOptions.loadoutSound)); + extra.add(loadout); + return extra; } @@ -421,6 +427,10 @@ public class Config { toolTip.add(new ConfigFloat(Component.literal("Tooltip size"), () -> Visual.tooltipSize, num -> Visual.tooltipSize = num, 0.1f, 0.5f, 2)); visual.add(toolTip); + visual.add(new ConfigBool(Component.literal("Hide non crits"), () -> Visual.hideNoneCrits, bool -> Visual.hideNoneCrits = bool)); + visual.add(new ConfigBool(Component.literal("Hide crits"), () -> Visual.hideCrits, bool -> Visual.hideCrits = bool)); + visual.add(new ConfigBool(Component.literal("Compact damage numbers"), () -> Visual.compactDamage, bool -> Visual.compactDamage = bool)); + return visual; } @@ -22,6 +22,8 @@ import blade.addon.features.notifications.NotificationDisplay; import blade.addon.features.other.*; import blade.addon.features.other.arrow.ArrowDisplay; import blade.addon.features.other.arrow.ArrowNotification; +import blade.addon.features.other.loadout.LoadoutDisplay; +import blade.addon.features.other.loadout.LoadoutNotification; import blade.addon.features.other.pet.PetDisplay; import blade.addon.features.other.pet.PetNotification; import config.practical.hud.HUDComponent; @@ -99,12 +101,15 @@ public class Components { @ConfigValue public static CombineableNotification bloodNotificationDisplay = new BloodNotification(); + @ConfigValue + public static CombineableNotification loadoutNotification = new LoadoutNotification(); + @ConfigValue public static HUDComponent combinedNotifications = new CombinedNotification( duplicateClassDisplay, keyNotifierDisplay, pre4Notification, melodyNotification, stormCrushNotification, crystalReminderNotification, chatNotification, petTitleNotification, arrowSwapDisplay, - sectionCompletionDisplay, bloodNotificationDisplay); + sectionCompletionDisplay, bloodNotificationDisplay, loadoutNotification); @ConfigValue public static HUDComponent relicProgressBar = new RelicProgressBar(); @@ -159,4 +164,7 @@ public class Components { @ConfigValue public static HUDComponent stormLbTimer = new StormLBTimer(); + + @ConfigValue + public static HUDComponent LoadoutDisplay = new LoadoutDisplay(); } @@ -144,4 +144,14 @@ public class ExtraOptions { @ConfigValue public static boolean formatMathResult = true; + + @ConfigValue + public static boolean enableLoadoutDisplay = false; + + @ConfigValue + public static boolean enableLoadoutNotification = false; + + @ConfigValue + public static SoundData loadoutSound = new SoundData(SoundEvents.NOTE_BLOCK_PLING.value(), 0, 1); + } @@ -64,4 +64,13 @@ public class Visual { @ConfigValue public static float tooltipSize = 1; + @ConfigValue + public static boolean hideNoneCrits = false; + + @ConfigValue + public static boolean hideCrits = false; + + @ConfigValue + public static boolean compactDamage = false; + } |
- added scaleable tooltips查看变更src/main/java/blade/addon/mixin/GuiGraphicsExtractorMixin.java | 44 ++++++++++++++++++++++++++++++++++++++++++-- src/main/java/blade/addon/utils/config/Config.java | 2 ++ src/main/java/blade/addon/utils/config/values/Visual.java | 3 +++ 3 files changed, 47 insertions(+), 2 deletions(-) @@ -1,18 +1,27 @@ package blade.addon.mixin; import blade.addon.utils.config.values.Visual; +import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner; +import net.minecraft.resources.Identifier; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.joml.Matrix3x2fStack; +import org.jspecify.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArgs; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.invoke.arg.Args; + +import java.util.List; @Mixin(GuiGraphicsExtractor.class) public class GuiGraphicsExtractorMixin { @@ -20,8 +29,7 @@ public class GuiGraphicsExtractorMixin { @Final @Shadow private Matrix3x2fStack pose; - - + @ModifyVariable(method = "itemCooldown", at=@At("STORE"), ordinal = 0) private float noCooldown(float f) { return Visual.hideCooldown? 0: f; @@ -46,4 +54,36 @@ public class GuiGraphicsExtractorMixin { } } + @Inject(method = "tooltip", at= @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;pushMatrix()Lorg/joml/Matrix3x2fStack;")) + private void scaleUpTooltip_head(Font font, List<ClientTooltipComponent> lines, int xo, int yo, ClientTooltipPositioner positioner, @Nullable Identifier style, CallbackInfo ci) { + pose.scale(Visual.tooltipSize); + } + + @ModifyArgs(method = "tooltip", at= @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;positionTooltip(IIIIII)Lorg/joml/Vector2ic;")) + private void scaleUpTooltip(Args args) { + + //Yeah, this is a bad way to do this, but I'm lazy + + int sw = args.get(0); + int sh = args.get(1); + int x = args.get(2); + int y = args.get(3); + int w = args.get(4); + int h = args.get(5); + + float scaledSW = (float)sw / Visual.tooltipSize; + float scaledSH = (float)sh / Visual.tooltipSize; + float scaledX = (float)x / Visual.tooltipSize; + float scaledY = (float)y / Visual.tooltipSize; + float scaledW = (float)w / Visual.tooltipSize; + float scaledH = (float)h / Visual.tooltipSize; + + args.set(0, (int)scaledSW); + args.set(1, (int)scaledSH); + args.set(2, (int)scaledX); + args.set(3, (int)scaledY); + args.set(4, (int)scaledW); + args.set(5, (int)scaledH); + } + } @@ -20,6 +20,7 @@ import config.practical.widgets.*; import config.practical.widgets.color.ConfigColor; import config.practical.widgets.options.ConfigOptions; import config.practical.widgets.sliders.ConfigDouble; +import config.practical.widgets.sliders.ConfigFloat; import config.practical.widgets.sliders.ConfigInt; import config.practical.widgets.sound.ConfigSound; import net.minecraft.client.Minecraft; @@ -417,6 +418,7 @@ public class Config { ConfigSection toolTip = new ConfigSection(Component.literal("ToolTips")); toolTip.add(new ConfigBool(Component.literal("Item quality"), () -> Visual.itemQuality, bool -> Visual.itemQuality = bool)); toolTip.add(new ConfigBool(Component.literal("Pet candy"), () -> Visual.petCandy, bool -> Visual.petCandy = bool)); + toolTip.add(new ConfigFloat(Component.literal("Tooltip size"), () -> Visual.tooltipSize, num -> Visual.tooltipSize = num, 0.1f, 0.5f, 2)); visual.add(toolTip); return visual; @@ -61,4 +61,7 @@ public class Visual { @ConfigValue public static boolean petCandy = false; + @ConfigValue + public static float tooltipSize = 1; + } |
- fixed goldor color - fixed hide player查看变更gradle.properties | 2 +- src/main/java/blade/addon/features/dungeon/HidePlayers.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 2 +- src/main/java/blade/addon/features/other/PracticeSS.java | 10 ++++++---- 4 files changed, 9 insertions(+), 7 deletions(-) @@ -9,7 +9,7 @@ minecraft_version=26.1.2 loader_version=0.19.3 loom_version=1.17-SNAPSHOT # Mod Properties -mod_version=2.5.2 +mod_version=2.5.3 maven_group=blade.addon archives_base_name=blade-addons # Dependencies @@ -57,7 +57,7 @@ public class HidePlayers { } public static boolean shouldHidePlayers(Player player) { - if (!Location.inDungeon() || !EntityUtil.isARealPlayer(player) || EntityUtil.isClientPlayer(player) || Phase.runStarted()) return false; + if (!Location.inDungeon() || !EntityUtil.isARealPlayer(player) || EntityUtil.isClientPlayer(player)) return false; if (testHideAtLeap()) { return true; @@ -50,7 +50,7 @@ public class GoldorTickTimer extends CombineableTickTimer { @Override public int getColor() { - double mod = getTime(); + double mod = getTime() % 3; return (mod < 1 ? Constants.GREEN : mod < 2 ? Constants.GOLD : Constants.RED); } @@ -47,11 +47,13 @@ public class PracticeSS { private static final int UNLUCKY_DURATION = 36; private static final int START_WAIT_DURATION = 6; + private static final int PHASES = 4; + private static boolean started = false; private static boolean showingPattern = false; private static int currentIndex = 0; - private static int endIndex = 4; + private static int endIndex = 3; private static int ticksLeft = 0; private static int totalTicks = 0; @@ -68,7 +70,7 @@ public class PracticeSS { public static void init() { - Events.ON_BLOCK_INTERACTION.register((BlockHitResult result, ItemStack item) -> { + Events.ON_BLOCK_INTERACTION.register((BlockHitResult result, ItemStack _) -> { if (!ExtraOptions.practiceSSAnywhere && !Location.in(Location.PRIVATE_ISLAND)) return false; ClientLevel world = Minecraft.getInstance().level; if (world == null) return false; @@ -113,7 +115,7 @@ public class PracticeSS { }); RenderingEvents.FILLED.register(PracticeSS::render); - Events.ON_LOCATION_CHANGE.register(location -> { + Events.ON_LOCATION_CHANGE.register(_ -> { reset(); return false; }); @@ -154,7 +156,7 @@ public class PracticeSS { Misc.sendSound(ExtraOptions.ssSound); - if (currentIndex == 5) { + if (currentIndex == PHASES) { recordTime(); } else if (currentIndex == endIndex) { incStage(); |
- overhauled hudcomponents (added categories, needs testing) - updated gradle查看变更build.gradle | 16 ++-----
gradle.properties | 4 +-
gradle/wrapper/gradle-wrapper.jar | Bin 45457 -> 47505 bytes
gradle/wrapper/gradle-wrapper.properties | 7 ++-
gradlew | 6 +--
gradlew.bat | 35 +++++---------
src/main/java/blade/addon/Bladeaddons.java | 51 +++++---------------
src/main/java/blade/addon/features/dungeon/{BloodNotifier.java => BloodNotification.java} | 49 ++++++++++++-------
src/main/java/blade/addon/features/dungeon/ChestCounter.java | 47 ++++++++++++++----
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 6 +--
src/main/java/blade/addon/features/dungeon/{KeyNotifier.java => KeyNotification.java} | 50 +++++++++++--------
src/main/java/blade/addon/features/dungeon/QuizTimer.java | 49 +++++++++++++++----
src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 68 +++++++++++++++-----------
src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 44 +++++++++++++----
src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 67 ++++++++++++++++++++++----
src/main/java/blade/addon/features/dungeon/f7/StormLBTimer.java | 55 ++++++++++++++++-----
src/main/java/blade/addon/features/dungeon/f7/dragons/{DragSpawnTimer.java => DragonSpawn.java} | 19 +++-----
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonSpawnTimer.java | 48 +++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonTracer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDisplay.java | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 49 +++++++++++++++----
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 102 +++++----------------------------------
src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 60 +++++++++++++++++------
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorStun.java | 47 ++++++++++++++----
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorTickTimer.java | 44 ++++++++++++++---
src/main/java/blade/addon/features/dungeon/f7/maxor/crystals/CrystalNotification.java | 36 ++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/maxor/{ => crystals}/CrystalSpawn.java | 23 ++-------
src/main/java/blade/addon/features/dungeon/f7/maxor/crystals/CrystalTimer.java | 43 +++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/relic/RelicProgressBar.java | 79 ++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/{RelicTimer.java => relic/RelicSpawn.java} | 91 +++++++----------------------------
src/main/java/blade/addon/features/dungeon/f7/relic/RelicTimer.java | 47 ++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/storm/DistanceToLedge.java | 57 ++++++++++++++++------
src/main/java/blade/addon/features/dungeon/f7/storm/StormDeathTime.java | 88 ++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/storm/StormTickTimer.java | 94 +++++++++++-------------------------
src/main/java/blade/addon/features/dungeon/f7/storm/StormTime.java | 38 +++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/storm/{ => pillar}/PillarExplode.java | 26 +---------
src/main/java/blade/addon/features/dungeon/f7/storm/pillar/PillarExplodeTimer.java | 50 +++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/storm/pillar/PillarNotification.java | 37 ++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/terms/CurrentSection.java | 45 ++++++++++++++---
src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 47 +++++++++++++-----
src/main/java/blade/addon/features/dungeon/f7/terms/{LeapNotification.java => LeapDisplay.java} | 73 +++++++++++++++++++---------
src/main/java/blade/addon/features/dungeon/f7/terms/{MelodyWarning.java => MelodyNotification.java} | 56 ++++++++++++++--------
src/main/java/blade/addon/features/dungeon/f7/terms/SectionCompleteNotification.java | 49 +++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/terms/SectionCompletion.java | 32 -------------
src/main/java/blade/addon/features/dungeon/f7/terms/SectionProgress.java | 88 +++++++++++++++++++++++-----------
src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 45 ++++++++++++-----
src/main/java/blade/addon/features/dungeon/f7/terms/device/DeviceNotification.java | 36 ++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/terms/{ => device}/DeviceNotifier.java | 18 ++-----
src/main/java/blade/addon/features/item/HeldItemToolTip.java | 51 +++++++++++++++-----
src/main/java/blade/addon/features/notifications/NotificationDisplay.java | 34 +++++++++++++
src/main/java/blade/addon/features/notifications/Notifications.java | 20 +++-----
src/main/java/blade/addon/features/other/KickedTimer.java | 40 ++++++++++++++--
src/main/java/blade/addon/features/other/RagDisplay.java | 42 +++++++++++++---
src/main/java/blade/addon/features/other/ReaperDisplay.java | 43 ++++++++++++++---
src/main/java/blade/addon/features/other/arrow/ArrowDisplay.java | 47 ++++++++++++++++++
src/main/java/blade/addon/features/other/arrow/ArrowNotification.java | 35 ++++++++++++++
src/main/java/blade/addon/features/other/{ => arrow}/ArrowSwapper.java | 23 ++-------
src/main/java/blade/addon/features/other/pet/PetDisplay.java | 67 ++++++++++++++++++++++++++
src/main/java/blade/addon/features/other/pet/PetNotification.java | 34 +++++++++++++
src/main/java/blade/addon/features/other/{ => pet}/SelectedPet.java | 51 ++++----------------
src/main/java/blade/addon/mixin/GuiMixin.java | 10 ++--
src/main/java/blade/addon/mixin/MultiPlayerGameModeMixin.java | 2 +-
src/main/java/blade/addon/utils/Location.java | 2 +-
src/main/java/blade/addon/utils/config/Config.java | 7 ++-
src/main/java/blade/addon/utils/config/components/Categories.java | 16 +++++++
src/main/java/blade/addon/utils/config/components/CombineableNotification.java | 47 ++++++++++++++++++
src/main/java/blade/addon/utils/config/components/CombineableTickTimer.java | 48 +++++++++++++++++++
src/main/java/blade/addon/utils/config/components/CombinedNotification.java | 79 ++++++++++++++++++++++++++++++
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 79 ------------------------------
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 94 +++++++++++++++++++++++-------------
src/main/java/blade/addon/utils/config/components/Components.java | 121 +++++++++++++++++++++++-----------------------
src/main/java/blade/addon/utils/config/values/Floor7.java | 4 +-
src/main/java/blade/addon/utils/debug/Debug.java | 35 ++++++--------
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 6 +--
src/main/java/blade/addon/utils/dungeon/Phase.java | 5 +-
src/main/java/blade/addon/utils/dungeon/Section.java | 5 +-
76 files changed, 2311 insertions(+), 997 deletions(-)@@ -34,31 +34,23 @@ loom { } repositories { - + mavenCentral() maven { url = "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" } maven { url = 'https://jitpack.io' } - maven { - name = "Terraformers" - url = "https://maven.terraformersmc.com/" - } + maven { url = "https://maven.terraformersmc.com/" } maven { url = 'https://repo.hypixel.net/repository/Hypixel/' } } dependencies { - // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - //mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" implementation "net.fabricmc:fabric-loader:${project.loader_version}" - - // Fabric API. This is technically optional, but you probably want it anyway. implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" - implementation("com.terraformersmc:modmenu:${project.modmenu_version}") include implementation("net.hypixel:mod-api:${project.hypixel_api_version}") include implementation("com.github.BladeMasterGabe:practical-config:${project.practical_config}") runtimeOnly("me.djtheredstoner:DevAuth-fabric:${project.dev_auth_version}") - + compileOnly("com.terraformersmc:modmenu:${project.modmenu_version}") } @@ -89,7 +81,7 @@ jar { inputs.property "projectName", projectName from("LICENSE") { - rename { "${it}_$projectName"} + rename { "${it}_$projectName" } } } @@ -13,9 +13,9 @@ mod_version=2.5.2 maven_group=blade.addon archives_base_name=blade-addons # Dependencies -fabric_api_version=0.152.1+26.1.2 +fabric_api_version=0.155.2+26.1.2 # I love dependencies sometimes breaking -practical_config=902a663c1b6c8917d02f12b7608eb373a9d3c1f3 +practical_config=757ad46ab1b257d494cc150261736b6f9b0e131c modmenu_version=18.0.0-beta.1 hypixel_api_version=1.0.2 dev_auth_version=1.2.2 @@ -1,6 +1,9 @@ -#Thu Jun 25 03:30:47 CEST 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip +networkTimeout=10000 +retries=0 +retryBackOffMs=500 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,29 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% @@ -3,28 +3,24 @@ package blade.addon; import blade.addon.features.dungeon.*; import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.PredevTimer; -import blade.addon.features.dungeon.f7.RelicTimer; -import blade.addon.features.dungeon.f7.StormLBTimer; -import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; import blade.addon.features.dungeon.f7.dragons.DragonHealth; +import blade.addon.features.dungeon.f7.dragons.DragonSpawn; import blade.addon.features.dungeon.f7.dragons.DragonTracer; -import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.invincibility.MaskHighlight; -import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.dungeon.f7.location.PositionMessages; -import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; -import blade.addon.features.dungeon.f7.maxor.MaxorStun; -import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; -import blade.addon.features.dungeon.f7.storm.DistanceToLedge; -import blade.addon.features.dungeon.f7.storm.PillarExplode; -import blade.addon.features.dungeon.f7.storm.StormTickTimer; -import blade.addon.features.dungeon.f7.terms.*; +import blade.addon.features.dungeon.f7.maxor.crystals.CrystalSpawn; +import blade.addon.features.dungeon.f7.relic.RelicSpawn; +import blade.addon.features.dungeon.f7.storm.StormTime; +import blade.addon.features.dungeon.f7.storm.pillar.PillarExplode; +import blade.addon.features.dungeon.f7.terms.device.DeviceNotifier; import blade.addon.features.filter.Filters; import blade.addon.features.highlight.*; import blade.addon.features.item.*; import blade.addon.features.notifications.Notifications; import blade.addon.features.other.*; +import blade.addon.features.other.arrow.ArrowSwapper; +import blade.addon.features.other.pet.SelectedPet; import blade.addon.features.sound.BonzoSound; import blade.addon.features.sound.TubaSound; import blade.addon.utils.Commands; @@ -33,6 +29,7 @@ import blade.addon.utils.Location; import blade.addon.utils.Scheduler; import blade.addon.utils.config.Config; import blade.addon.utils.config.FolderUtility; +import blade.addon.utils.config.components.Categories; import blade.addon.utils.config.components.Components; import blade.addon.utils.config.values.Buttons; import blade.addon.utils.data.EntityUtil; @@ -49,6 +46,7 @@ public class Bladeaddons implements ModInitializer { @Override public void onInitialize() { FolderUtility.init(); + Categories.init(); Components.init(); Buttons.init(); try { @@ -68,38 +66,25 @@ public class Bladeaddons implements ModInitializer { RenderingEvents.init(); - StormTickTimer.init(); - GoldorTickTimer.init(); - TermStartTimer.init(); + StormTime.init(); PositionMessages.init(); InvincibilityTimer.init(); - WarpCooldown.init(); LeapMessage.init(); ExplosiveShot.init(); - RunStartValidator.init(); HidePlayers.init(); CrystalSpawn.init(); - KeyNotifier.init(); - RelicTimer.init(); + RelicSpawn.init(); AutoRequeue.init(); MobHighlight.init(); - ChestCounter.init(); Scheduler.init(); - SecretSpawnTimer.init(); - DistanceToLedge.init(); ItemHighlight.init(); BossWaypoints.init(); DianaNotifier.init(); - DragSpawnTimer.init(); + DragonSpawn.init(); SelectedPet.init(); - LocationNotifier.init(); PredevTimer.init(); - KickedTimer.init(); DeviceNotifier.init(); PillarExplode.init(); - MelodyWarning.init(); - RagDisplay.init(); - LeapNotification.init(); PracticeSS.init(); CompactHoppity.init(); DropAnimation.init(); @@ -108,14 +93,10 @@ public class Bladeaddons implements ModInitializer { Notifications.init(); BatHighlight.init(); WitherHighlight.init(); - InvincibilityDuration.init(); TeammateHighlight.init(); - SectionProgress.init(); BonzoSound.init(); - QuizTimer.init(); Filters.init(); DragonHealth.init(); - MaxorStun.init(); ArrowSwapper.init(); StarCountHighlight.init(); MaskHighlight.init(); @@ -124,13 +105,7 @@ public class Bladeaddons implements ModInitializer { SelectedPetHighlight.init(); SearchBar.init(); TubaSound.init(); - SectionCompletion.init(); - MaxorTickTimer.init(); - BloodNotifier.init(); - CurrentSection.init(); DragonTracer.init(); - ReaperDisplay.init(); - StormLBTimer.init(); DeathMessage.init(); BlockPetMenu.init(); ToolTip.init(); @@ -1,23 +1,27 @@ package blade.addon.features.dungeon; -import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.config.components.CombineableNotification; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphicsExtractor; +import config.practical.hud.HUDCategory; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; -public class BloodNotifier { +import java.util.List; - private static boolean detected = false; - private static long prevTime = 0; +public class BloodNotification extends CombineableNotification { - public static void init() { + private boolean detected = false; + private long prevTime = 0; + + public BloodNotification() { + super("blood notification"); + } + + public void init() { Events.ON_GAME_MESSAGE.register(message -> { if (detected || !Location.inDungeon()) return false; @@ -35,26 +39,37 @@ public class BloodNotifier { return false; }); - Events.ON_LOCATION_CHANGE.register(newLocation -> { - reset(); + Events.ON_LOCATION_CHANGE.register(_ -> { + resetDetection(); return false; }); } - private static void reset() { + @Override + public boolean shouldRender() { + return Dungeons.alertBloodSpawns && System.currentTimeMillis() - prevTime < 2000 && correctClass(); + } + + @Override + public List<HUDCategory> categories() { + return List.of(); + } + + private void resetDetection() { detected = false; } - private static boolean correctClass() { + private boolean correctClass() { return Dungeons.alertBloodForAllClasses || DungeonClass.isClass(DungeonClass.MAGE); } - public static boolean display() { - return Dungeons.alertBloodSpawns && System.currentTimeMillis() - prevTime < 2000 && correctClass(); + @Override + public boolean enabled() { + return Dungeons.alertBloodSpawns; } - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { - RenderUtils.drawCenteredText(graphics, component, Component.literal("First four mobs spawned!"), Constants.RED); + @Override + public Component getText() { + return Component.literal("First four mobs spawned!"); } - } @@ -8,16 +8,19 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; import config.practical.hud.HUDComponent; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; +import org.jspecify.annotations.NonNull; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class ChestCounter { +public class ChestCounter extends HUDComponent { private static final Pattern PATTERN = Pattern.compile("^ Unclaimed chests: (\\d+)$"); @@ -25,8 +28,12 @@ public class ChestCounter { private static int countedChests = 0; private static boolean hasUpdatedData = false; - public static void init() { - Events.ON_LOCATION_CHANGE.register(newLocation -> { + public ChestCounter() { + super("Chest count"); + } + + public void init() { + Events.ON_LOCATION_CHANGE.register(_ -> { if (Location.in(Location.DUNGEON_HUB)) { hasUpdatedData = false; } @@ -62,19 +69,41 @@ public class ChestCounter { }); } - public static boolean display() { + @Override + public int getWidth() { + return 110; + } + + @Override + public int getHeight() { + return 10; + } + + @Override + public boolean editable() { + return Dungeons.displayChestCount; + } + + @Override + public boolean shouldRender() { if ((Dungeons.onlyAfterRunOver && !Phase.runOver())) return false; return Dungeons.displayChestCount && Location.inDungeon(); } - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { - int x = component.getScaledX(); - int y = component.getScaledY(); + @Override + public List<HUDCategory> categories() { + return null; + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { + int x = getScaledX(); + int y = getScaledY(); if (hasUpdatedData) { - RenderUtils.drawPrefixedText(component, graphics, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); + RenderUtils.drawPrefixedText(this, guiGraphicsExtractor, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); } else { - graphics.text(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); + guiGraphicsExtractor.text(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); } } @@ -1,6 +1,6 @@ package blade.addon.features.dungeon; -import blade.addon.features.dungeon.f7.terms.DeviceNotifier; +import blade.addon.features.dungeon.f7.terms.device.DeviceNotifier; import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.data.EntityUtil; @@ -19,7 +19,7 @@ public class HidePlayers { public static void init() { - Events.ON_LEAP.register(message -> { + Events.ON_LEAP.register(_ -> { justLeapt = true; startTime = System.currentTimeMillis(); return false; @@ -57,7 +57,7 @@ public class HidePlayers { } public static boolean shouldHidePlayers(Player player) { - if (!Location.inDungeon() || !EntityUtil.isARealPlayer(player) || EntityUtil.isClientPlayer(player)) return false; + if (!Location.inDungeon() || !EntityUtil.isARealPlayer(player) || EntityUtil.isClientPlayer(player) || Phase.runStarted()) return false; if (testHideAtLeap()) { return true; @@ -2,15 +2,14 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; +import blade.addon.utils.config.components.Categories; +import blade.addon.utils.config.components.CombineableNotification; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import config.practical.hud.HUDComponent; +import config.practical.hud.HUDCategory; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; @@ -20,11 +19,12 @@ import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ResolvableProfile; +import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class KeyNotifier { +public class KeyNotification extends CombineableNotification { private final static Component BLOOD_KEY = Component.literal("§l§cBlood Key Dropped"); private final static Component WITHER_KEY = Component.literal("§l§7Wither Key Dropped"); @@ -36,12 +36,16 @@ public class KeyNotifier { private final static Pattern AUTOMATIC_PICKUP_PATTERN = Pattern.compile("A (Wither|Blood) Key was picked up!"); private final static Pattern NORMAL_PICKUP_PATTERN = Pattern.compile("has obtained (Wither|Blood) Key!"); - private final static CopyOnWriteArrayList<Entity> foundKeys = new CopyOnWriteArrayList<>(); + private final CopyOnWriteArrayList<Entity> foundKeys = new CopyOnWriteArrayList<>(); - private static boolean hasKey = false; - private static boolean isBloodKey = false; + private boolean hasKey = false; + private boolean isBloodKey = false; - public static void init() { + public KeyNotification() { + super("Key notifier"); + } + + public void init() { ClientTickEvents.END_LEVEL_TICK.register((world) -> { if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier || Phase.inBoss()) return; @@ -96,7 +100,7 @@ public class KeyNotifier { return false; }); - Events.ON_LOCATION_CHANGE.register(locations -> { + Events.ON_LOCATION_CHANGE.register(_ -> { if (Location.inDungeon()) { isBloodKey = false; hasKey = false; @@ -106,19 +110,27 @@ public class KeyNotifier { }); } - private static boolean isValidClass() { - return (Dungeons.displayKeyForAllClasses || DungeonClass.isClass(DungeonClass.ARCHER) || DungeonClass.isClass(DungeonClass.MAGE) && Dungeons.enableKeyNotifier); + @Override + public boolean shouldRender() { + return Location.inDungeon() && hasKey && isValidClass() && !Phase.inBoss(); } - public static boolean display() { - return Location.inDungeon() && hasKey && isValidClass() && !Phase.inBoss(); + @Override + public List<HUDCategory> categories() { + return List.of(Categories.CLEAR); } - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { - int x = component.getScaledX(); - int y = component.getScaledY(); + @Override + public boolean enabled() { + return Dungeons.enableKeyNotifier; + } + + @Override + public Component getText() { + return isBloodKey ? BLOOD_KEY : WITHER_KEY; + } - Component text = isBloodKey ? BLOOD_KEY : WITHER_KEY; - RenderUtils.drawCenteredText(graphics, Minecraft.getInstance().font, text, x, y, component.getWidth(), 0xffffffff); + private boolean isValidClass() { + return (Dungeons.displayKeyForAllClasses || DungeonClass.isClass(DungeonClass.ARCHER) || DungeonClass.isClass(DungeonClass.MAGE) && Dungeons.enableKeyNotifier); } } @@ -2,25 +2,34 @@ package blade.addon.features.dungeon; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.components.Categories; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; import config.practical.hud.HUDComponent; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; -public class QuizTimer { +import java.util.List; + +public class QuizTimer extends HUDComponent { private static final int START_DURATION = 220; private static final int QUESTION_DURATION = 100; - private static int tick = 0; - private static int stage = 0; + private int tick = 0; + private int stage = 0; + + public QuizTimer() { + super("Quiz timer"); + } - public static void init() { + public void init() { Events.ON_GAME_MESSAGE.register(text -> { if (!Location.inDungeon()) return false; @@ -45,18 +54,40 @@ public class QuizTimer { return false; }); - Events.ON_LOCATION_CHANGE.register(newLocation -> { + Events.ON_LOCATION_CHANGE.register(_ -> { tick = 0; stage = 0; return false; }); } - public static boolean display() { + @Override + public int getWidth() { + return 80; + } + + @Override + public int getHeight() { + return 10; + } + + @Override + public boolean editable() { + return Dungeons.quizTimer; + } + + @Override + public boolean shouldRender() { return Dungeons.quizTimer && tick > 0; } - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { + @Override + public List<HUDCategory> categories() { + return List.of(Categories.CLEAR); + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { Font textRenderer = Minecraft.getInstance().font; if (textRenderer == null) return; @@ -65,9 +96,9 @@ public class QuizTimer { .append(Component.literal(stage + "/3").withColor(0xffffffff) .append(Component.literal("): ").withColor(ExtraOptions.timerPrefixColor)) .append(Component.literal(Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION) + "s").withColor(0xffffffff))); - graphics.text(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); + guiGraphicsExtractor.text(textRenderer, drawnText, getScaledX(), getScaledY(), 0xffffffff, true); } else { - RenderUtils.drawPrefixedTimer(component, graphics, "Quiz", tick); + RenderUtils.drawPrefixedTimer(this, guiGraphicsExtractor, "Quiz", tick); } } @@ -2,14 +2,14 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; +import blade.addon.utils.config.components.Categories; +import blade.addon.utils.config.components.CombineableNotification; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.data.PartyUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import config.practical.hud.HUDComponent; +import config.practical.hud.HUDCategory; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.Component; @@ -18,11 +18,12 @@ import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Scoreboard; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class RunStartValidator { +public class RunStartValidator extends CombineableNotification { private static final Pattern STARTING_PATTERN = Pattern.compile("^Starting in \\d second(s)?"); private static final Pattern CLASS_PATTERN = Pattern.compile("\\[([ABHMT])]"); @@ -35,7 +36,11 @@ public class RunStartValidator { private static boolean hasTicked = false; - public static void init() { + public RunStartValidator() { + super("Run start validator"); + } + + public void init() { Events.ON_GAME_MESSAGE.register(message -> { if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return false; @@ -49,16 +54,16 @@ public class RunStartValidator { return false; }); - Events.ON_LOCATION_CHANGE.register(location -> { + Events.ON_LOCATION_CHANGE.register(_ -> { if (Location.inDungeon()) { PartyUtil.sendPacket(); - reset(); + resetInfo(); } return false; }); - Events.ON_PLAYER_ENTRY.register(receivedEntry -> { + Events.ON_PLAYER_ENTRY.register(_ -> { //will only check after the first game message in case of false positives if (!hasTicked) return false; if (!Location.inDungeon() || Phase.runStarted() || (!Dungeons.detectDuplicateClass && !Dungeons.detectPlayerCount)) @@ -68,7 +73,30 @@ public class RunStartValidator { }); } - private static boolean validate() { + @Override + public boolean shouldRender() { + return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers); + } + + @Override + public List<HUDCategory> categories() { + return List.of(Categories.CLEAR); + } + + @Override + public boolean enabled() { + return (Dungeons.detectDuplicateClass || Dungeons.detectPlayerCount); + + } + + @Override + public Component getText() { + if (hasDupeClasses) return DUPE_CLASS_TEXT; + else if (notEnoughPlayers) return PLAYER_COUNT_TEXT; + else return Component.literal("§cSome warning text"); + } + + private boolean validate() { ClientLevel world = Minecraft.getInstance().level; LocalPlayer player = Minecraft.getInstance().player; if (world == null || player == null) return false; @@ -81,7 +109,7 @@ public class RunStartValidator { return hasDupeClasses || notEnoughPlayers; } - private static void checkDuplicateClasses(HashMap<String, Integer> map) { + private void checkDuplicateClasses(HashMap<String, Integer> map) { for (Map.Entry<String, Integer> entry : map.entrySet()) { String clazz = entry.getKey(); Integer count = entry.getValue(); @@ -96,7 +124,7 @@ public class RunStartValidator { hasDupeClasses = false; } - private static void checkPlayerCount(HashMap<String, Integer> map) { + private void checkPlayerCount(HashMap<String, Integer> map) { if (!Dungeons.detectPlayerCount) { notEnoughPlayers = false; return; @@ -109,13 +137,13 @@ public class RunStartValidator { notEnoughPlayers = count < PartyUtil.getPlayerCount(); } - private static void reset() { + private void resetInfo() { hasDupeClasses = false; notEnoughPlayers = false; hasTicked = false; } - private static HashMap<String, Integer> readScoreBoard(Scoreboard scoreboard) { + private HashMap<String, Integer> readScoreBoard(Scoreboard scoreboard) { HashMap<String, Integer> map = new HashMap<>(); for (PlayerTeam team : scoreboard.getPlayerTeams()) { @@ -130,18 +158,4 @@ public class RunStartValidator { } return map; } - - public static boolean display() { - return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers); - } - - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { - if (hasDupeClasses) { - RenderUtils.drawCenteredText(graphics, component, DUPE_CLASS_TEXT); - } else if (notEnoughPlayers) { - RenderUtils.drawCenteredText(graphics, component, PLAYER_COUNT_TEXT); - } else { - RenderUtils.drawCenteredText(graphics, component, Component.literal("§cSome warning text")); - } - } } @@ -2,27 +2,34 @@ package blade.addon.features.dungeon; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.components.Categories; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; import config.practical.hud.HUDComponent; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; +import org.jspecify.annotations.NonNull; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class SecretSpawnTimer { +public class SecretSpawnTimer extends HUDComponent { private static final Pattern PATTERN = Pattern.compile("^Time Elapsed: "); private static final int TICKS_PER_SECOND = 20; private static int tick = 0; - public static void init() { + public SecretSpawnTimer() { + super("Secret spawn timer"); + } + public void init() { Events.ON_TEAM.register(text -> { if (!Location.inDungeon() || !Dungeons.enableSecretSpawnTimer) return false; Matcher matcher = PATTERN.matcher(text); @@ -38,17 +45,38 @@ public class SecretSpawnTimer { }); } - public static boolean display() { + @Override + public int getWidth() { + return 20; + } + + @Override + public int getHeight() { + return 10; + } + + @Override + public boolean editable() { + return Dungeons.enableSecretSpawnTimer; + } + + @Override + public boolean shouldRender() { return Location.inDungeon() && Dungeons.enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(); } - public static void render(HUDComponent component, GuiGraphicsExtractor context) { - int x = component.getScaledX(); - int y = component.getScaledY(); + @Override + public List<HUDCategory> categories() { + return List.of(Categories.CLEAR); + } - int color = tick > 10 ? Constants.GREEN : tick > 5 ? Constants.GOLD : Constants.RED; + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { + int x = getScaledX(); + int y = getScaledY(); - RenderUtils.drawCenteredText(context, Minecraft.getInstance().font, Component.literal(tick + ""), x, y, component.getWidth(), color); + int color = tick > 10 ? Constants.GREEN : tick > 5 ? Constants.GOLD : Constants.RED; + RenderUtils.drawCenteredText(guiGraphicsExtractor, Minecraft.getInstance().font, Component.literal(tick + ""), x, y, this.getWidth(), color); } } @@ -3,36 +3,77 @@ package blade.addon.features.dungeon; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; import config.practical.hud.HUDComponent; import net.minecraft.client.gui.GuiGraphicsExtractor; +import org.jspecify.annotations.NonNull; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class WarpCooldown { +public class WarpCooldown extends HUDComponent { - private static final int WARP_COOLDOWN_MS = 30 * 1000; - private static final Pattern PATTERN = Pattern.compile("^-*\\n\\[[^]]+] (\\w+) entered (?:MM )?\\w+ Catacombs, Floor (\\w+)!\\n-*$"); + private static final int INSTANCE_COOLDOWN_MS = 30 * 1000; + private static final int WARP_COOLDOWN_MS = 4 * 1000; + + private static final Pattern INSTANCE_PATTERN = Pattern.compile("^-*\\n\\[[^]]+] (\\w+) entered (?:MM )?\\w+ Catacombs, Floor (\\w+)!\\n-*$"); + private static final Pattern WARP_PATTERN = Pattern.compile("^Sending to server .+"); private static long endTime = 0; private static boolean displayCooldown = false; - public static void init() { + public WarpCooldown() { + super("Warp cooldown"); + } + + public void init() { Events.ON_GAME_MESSAGE.register(message -> { if (!Dungeons.enableWarpCooldown) return false; if ((endTime - System.currentTimeMillis()) > 0) return false; - Matcher matcher = PATTERN.matcher(message.getString()); + Matcher matcher = INSTANCE_PATTERN.matcher(message.getString()); + if (matcher.find()) { + setCooldown(INSTANCE_COOLDOWN_MS); + return false; + } + + matcher = WARP_PATTERN.matcher(message.getString()); if (matcher.find()) { - endTime = System.currentTimeMillis() + WARP_COOLDOWN_MS; - displayCooldown = true; + setCooldown(WARP_COOLDOWN_MS); } + + return false; }); } - public static boolean display() { + private void setCooldown(int duration) { + displayCooldown = true; + long newEndTime = System.currentTimeMillis() + duration; + if (newEndTime < endTime) return; + endTime = newEndTime; + + } + + @Override + public int getWidth() { + return 110; + } + + @Override + public int getHeight() { + return 10; + } + + @Override + public boolean editable() { + return Dungeons.enableWarpCooldown; + } + + @Override + public boolean shouldRender() { if (!Dungeons.enableWarpCooldown || !displayCooldown) return false; if ((endTime - System.currentTimeMillis()) > 0) { @@ -43,8 +84,14 @@ public class WarpCooldown { } } - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { + @Override + public List<HUDCategory> categories() { + return null; + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); - RenderUtils.drawPrefixedTimer(component, graphics, "Warp Cooldown", timeRemaining); + RenderUtils.drawPrefixedTimer(this, guiGraphicsExtractor, "Warp Cooldown", timeRemaining); } } @@ -2,28 +2,38 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.components.Categories; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; import config.practical.hud.HUDComponent; import net.minecraft.client.gui.GuiGraphicsExtractor; +import org.jspecify.annotations.NonNull; -public class StormLBTimer { +import java.util.List; + + +public class StormLBTimer extends HUDComponent { private static final int BASE_LB_TICK = 20 * 34; private static final int DISPLAY_DURATION_TICK = 20 * 5; - private static int tick = 0; + private int tick = 0; - public static void init() { + public StormLBTimer() { + super("Storm lb timer"); + } + + public void init() { Events.ON_SERVER_TICK.register(() -> { if (Location.inDungeon() && Phase.inP2() && !Phase.stormDead()) tick++; return false; }); - Events.ON_LOCATION_CHANGE.register(newLocation -> { + Events.ON_LOCATION_CHANGE.register(_ -> { if (Location.inDungeon()) { tick = 0; } @@ -31,24 +41,45 @@ public class StormLBTimer { }); } - private static int getCurrentTickTime() { - return BASE_LB_TICK + Floor7.lbTickOffset - tick; + @Override + public int getWidth() { + return 30; } - private static boolean validTime() { - int deltaTick = getCurrentTickTime(); - return deltaTick > 0 && deltaTick <= DISPLAY_DURATION_TICK; + @Override + public int getHeight() { + return 10; + } + @Override + public boolean editable() { + return Floor7.showLBTimer; } - public static boolean display() { + @Override + public boolean shouldRender() { return Floor7.showLBTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead() && validTime() && DungeonClass.isClass(DungeonClass.ARCHER); } - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { + @Override + public List<HUDCategory> categories() { + return List.of(Categories.P2); + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { int deltaTick = getCurrentTickTime(); double num = deltaTick * Constants.TICK_DURATION; - RenderUtils.drawTimer(component, graphics, num, RenderUtils.getStatusColor(60, 30, deltaTick)); + RenderUtils.drawTimer(this, guiGraphicsExtractor, num, RenderUtils.getStatusColor(60, 30, deltaTick)); + } + + private int getCurrentTickTime() { + return BASE_LB_TICK + Floor7.lbTickOffset - tick; } + private boolean validTime() { + int deltaTick = getCurrentTickTime(); + return deltaTick > 0 && deltaTick <= DISPLAY_DURATION_TICK; + + } } @@ -4,15 +4,12 @@ import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; import net.minecraft.sounds.SoundEvents; -public class DragSpawnTimer { +public class DragonSpawn { public enum Team { ARCHER_TEAM("Archer team"), BERS_TEAM("Bers team"); @@ -52,8 +49,8 @@ public class DragSpawnTimer { return false; }); - Events.ON_LOCATION_CHANGE.register(newLocation -> { - reset(); + Events.ON_LOCATION_CHANGE.register(_ -> { + resetInfo(); return false; }); } @@ -89,17 +86,13 @@ public class DragSpawnTimer { return true; } - private static void reset() { + private static void resetInfo() { hasDoneSplit = false; currentDragon = Dragon.NONE; tick = 0; } - public static boolean display() { - return Floor7.dragSpawnTimers && currentDragon != Dragon.NONE; - } - - public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { - RenderUtils.drawTimer(component, graphics, tick, currentDragon.color); + public static int getTick() { + return tick; } } @@ -0,0 +1,48 @@ +package blade.addon.features.dungeon.f7.dragons; + +import blade.addon.utils.config.components.Categories; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class DragonSpawnTimer extends HUDComponent { + + public DragonSpawnTimer() { + super("Dragon spawn timer"); + } + + @Override + public int getWidth() { + return 30; + } + + @Override + public int getHeight() { + return 10; + } + + @Override + public boolean editable() { + return Floor7.dragSpawnTimers; + } + + @Override + public boolean shouldRender() { + return Floor7.dragSpawnTimers && DragonSpawn.currentDragon != Dragon.NONE; + } + + @Override + public List<HUDCategory> categories() { + return List.of(Categories.P5); + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { + RenderUtils.drawTimer(this, guiGraphicsExtractor, DragonSpawn.getTick(), DragonSpawn.currentDragon.color); + } +} @@ -16,8 +16,8 @@ public class DragonTracer { private static void render(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Floor7.dragonTracer) return; - Dragon dragon = DragSpawnTimer.currentDragon; - if (dragon == null || dragon == Dragon.NONE || !DragSpawnTimer.hasDoneSplit) return; + Dragon dragon = DragonSpawn.currentDragon; + if (dragon == null || dragon == Dragon.NONE || !DragonSpawn.hasDoneSplit) return; RenderUtils.renderLineTo(context, dragon.spawnPos, dragon.color); } @@ -0,0 +1,136 @@ +package blade.addon.features.dungeon.f7.invincibility; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.config.components.Categories; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.dungeon.Phase; +import config.practical.hud.HUDCategory; +import config.practical.hud.HUDComponent; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.renderer.RenderPipelines; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.Identifier; +import org.jspecify.annotations.NonNull; + +import java.util.List; + +public class InvincibilityDisplay extends HUDComponent { + + private static final Identifier BONZO_SPRITE = Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "bonzo-mask"); + private static final Identifier SPIRIT_SPRITE = Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "spirit-mask"); + private static final Identifier PHOENIX_SPRITE = Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "phoenix"); + + private static final int TEXT_HEIGHT = 9; + private static final int SPRITE_SIZE = TEXT_HEIGHT; + + + public InvincibilityDisplay() { + super("Invincibility timer"); + } + + @Override + public int getWidth() { + return 110; + } + + @Override + public int getHeight() { + return 28; + } + + @Override + public boolean editable() { + return Dungeons.displayInvincibilityTimer; + } + + @Override + public boolean shouldRender() { + if (!Dungeons.displayInvincibilityTimer || !Location.inDungeon()) { + return false; + } + + switch (Dungeons.displayWhen) { + case BOSS_ONLY -> { + return Phase.inBoss(); + } + case P3_ONLY -> { + return Phase.inP3(); + } + case ALWAYS -> { + return true; + } + case USEFUL_PHASES -> { + return Phase.inP3() || Phase.inP2(); + } + case null, default -> { + return false; + } + } + } + + @Override + public List<HUDCategory> categories() { + switch (Dungeons.displayWhen) { + case BOSS_ONLY -> { + return List.of(Categories.P1, Categories.P2, Categories.P3, Categories.P4, Categories.P5); + } + case P3_ONLY -> { + return List.of(Categories.P3); + } + case ALWAYS -> { + return null; + } + case USEFUL_PHASES -> { + return List.of(Categories.P2, Categories.P3); + } + } + + return null; + } + + private static Component formatTimer(int ticks) { + return Component.literal("§8(§7" + Constants.DECIMAL_FORMAT.format(ticks * Constants.TICK_DURATION) + "§8)"); + } + + private static Component getText(int ticks, boolean isOn, String string) { + if (ticks > 0) { + return Component.literal("§c" + string).append(formatTimer(ticks)); + } else { + String color = isOn ? "§e" : "§a"; + return Component.literal(color + string); + } + } + + private static void drawSprite(GuiGraphicsExtractor context, Identifier identifier, int x, int y, boolean isOn, int ticks, Component timerText) { + int color = (ticks > 0 ? Constants.RED : isOn ? Constants.YELLOW : Constants.GREEN); + context.fill(x, y, x + SPRITE_SIZE, y + SPRITE_SIZE, color); + context.blitSprite(RenderPipelines.GUI_TEXTURED, identifier, x, y, SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); + if (ticks > 0) { + context.text(Minecraft.getInstance().font, timerText, x + TEXT_HEIGHT * 2, y, 0xffffffff, true); + } + + } + + @Override + public void render(@NonNull GuiGraphicsExtractor guiGraphicsExtractor) { + int x = getScaledX(); + int y = getScaledY(); + + if (Dungeons.useSprites) { + drawSprite(guiGraphicsExtractor, BONZO_SPRITE, x, y, InvincibilityTimer.bonzoMaskOn, InvincibilityTimer.bonzoMaskTicks, formatTimer(InvincibilityTimer.bonzoMaskTicks)); + drawSprite(guiGraphicsExtractor, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, InvincibilityTimer.spiritMaskOn, InvincibilityTimer.spiritMaskTicks, formatTimer(InvincibilityTimer.spiritMaskTicks)); + drawSprite(guiGraphicsExtractor, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, InvincibilityTimer.phoenixOn, InvincibilityTimer.phoenixTicks, formatTimer(InvincibilityTimer.phoenixTicks)); + } else { + if (Dungeons.removeMaskPart) { + guiGraphicsExtractor.text(Minecraft.getInstance().font, getText(InvincibilityTimer.bonzoMaskTicks, InvincibilityTimer.bonzoMaskOn, "Bonzo "), x, y, 0xffffffff, true); + guiGraphicsExtractor.text(Minecraft.getInstance().font, getText(InvincibilityTimer.spiritMaskTicks, InvincibilityTimer.spiritMaskOn, "Spirit "), x, y + TEXT_HEIGHT, 0xffffffff, true); + } else { + guiGraphicsExtractor.text(Minecraft.getInstance().font, getText(InvincibilityTimer.bonzoMaskTicks, InvincibilityTimer.bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); + guiGraphicsExtractor.text(Minecraft.getInstance().font, getText(InvincibilityTimer.spiritMaskTicks, InvincibilityTimer.spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); + } + guiGraphicsExtractor.text(Minecraft.getInstance().font, getText(InvincibilityTimer.phoenixTicks, InvincibilityTimer.phoenixOn, "Phoenix "), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); + } + } +} @@ -4,35 +4,66 @@ import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDCategory; import config.practical.hud.HUDComponent; import net.minecraft.client.gui.GuiGraphicsExtractor; +import org.jspecify.annotations.NonNull; -public class InvincibilityDuration { +import java.util.List; + +public class InvincibilityDuration extends HUDComponent { private static final int MAX_DURATION = 3 * 20; - private static int ticks = 0; + private int ticks = 0; + + public InvincibilityDuration() { + super("Invincibility duration"); + } - public static void init() { + public void init() { Events.ON_SERVER_TICK.register(() -> { ticks = Math.max(0, ticks - 1); return false; }); } - public static void proc() { - ticks = MAX_DURATION; - Misc.sendSound(Dungeons.invincibilitySound); + @Override + public int getWidth() { + return 30; + } + + …… diff 过长已截断 …… |
- fixed a crash when both the nametag and outline was active on a teammate (26.1.2 only issue)查看变更src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 40 ++++++++++++++++++++++++++++------------ src/main/java/blade/addon/utils/Location.java | 7 ++++--- src/main/java/blade/addon/utils/rendering/RenderLayers.java | 2 ++ src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 5 +++++ src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 2 ++ 5 files changed, 41 insertions(+), 15 deletions(-) @@ -44,29 +44,45 @@ public class TeammateHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> teammates.removeIf(Entity::isRemoved)); RenderingEvents.LINE_NO_DEPTH.register(TeammateHighlight::renderOutline); + RenderingEvents.TEXT.register(TeammateHighlight::renderText); + } + + private static boolean shouldRender(Player player) { + if (Dungeons.dontHighlightHiddenTeammates && HidePlayers.shouldHidePlayers(player)) return false; + if (Dungeons.dontHighlightVisibleTeammates && !HidePlayers.shouldHidePlayers(player)) return false; + return true; } private static void renderOutline(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { - if (!Dungeons.highlightTeammates && !Dungeons.renderClassName) return; + if (!Dungeons.highlightTeammates) return; teammates.forEach(player -> { - if (Dungeons.dontHighlightHiddenTeammates && HidePlayers.shouldHidePlayers(player)) return; - if (Dungeons.dontHighlightVisibleTeammates && !HidePlayers.shouldHidePlayers(player)) return; + if (!shouldRender(player)) return; DungeonClass clazz = DungeonClass.getClass(player); if (clazz == null) return; int color = DungeonClass.getColor(clazz); - if (Dungeons.highlightTeammates) { - float[] rgba = RenderUtils.toFloats(color); - RenderUtils.renderOutlinedBox(matrixStack, consumer,EntityUtil.getBox(player), rgba); - } + float[] rgba = RenderUtils.toFloats(color); + RenderUtils.renderOutlinedBox(matrixStack, consumer, EntityUtil.getBox(player), rgba); + + }); + } + + private static void renderText(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + if (!Dungeons.renderClassName) return; + + teammates.forEach(player -> { + if (!shouldRender(player)) return; + DungeonClass clazz = DungeonClass.getClass(player); + if (clazz == null) return; + + int color = DungeonClass.getColor(clazz); + + Component text = Component.literal(player.getName().getString()).withColor(color).append(Component.literal(" [" + DungeonClass.getChar(clazz) + "]").withColor(Constants.YELLOW)); + Vec3 pos = EntityUtil.getLerpedPos(player); + RenderUtils.renderText(context, matrixStack, text, pos.x(), pos.y() + 2.75, pos.z(), 2); - if (Dungeons.renderClassName) { - Component text = Component.literal(player.getName().getString()).withColor(color).append(Component.literal(" [" + DungeonClass.getChar(clazz) + "]").withColor(Constants.YELLOW)); - Vec3 pos = EntityUtil.getLerpedPos(player); - RenderUtils.renderText(context, matrixStack, text, pos.x(), pos.y() + 2.75, pos.z(), 2); - } }); } @@ -29,8 +29,9 @@ public enum Location { JERRYS_WORKSHOP("Jerry's Workshop"), MINESHAFT("Mineshaft"), DARK_AUCTION("Dark Auction"), - KUUDRA("Kuudra"),; - + KUUDRA("Kuudra"), + TORRHUS_CANYON("Torrhus Canyon"), + SAFARI("Safari"); final String name; Location(String name) { @@ -51,7 +52,7 @@ public enum Location { ServerType serverType = packet.getServerType().get(); inSkyblock = serverType.getName().equals("SkyBlock"); } - + Debug.sendDebugMessage(Component.literal("Parsing location: " + locationName)); changeLocation(getLocation(locationName)); })); @@ -25,5 +25,7 @@ public class RenderLayers { public static final RenderType LINE_NO_DEPTH = RenderType.create("line-no-depth-layer", RenderSetup.builder(RenderPipelines.LINE_NO_DEPTH).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); + public static final RenderType TEXT = + RenderType.create("text-layer", RenderSetup.builder(RenderPipelines.TEXT).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); } @@ -48,4 +48,9 @@ public class RenderPipelines { .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) .build()); + public static final RenderPipeline TEXT = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(blade.addon.utils.Constants.NAMESPACE, "text-pipe")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) + .withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false)) + .build()); } @@ -10,6 +10,7 @@ public class RenderingEvents { public static RenderHandler LINE = new RenderHandler(RenderLayers.LINE); public static RenderHandler FILLED_NO_DEPTH = new RenderHandler(RenderLayers.FILLED_NO_DEPTH); public static RenderHandler LINE_NO_DEPTH = new RenderHandler(RenderLayers.LINE_NO_DEPTH); + public static RenderHandler TEXT = new RenderHandler(RenderLayers.TEXT); public static void init() { @@ -19,5 +20,6 @@ public class RenderingEvents { LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(LINE::init); LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(FILLED_NO_DEPTH::init); LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(LINE_NO_DEPTH::init); + LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(TEXT::init); } } |
- added the forgotten button for math formatting查看变更src/main/java/blade/addon/utils/config/Config.java | 1 + 1 file changed, 1 insertion(+) @@ -331,6 +331,7 @@ public class Config { extra.add(new ConfigBool(Component.literal("Display selected arrow"), () -> ExtraOptions.displayCurrentArrow, bool -> ExtraOptions.displayCurrentArrow = bool)); extra.add(new ConfigBool(Component.literal("Title on arrow swap"), () -> ExtraOptions.arrowSwapNotification, bool -> ExtraOptions.arrowSwapNotification = bool)); extra.add(new ConfigBool(Component.literal("Toggleable searchbar (ctrl + f)"), () -> ExtraOptions.toggleableSearchBar, bool -> ExtraOptions.toggleableSearchBar = bool)); + extra.add(new ConfigBool(Component.literal("Format math results"), () -> ExtraOptions.formatMathResult, bool -> ExtraOptions.formatMathResult = bool)); extra.add(new ConfigColor(Component.literal("Searchbar miss color"), () -> ExtraOptions.searchbarMissColor, color -> ExtraOptions.searchbarMissColor = color, "search-bar-miss-color", true)); extra.add(new ConfigBool(Component.literal("Disable protect item (resets on launch)"), () -> ProtectItem.stopProtectItem, bool -> ProtectItem.stopProtectItem = bool)); extra.add(new ConfigBool(Component.literal("Display reaper duration"), () -> ExtraOptions.enableReaperDisplay, bool -> ExtraOptions.enableReaperDisplay = bool)); |
- changed candy tooltip查看变更src/main/java/blade/addon/features/item/ToolTip.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -72,7 +72,7 @@ public class ToolTip { String candies = matcher.group(1); if (candies.equals("0")) return; - lines.add(Component.literal("§aCandies : (" + candies + "/10)")); + lines.add(Component.literal("§aCandies: (" + candies + "/10)")); } |
- added support for searching multiple items at a time (use , between each item) - replaced built in fabric msg received events - added item quality in tooltip - added pet candy in tooltip - fixed pet training breaking the pet display查看变更src/main/java/blade/addon/Bladeaddons.java | 1 + src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 8 +++++--- src/main/java/blade/addon/features/item/ToolTip.java | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/SearchBar.java | 40 ++++++++++++++++++++++++++++++++++------ src/main/java/blade/addon/features/other/SelectedPet.java | 3 +++ src/main/java/blade/addon/utils/config/Config.java | 6 ++++++ src/main/java/blade/addon/utils/config/values/Visual.java | 6 ++++++ src/main/java/blade/addon/utils/data/ItemUtil.java | 7 +++++++ src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 7 ++++--- src/main/java/blade/addon/utils/events/CustomEvents.java | 19 +++++++++++-------- 10 files changed, 157 insertions(+), 20 deletions(-) @@ -133,5 +133,6 @@ public class Bladeaddons implements ModInitializer { StormLBTimer.init(); DeathMessage.init(); BlockPetMenu.init(); + ToolTip.init(); } } \ No newline at end of file @@ -4,8 +4,8 @@ import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.network.chat.Component; + import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -35,13 +35,15 @@ public class AutoRequeue { return false; }); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() && !Dungeons.enableAutoRequeue) return; + Events.ON_GAME_MESSAGE.register(message -> { + if (!Location.inDungeon() && !Dungeons.enableAutoRequeue) return false; String string = message.getString(); Matcher matcher = LEFT_PATTERN.matcher(string); if (matcher.find()) { someoneLeft = true; } + + return false; }); Events.ON_RUN_END.register(() -> { @@ -0,0 +1,80 @@ +package blade.addon.features.item; + +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.data.ItemUtil; +import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ToolTip { + + private static final Pattern PATTERN = Pattern.compile("\"candyUsed\":(\\d+),"); + + public static void init() { + ItemTooltipCallback.EVENT.register((item, tooltipContext, tooltipType, lines) -> { + + CompoundTag nbt = ItemUtil.getNbt(item); + if (nbt == null) return; + attemptItemQuality(nbt, lines); + attemptCandy(nbt, lines); + + }); + } + + + private static void attemptItemQuality(CompoundTag nbt, List<Component> lines) { + if (!Visual.itemQuality) return; + int statboost = nbt.getIntOr("baseStatBoostPercentage", -1); + if (statboost == -1) return; + + int tier = nbt.getIntOr("item_tier", -1); + if (tier == -1) return; + + String statBoost = "§4Stat boost: " + statboost + "/50"; + String reqString = "req: " + getFloor(tier); + + lines.add(Component.literal(statBoost + " " + reqString)); + + } + + private static String getFloor(int tier) { + return switch (tier) { + case 0 -> "E"; + case 1 -> "F1"; + case 2 -> "F2"; + case 3 -> "F3"; + case 4 -> "F4"; + case 5 -> "F5"; + case 6 -> "F6"; + case 7 -> "F7"; + case 8 -> "M5"; + case 9 -> "M6"; + case 10 -> "M7"; + default -> "?"; + }; + } + + + private static void attemptCandy(CompoundTag nbt, List<Component> lines) { + if (!Visual.petCandy) return; + if (!nbt.getStringOr("id", "").equals("PET")) return; + + String petInfo = nbt.getStringOr("petInfo", null); + if (petInfo == null) return; + + Matcher matcher = PATTERN.matcher(petInfo); + if (!matcher.find()) return; + + String candies = matcher.group(1); + if (candies.equals("0")) return; + + lines.add(Component.literal("§aCandies : (" + candies + "/10)")); + + + } + +} @@ -17,19 +17,27 @@ import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import org.lwjgl.glfw.GLFW; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + public class SearchBar { private static final int SEARCH_Y = 20; private static final int SEARCH_WIDTH = 150; private static final int SEARCH_HEIGHT = 20; + private static EditBox searchBar; private static boolean shouldDisplay = false; - private static String searchTerm = ""; + private static double parsedValue = Double.NaN; + private static String writtenString = ""; + private static CopyOnWriteArrayList<String> searchTerms = new CopyOnWriteArrayList<>(); + + private static final ConcurrentHashMap<ItemStack, Boolean> parsedData = new ConcurrentHashMap<>(); public static void init() { DrawEvents.INVENTORY_SLOT_AFTER.register((context, item, x, y) -> { - if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar && Double.isNaN(parsedValue)) { + if (shouldDisplay() && !writtenString.isEmpty() && ExtraOptions.toggleableSearchBar && Double.isNaN(parsedValue)) { if (!matches(item)) { context.fill(x, y, x + 16, y + 16, ExtraOptions.searchbarMissColor); } @@ -39,10 +47,18 @@ public class SearchBar { } private static boolean matches(ItemStack item) { + if (parsedData.containsKey(item)) return parsedData.get(item); + String name = item.getHoverName().getString().toLowerCase(); if (name.equals("air")) return false; - return (name.contains(searchTerm) || ItemUtil.containsIgnoreCaseLore(item, searchTerm)); + for (String term : searchTerms) { + if (name.contains(term) || ItemUtil.containsIgnoreCaseLore(item, term)) { + return true; + } + } + + return false; } public static void render(GuiGraphicsExtractor context, int mouseX, int mouseY, float deltaTicks) { @@ -54,7 +70,7 @@ public class SearchBar { Font textRenderer = Minecraft.getInstance().font; if (textRenderer == null) return; - int textX = searchBar.getX() + textRenderer.width(searchTerm) + 4; + int textX = searchBar.getX() + textRenderer.width(writtenString) + 4; int textY = searchBar.getY() + (searchBar.getHeight() - 8) / 2; context.text(textRenderer, expression, textX, textY, 0xffffffff, true); } @@ -106,9 +122,21 @@ public class SearchBar { if (window == null || textRenderer == null) return false; searchBar = new EditBox(textRenderer, (window.getGuiScaledWidth() - SEARCH_WIDTH) / 2, SEARCH_Y, SEARCH_WIDTH, SEARCH_HEIGHT, Component.literal("")); + searchBar.setMaxLength(100); searchBar.setResponder(string -> { - searchTerm = string.toLowerCase(); - parsedValue = MathParser.parseExpression(searchTerm); + + + writtenString = string.toLowerCase(); + parsedValue = MathParser.parseExpression(writtenString); + if (Double.isNaN(parsedValue)) { + parsedData.clear(); + } + + String[] terms = writtenString.split(","); + searchTerms.clear(); + for (String term: terms) { + searchTerms.add(term.strip()); + } }); return true; } @@ -95,6 +95,9 @@ public class SelectedPet { return false; } + int correctionCheck = string.indexOf("["); + if (correctionCheck != 1) return false; + Matcher matcher = TAB_PET_PATTERN.matcher(string); if (matcher.find()) { String petName = matcher.group(1).replace(" ✦", ""); @@ -413,6 +413,12 @@ public class Config { visual.add(new ConfigBool(Component.literal("1.8.9 like fishing bobber"), () -> Visual.oldFishingRod, bool -> Visual.oldFishingRod = bool)); visual.add(new ConfigBool(Component.literal("Stop shovel swing when flattening dirt"), () -> Visual.stopShovelFlattening, bool -> Visual.stopShovelFlattening = bool)); visual.add(new ConfigBool(Component.literal("Stop swinging when throwing a pearl"), () -> Visual.stopPearlSwing, bool -> Visual.stopPearlSwing = bool)); + + ConfigSection toolTip = new ConfigSection(Component.literal("ToolTips")); + toolTip.add(new ConfigBool(Component.literal("Item quality"), () -> Visual.itemQuality, bool -> Visual.itemQuality = bool)); + toolTip.add(new ConfigBool(Component.literal("Pet candy"), () -> Visual.petCandy, bool -> Visual.petCandy = bool)); + visual.add(toolTip); + return visual; } @@ -55,4 +55,10 @@ public class Visual { @ConfigValue public static boolean circularRarityBackground = false; + @ConfigValue + public static boolean itemQuality = false; + + @ConfigValue + public static boolean petCandy = false; + } @@ -30,6 +30,13 @@ public class ItemUtil { return compound.getStringOr("uuid", null); } + public static CompoundTag getNbt(ItemStack item) { + CustomData nbt = item.get(DataComponents.CUSTOM_DATA); + if (nbt == null) return null; + + return nbt.copyTag(); + } + public static boolean isHolding(String name) { LocalPlayer player = Minecraft.getInstance().player; if (player == null) return false; @@ -6,7 +6,6 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.events.Events; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; @@ -38,14 +37,16 @@ public enum DungeonClass { return false; }); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Phase.runStarted() && currentClass != null) return; + Events.ON_GAME_MESSAGE.register(message -> { + if (!Phase.runStarted() && currentClass != null) return false; Matcher matcher = PATTERN.matcher(message.getString()); if (matcher.find()) { String dungeonClass = matcher.group(1); currentClass = parseClass(dungeonClass); } + + return false; }); Events.ON_PLAYER_ENTRY.register(receivedEntry -> { @@ -1,8 +1,7 @@ package blade.addon.utils.events; -import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import blade.addon.utils.debug.Debug; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -16,20 +15,20 @@ public class CustomEvents { public static void init() { //party event - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + Events.ON_GAME_MESSAGE.register(message -> { String string = message.getString(); Matcher matcher = PARTY_PATTERN.matcher(string); - if (!matcher.find()) return; + if (!matcher.find()) return false; int index = string.indexOf(":"); if (index < PARTY_MSG_OFFSET) { Debug.LOGGER.error("{} had bad index", string); - return; + return false; } String tempUsername = string.substring(PARTY_MSG_OFFSET, index).replaceAll("§.", ""); - if (index + 2 >= string.length()) return; + if (index + 2 >= string.length()) return false; String sentMessage = string.substring(index + 2).strip(); index = tempUsername.indexOf("]") + 2; @@ -39,18 +38,22 @@ public class CustomEvents { String username = tempUsername; Events.ON_PARTY_MESSAGE.invoke(partyMessageEvent -> partyMessageEvent.sentMessage(username, sentMessage)); + + return false; }); //leap event - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + Events.ON_GAME_MESSAGE.register(message -> { if (Location.inDungeon()) { String string = message.getString(); Matcher matcher = LEAP_PATTERN.matcher(string); - if (!matcher.find()) return; + if (!matcher.find()) return false; Events.ON_LEAP.invoke(leapEvent -> leapEvent.onLeap(matcher.group(1))); } + + return false; }); } } |
- added sound on invincibility proc - fixed a crash when modifying some save folders - x can be used instead of * for multiplication - math results formatting can now be disabled - added a toggle to display distance on all classes - made DistanceToLedge be different for non mastermode查看变更src/main/java/blade/addon/Bladeaddons.java | 4 +++- src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 4 +++- src/main/java/blade/addon/features/dungeon/f7/storm/DistanceToLedge.java | 11 ++++++++++- src/main/java/blade/addon/features/other/SearchBar.java | 2 +- src/main/java/blade/addon/utils/MathParser.java | 1 + src/main/java/blade/addon/utils/config/Config.java | 2 ++ src/main/java/blade/addon/utils/config/FolderUtility.java | 8 ++++++-- src/main/java/blade/addon/utils/config/values/Dungeons.java | 5 +++++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 +++ src/main/java/blade/addon/utils/config/values/Floor7.java | 3 +++ src/main/java/blade/addon/utils/dungeon/Phase.java | 13 +++++++++++-- 11 files changed, 48 insertions(+), 8 deletions(-) @@ -51,7 +51,9 @@ public class Bladeaddons implements ModInitializer { FolderUtility.init(); Components.init(); Buttons.init(); - Config.manager.load(); + try { + Config.manager.load(); + }catch (NullPointerException err) {} Keybinds.init(); CustomEvents.init(); Commands.init(); @@ -1,5 +1,6 @@ package blade.addon.features.dungeon.f7.invincibility; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -20,10 +21,11 @@ public class InvincibilityDuration { public static void proc() { ticks = MAX_DURATION; + Misc.sendSound(Dungeons.invincibilitySound); } public static boolean display() { - return ticks > 0 && Dungeons.InvincibilityDuration; + return ticks > 0 && Dungeons.InvincibilityDuration; } public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { @@ -33,10 +33,19 @@ public class DistanceToLedge { return YELLOW_PAD.contains(player.position()); } + public static boolean isPYClass() { + if (Floor7.displayDistanceOnAllClasses) return true; + if (Phase.isInMasterMode()) { + return DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER); + } else { + return DungeonClass.isClass(DungeonClass.TANK) || DungeonClass.isClass(DungeonClass.ARCHER); + } + } + public static boolean display() { if (!Floor7.displayDistanceToLedge || !Location.inDungeon()) return false; if (Floor7.showDistanceAtYellowOnly && !isAtYellow()) return false; - return Phase.inP2() && !Phase.stormDead() && (DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER)); + return Phase.inP2() && !Phase.stormDead() && isPYClass(); } public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { @@ -50,7 +50,7 @@ public class SearchBar { searchBar.extractRenderState(context, mouseX, mouseY, deltaTicks); if (!Double.isNaN(parsedValue)) { - String expression = " §e= §2" + RenderUtils.formatNumber((float) parsedValue); + String expression = " §e= §2" + (ExtraOptions.formatMathResult ? RenderUtils.formatNumber((float) parsedValue) : (long) parsedValue); Font textRenderer = Minecraft.getInstance().font; if (textRenderer == null) return; @@ -291,6 +291,7 @@ public class MathParser { int index = copiedString.indexOf(token); if (index == 0) { copiedString = copiedString.substring(token.length()); + if (token.equals("x")) token = "*"; output.add(token); wasPrevNum = false; continue; @@ -88,6 +88,7 @@ public class Config { invincibility.add(new ConfigBool(Component.literal("Invincibility duration"), () -> Dungeons.InvincibilityDuration, bool -> Dungeons.InvincibilityDuration = bool)); invincibility.add(new ConfigBool(Component.literal("Duration changing color"), () -> Dungeons.useStatusColorForInvincibility, bool -> Dungeons.useStatusColorForInvincibility = bool)); invincibility.add(new ConfigBool(Component.literal("Remove \"Mask\" in the text"), () -> Dungeons.removeMaskPart, bool -> Dungeons.removeMaskPart = bool)); + invincibility.add(new ConfigSound(Component.literal("Proc sound"), Dungeons.invincibilitySound)); dungeons.add(invincibility); ConfigSection classColors = new ConfigSection(Component.literal("Class Colors")); @@ -183,6 +184,7 @@ public class Config { storm.add(new ConfigBool(Component.literal("First Death time"), () -> Floor7.enableStormDeathTime, bool -> Floor7.enableStormDeathTime = bool)); storm.add(new ConfigBool(Component.literal("Distance to ledge"), () -> Floor7.displayDistanceToLedge, bool -> Floor7.displayDistanceToLedge = bool)); storm.add(new ConfigBool(Component.literal("Only display distance at yellow"), () -> Floor7.showDistanceAtYellowOnly, bool -> Floor7.showDistanceAtYellowOnly = bool)); + storm.add(new ConfigBool(Component.literal("Display distance on all classes"), () -> Floor7.displayDistanceOnAllClasses, bool -> Floor7.displayDistanceOnAllClasses = bool)); storm.add(new ConfigBool(Component.literal("Warn if spirit mask is used"), () -> Floor7.notifyUsedSpiritMask, bool -> Floor7.notifyUsedSpiritMask = bool)); storm.add(new ConfigBool(Component.literal("Pillar explode timer"), () -> Floor7.timePillarExplosion, bool -> Floor7.timePillarExplosion = bool)); storm.add(new ConfigBool(Component.literal("Storm crushed notification"), () -> Floor7.notifyStormCrush, bool -> Floor7.notifyStormCrush = bool)); @@ -27,8 +27,12 @@ public class FolderUtility { } } - ProtectItem.itemManager.load(); - PersonalBests.pbManager.load(); + try { + ProtectItem.itemManager.load(); + PersonalBests.pbManager.load(); + } catch (NullPointerException err) { + Debug.LOGGER.error("Failed to load protected item data or personal best data"); + } } } @@ -1,7 +1,9 @@ package blade.addon.utils.config.values; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; +import config.practical.data.SoundData; import config.practical.manager.ConfigValue; +import net.minecraft.sounds.SoundEvents; public class Dungeons { @@ -163,4 +165,7 @@ public class Dungeons { @ConfigValue public static String customLeapMessage = "Leaped to <player>!"; + + @ConfigValue + public static SoundData invincibilitySound = new SoundData(SoundEvents.NOTE_BLOCK_PLING.value(), 0, 1); } @@ -141,4 +141,7 @@ public class ExtraOptions { @ConfigValue public static int searchbarMissColor = 0xaa111111; + + @ConfigValue + public static boolean formatMathResult = true; } @@ -189,4 +189,7 @@ public class Floor7 { @ConfigValue public static int lbTickOffset = 10; + + @ConfigValue + public static boolean displayDistanceOnAllClasses = false; } @@ -10,10 +10,12 @@ import blade.addon.utils.events.interfaces.PhaseEvent; import blade.addon.utils.events.interfaces.RunEndEvent; import config.practical.hud.HUDComponent; import config.practical.manager.ConfigValue; + import java.util.ArrayList; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.network.chat.Component; @@ -34,6 +36,7 @@ public class Phase { private static int currentPhase = -1; private static String floor = ""; + private static boolean inMasterMode = false; private static boolean inFloor7 = false; private static boolean stormDead = false; private static boolean runOver = false; @@ -85,6 +88,7 @@ public class Phase { } if (floor != null) { if (floor.contains("7")) inFloor7 = true; + if (floor.contains("M")) inMasterMode = true; } return false; @@ -95,6 +99,7 @@ public class Phase { floor = null; currentPhase = -1; inFloor7 = false; + inMasterMode = false; stormDead = false; runOver = false; } @@ -172,6 +177,10 @@ public class Phase { return inFloor7; } + public static boolean isInMasterMode() { + return inMasterMode; + } + public static boolean runStarted() { return currentPhase >= 0; } @@ -209,7 +218,7 @@ public class Phase { } public static boolean inP5() { - return currentPhase == 9 && inFloor7; + return currentPhase == 9 && inFloor7 && inMasterMode; } public static boolean runOver() { @@ -218,7 +227,7 @@ public class Phase { public static double getPhaseTime(int index) { - if (index < 0 ||index >= currentSplits.size()) return 0; + if (index < 0 || index >= currentSplits.size()) return 0; return currentSplits.get(index).getRealTime(); } |
- made odin loadout keybinds compatible - added custom leap message - improved leap notification regions查看变更src/main/java/blade/addon/features/dungeon/LeapMessage.java | 6 ++---- src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 4 ++-- src/main/java/blade/addon/features/other/SelectedPet.java | 40 ++++++++++++++++++++++++---------------- src/main/java/blade/addon/mixin/MultiPlayerGameModeMixin.java | 20 ++++++++++++++++++++ src/main/java/blade/addon/utils/Commands.java | 3 +++ src/main/java/blade/addon/utils/config/Config.java | 3 ++- src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ src/main/java/blade/addon/utils/dungeon/FillHelper.java | 1 + src/main/java/blade/addon/utils/events/CustomEvents.java | 4 ++-- src/main/java/blade/addon/utils/events/interfaces/LeapEvent.java | 4 +--- src/main/resources/blade-addons.mixins.json | 27 ++++++++++++++------------- 11 files changed, 74 insertions(+), 41 deletions(-) @@ -7,15 +7,13 @@ import net.minecraft.client.multiplayer.ClientPacketListener; public class LeapMessage { - private static final int INDEX_REMOVAL = 9; - public static void init() { - Events.ON_LEAP.register(message -> { + Events.ON_LEAP.register(name -> { if (!Dungeons.enableLeapMessages) return false; ClientPacketListener networkHandler = Minecraft.getInstance().getConnection(); if (networkHandler == null) return false; - networkHandler.sendCommand("pc " + message.getString().substring(INDEX_REMOVAL)); + networkHandler.sendCommand("pc " + Dungeons.customLeapMessage.replace("<player>", name)); return false; }); } @@ -26,8 +26,8 @@ public class LeapNotification { private static final AABB[] REGIONS = { new AABB(91, 105, 46, 111, 127, 123), new AABB(17, 106, 121, 108, 145, 143), - new AABB(-2, 106, 51, 20, 145, 142), - new AABB(-1, 26, 29, 191, 145, 58), + new AABB(-2, 106, 51, 20, 145, 128), + new AABB( 20, 26, 29, 191, 145, 58), new AABB(3, 5, 0, 128, 48, 140) }; @@ -17,6 +17,9 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.resources.Identifier; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerInput; import java.util.List; import java.util.regex.Matcher; @@ -77,6 +80,7 @@ public class SelectedPet { summonPet(name, Component.literal(textName), getLevel(unformattedLine), true); } + return false; }); @@ -113,28 +117,32 @@ public class SelectedPet { return false; }); - Events.ON_SLOT_CLICKED.register((slot, slotId, button,clickType) -> { - if (!inLoadout || button != 0) return false; + ClientTickEvents.END_LEVEL_TICK.register((world -> { + tick = Math.max(tick - 1, 0); + })); - Component component = ItemUtil.findLore(slot.getItem(), "Pet: "); - if (component == null) return false; + } - String string = component.getString(); - Matcher matcher = TAB_PET_PATTERN.matcher(string); - if (matcher.find()) { - String petName = matcher.group(1).replace(" ✦", ""); - Style style = getStyle(component, petName); - summonPet(petName, Component.literal(petName).setStyle(style), getLevel(string), false); - } + public static void testLoadoutClick(int container, int slotId, int button, ContainerInput containerInput, Player player) { + if (!inLoadout || button != 0 || player == null) return; + AbstractContainerMenu containerMenu = player.containerMenu; + if (containerMenu == null) { + Misc.addChatMessage(Component.literal("container is null")); + return; + } - return false; - }); + Component component = ItemUtil.findLore(containerMenu.getSlot(slotId).getItem(), "Pet: "); + if (component == null) return; - ClientTickEvents.END_LEVEL_TICK.register((world -> { - tick = Math.max(tick - 1, 0); - })); + String string = component.getString(); + Matcher matcher = TAB_PET_PATTERN.matcher(string); + if (matcher.find()) { + String petName = matcher.group(1).replace(" ✦", ""); + Style style = getStyle(component, petName); + summonPet(petName, Component.literal(petName).setStyle(style), getLevel(string), false); + } } private static void despawnPet() { @@ -0,0 +1,20 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SelectedPet; +import net.minecraft.client.multiplayer.MultiPlayerGameMode; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ContainerInput; +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(MultiPlayerGameMode.class) +public class MultiPlayerGameModeMixin { + + @Inject(method = "handleContainerInput", at=@At("HEAD")) + public void handleInventoryMouseClick(int container, int slotId, int button, ContainerInput containerInput, Player player, CallbackInfo ci) { + SelectedPet.testLoadoutClick(container, slotId, button, containerInput, player); + } + +} @@ -44,6 +44,9 @@ public class Commands { .then(ClientCommands.literal("ij").executes(context -> FillHelper.fillItem(FillHelper.INFLATABLE_JERRY, 64, 64, false))) + .then(ClientCommands.literal("sp").executes(context -> FillHelper.fillItem(FillHelper.SPRIT_LEAP, 16, 16, false))) + + .then(ClientCommands.literal("refill") .executes( context -> { @@ -77,7 +77,7 @@ public class Config { ConfigSection deathMessage = new ConfigSection(Component.literal("Death message")); deathMessage.add(new ConfigBool(Component.literal("Send death message"), () -> Dungeons.sendDeathMessage, bool -> Dungeons.sendDeathMessage = bool)); - deathMessage.add(new ConfigString(Component.literal("Message sent (<player> replaces with the players name) "), () -> Dungeons.deathMessage, str -> Dungeons.deathMessage = str)); + deathMessage.add(new ConfigString(Component.literal("Message sent, (<player> gets replaced with the players name) "), () -> Dungeons.deathMessage, str -> Dungeons.deathMessage = str)); //dungeons.add(deathMessage); ConfigSection invincibility = new ConfigSection(Component.literal("Invincibility Timer")); @@ -121,6 +121,7 @@ public class Config { dungeons.add(chests); dungeons.add(new ConfigBool(Component.literal("Leap message"), () -> Dungeons.enableLeapMessages, bool -> Dungeons.enableLeapMessages = bool)); + dungeons.add(new ConfigString(Component.literal("Custom leap message, (<player> gets replaced with the players name)"), () -> Dungeons.customLeapMessage, str -> Dungeons.customLeapMessage = str)); dungeons.add(new ConfigBool(Component.literal("Auto requeue"), () -> Dungeons.enableAutoRequeue, bool -> Dungeons.enableAutoRequeue = bool)); ConfigSection expo = new ConfigSection(Component.literal("Explosive shot")); @@ -160,4 +160,7 @@ public class Dungeons { @ConfigValue public static boolean dontHighlightVisibleTeammates = false; + + @ConfigValue + public static String customLeapMessage = "Leaped to <player>!"; } @@ -12,6 +12,7 @@ public class FillHelper { public static final String SUPERBOOM_TNT = "Superboom TNT"; public static final String INFLATABLE_JERRY = "Inflatable Jerry"; public static final String DECOY = "Decoy"; + public static final String SPRIT_LEAP = "Spirit Leap"; /** * @param itemName Name of item @@ -10,7 +10,7 @@ import java.util.regex.Pattern; public class CustomEvents { private static final Pattern PARTY_PATTERN = Pattern.compile("^§9Party §8>"); - private static final Pattern LEAP_PATTERN = Pattern.compile("^You have teleported to .*!$"); + private static final Pattern LEAP_PATTERN = Pattern.compile("^You have teleported to (.*)!$"); private static final int PARTY_MSG_OFFSET = 11; @@ -49,7 +49,7 @@ public class CustomEvents { Matcher matcher = LEAP_PATTERN.matcher(string); if (!matcher.find()) return; - Events.ON_LEAP.invoke(leapEvent -> leapEvent.onLeap(message)); + Events.ON_LEAP.invoke(leapEvent -> leapEvent.onLeap(matcher.group(1))); } }); } @@ -1,7 +1,5 @@ package blade.addon.utils.events.interfaces; -import net.minecraft.network.chat.Component; - public interface LeapEvent { - boolean onLeap(Component message); + boolean onLeap(String name); } @@ -3,16 +3,16 @@ "package": "blade.addon.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "LevelChunkMixin", - "ConnectionMixin", + "ArrowLayerMixin", "ClientPacketListenerMixin", + "ConnectionMixin", "EnderPearlItemMixin", "EntityMixin", + "InventoryMixin", "ItemStackMixin", + "LevelChunkMixin", "LivingEntityMixin", - "InventoryMixin", - "ShovelItemMixin", - "ArrowLayerMixin" + "ShovelItemMixin" ], "injectors": { "defaultRequire": 1 @@ -21,24 +21,25 @@ "requireAnnotations": true }, "client": [ + "AbstractContainerScreenMixin", "BossHealthOverlayMixin", "ChatComponentMixin", "ChatScreenMixin", - "LocalPlayerMixin", "ClientPacketListenerMixin", - "GuiGraphicsExtractorMixin", - "EntityRendererMixin", + "EffectsInInventoryMixin", "EntityRenderDispatcherMixin", - "AbstractContainerScreenMixin", - "HeldItemRendererMixin", + "EntityRendererMixin", + "GuiGraphicsExtractorMixin", "GuiMixin", + "HeldItemRendererMixin", "InventoryScreenMixin", "KeyboardHandlerMixin", + "LocalPlayerMixin", "MinecraftMixin", "MouseHandlerMixin", - "RecipeBookScreenMixin", + "MultiPlayerGameModeMixin", "RecipeBookComponentMixin", - "SkullBlockRendererMixin", - "EffectsInInventoryMixin" + "RecipeBookScreenMixin", + "SkullBlockRendererMixin" ] } \ No newline at end of file |
- added death messages - made none uuid items protectable - added hide visible teammate's highlight查看变更src/main/java/blade/addon/Bladeaddons.java | 2 +- src/main/java/blade/addon/features/dungeon/DeathMessage.java | 29 +++++++++++++---------------- src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 1 + src/main/java/blade/addon/features/item/ProtectItem.java | 29 +++++++++++++++++++---------- src/main/java/blade/addon/utils/config/Config.java | 3 ++- src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 11 +++++++++++ 7 files changed, 50 insertions(+), 28 deletions(-) @@ -129,7 +129,7 @@ public class Bladeaddons implements ModInitializer { DragonTracer.init(); ReaperDisplay.init(); StormLBTimer.init(); - //DeathMessage.init(); TODO finish this + DeathMessage.init(); BlockPetMenu.init(); } } \ No newline at end of file @@ -2,6 +2,7 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; @@ -11,11 +12,7 @@ import java.util.regex.Pattern; public class DeathMessage { - private static final Pattern[] patterns = new Pattern[]{ - Pattern.compile("^ ☠ (.*) was killed by *."), - Pattern.compile("^ ☠ (.*) died to a *."), - Pattern.compile("^ ☠ (.*) fell to their death *."), - }; + private static final Pattern PATTERN = Pattern.compile("^ ☠ (.+) and became a ghost\\.$"); public static void init() { @@ -24,17 +21,17 @@ public class DeathMessage { if (!Location.inDungeon() || !Dungeons.sendDeathMessage) return false; String msg = text.getString(); - for(Pattern pattern: patterns) { - Matcher matcher = pattern.matcher(msg); - if (matcher.find()) { - String name = matcher.group(1); - - ClientPacketListener networkHandler = Minecraft.getInstance().getConnection(); - if (networkHandler == null) return false; - networkHandler.sendCommand("pc " + createMessage(name)); - return false; - } - } + + Matcher matcher = PATTERN.matcher(msg); + if (!matcher.find()) return false; + + String message = matcher.group(1); + String name = DungeonClass.getNameFromMessage(message); + if (name == null) return false; + + ClientPacketListener networkHandler = Minecraft.getInstance().getConnection(); + if (networkHandler == null) return false; + networkHandler.sendCommand("pc " + createMessage(name)); return false; }); @@ -51,6 +51,7 @@ public class TeammateHighlight { teammates.forEach(player -> { if (Dungeons.dontHighlightHiddenTeammates && HidePlayers.shouldHidePlayers(player)) return; + if (Dungeons.dontHighlightVisibleTeammates && !HidePlayers.shouldHidePlayers(player)) return; DungeonClass clazz = DungeonClass.getClass(player); if (clazz == null) return; @@ -51,18 +51,24 @@ public class ProtectItem { } ItemStack item = player.getInventory().getSelectedItem(); - String uuid = ItemUtil.getUuid(item); - if (uuid == null) { - Misc.addChatMessage(Component.literal("Cant protect this item, it does not have a uuid")); + String saveString = ItemUtil.getUuid(item); + + if (saveString == null) { + saveString = ItemUtil.getId(item); + } + + if (saveString == null) { + Misc.addChatMessage(Component.literal("Cant protect this item, the item does not have a uuid or id")); return; } + ProtectedItemHolder holder = (ProtectedItemHolder) (Object) item; - if (protectedItems.contains(uuid)) { - protectedItems.remove(uuid); + if (protectedItems.contains(saveString)) { + protectedItems.remove(saveString); holder.blade_addons$setProtected(false); Misc.addChatMessage(Component.literal("Item ").append(item.getHoverName()).append(" is NOT protected anymore")); } else { - protectedItems.add(uuid); + protectedItems.add(saveString); holder.blade_addons$setProtected(true); Misc.addChatMessage(Component.literal("Item ").append(item.getHoverName()).append(" is protected")); } @@ -72,14 +78,17 @@ public class ProtectItem { public static boolean protect(ItemStack stack) { if (stopProtectItem) return false; - String uuid = ItemUtil.getUuid(stack); + String saveString = ItemUtil.getUuid(stack); + + if (saveString == null) { + saveString = ItemUtil.getId(stack); + } - //TODO: add smth for non uuid items - if (uuid == null) { + if (saveString == null) { return false; } - return protectedItems.contains(uuid); + return protectedItems.contains(saveString); } private static void draw(GuiGraphicsExtractor context, ItemStack stack, int x, int y) { @@ -107,7 +107,8 @@ public class Config { hidePlayers.add(new ConfigBool(Component.literal("SS only hides before terms"), () -> Dungeons.hideBeforeTermsOnly, bool -> Dungeons.hideBeforeTermsOnly = bool)); hidePlayers.add(new ConfigBool(Component.literal("Hide players in range"), () -> Dungeons.hidePlayersInRange, bool -> Dungeons.hidePlayersInRange = bool)); hidePlayers.add(new ConfigDouble(Component.literal("Hiding range"), () -> Dungeons.hidePlayerRange, num -> Dungeons.hidePlayerRange = num, 1, 0, 7)); - hidePlayers.add(new ConfigBool(Component.literal("Hide teammate highlight"), () -> Dungeons.dontHighlightHiddenTeammates, bool -> Dungeons.dontHighlightHiddenTeammates = bool)); + hidePlayers.add(new ConfigBool(Component.literal("Hide hidden teammate's highlight"), () -> Dungeons.dontHighlightHiddenTeammates, bool -> Dungeons.dontHighlightHiddenTeammates = bool)); + hidePlayers.add(new ConfigBool(Component.literal("Hide visible teammate's highlight"), () -> Dungeons.dontHighlightVisibleTeammates, bool -> Dungeons.dontHighlightVisibleTeammates = bool)); dungeons.add(hidePlayers); @@ -157,4 +157,7 @@ public class Dungeons { @ConfigValue public static boolean blockRemovingPet = false; + + @ConfigValue + public static boolean dontHighlightVisibleTeammates = false; } @@ -9,6 +9,8 @@ import blade.addon.utils.events.Events; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; + +import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -98,6 +100,15 @@ public enum DungeonClass { return nameClassMap.containsKey(name); } + public static String getNameFromMessage(String message) { + for (Iterator<String> it = nameClassMap.keys().asIterator(); it.hasNext(); ) { + String name = it.next(); + if (message.contains(name)) return name; + } + + return null; + } + public static int getColor(DungeonClass dungeonClass) { if (dungeonClass == null) return 0xffffffff; |
- added storm lb timer查看变更src/main/java/blade/addon/Bladeaddons.java | 4 +++- src/main/java/blade/addon/features/dungeon/f7/StormLBTimer.java | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 5 +++++ src/main/java/blade/addon/utils/config/components/Components.java | 39 +++++++++++++-------------------------- src/main/java/blade/addon/utils/config/values/Floor7.java | 6 ++++++ 5 files changed, 81 insertions(+), 27 deletions(-) @@ -4,6 +4,7 @@ import blade.addon.features.dungeon.*; import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; +import blade.addon.features.dungeon.f7.StormLBTimer; import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; import blade.addon.features.dungeon.f7.dragons.DragonHealth; import blade.addon.features.dungeon.f7.dragons.DragonTracer; @@ -127,7 +128,8 @@ public class Bladeaddons implements ModInitializer { CurrentSection.init(); DragonTracer.init(); ReaperDisplay.init(); - BlockPetMenu.init(); + StormLBTimer.init(); //DeathMessage.init(); TODO finish this + BlockPetMenu.init(); } } \ No newline at end of file @@ -0,0 +1,54 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.GuiGraphicsExtractor; + +public class StormLBTimer { + + private static final int BASE_LB_TICK = 20 * 34; + private static final int DISPLAY_DURATION_TICK = 20 * 5; + + private static int tick = 0; + + public static void init() { + Events.ON_SERVER_TICK.register(() -> { + if (Location.inDungeon() && Phase.inP2() && !Phase.stormDead()) tick++; + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + if (Location.inDungeon()) { + tick = 0; + } + return false; + }); + } + + private static int getCurrentTickTime() { + return BASE_LB_TICK + Floor7.lbTickOffset - tick; + } + + private static boolean validTime() { + int deltaTick = getCurrentTickTime(); + return deltaTick > 0 && deltaTick <= DISPLAY_DURATION_TICK; + + } + + public static boolean display() { + return Floor7.showLBTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead() && validTime() && DungeonClass.isClass(DungeonClass.ARCHER); + } + + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { + int deltaTick = getCurrentTickTime(); + double num = deltaTick * Constants.TICK_DURATION; + RenderUtils.drawTimer(component, graphics, num, RenderUtils.getStatusColor(60, 30, deltaTick)); + } + +} @@ -245,6 +245,11 @@ public class Config { dragon.add(new ConfigBool(Component.literal("Render dragon spawn tracer"), () -> Floor7.dragonTracer, bool -> Floor7.dragonTracer = bool)); floor7.add(dragon); + ConfigSection stormlb = new ConfigSection(Component.literal("Storm lb")); + stormlb.add(new ConfigBool(Component.literal("Enable"), () -> Floor7.showLBTimer, bool -> Floor7.showLBTimer = bool)); + stormlb.add(new ConfigInt(Component.literal("Tick offset (34:00 is at 0)"), () -> Floor7.lbTickOffset, num -> Floor7.lbTickOffset = num, 1, 0, 20)); + floor7.add(stormlb); + return floor7; } @@ -1,38 +1,22 @@ package blade.addon.utils.config.components; -import blade.addon.features.dungeon.BloodNotifier; -import blade.addon.features.dungeon.ChestCounter; -import blade.addon.features.dungeon.QuizTimer; -import blade.addon.features.dungeon.RunStartValidator; -import blade.addon.features.dungeon.KeyNotifier; -import blade.addon.features.dungeon.SecretSpawnTimer; -import blade.addon.features.dungeon.WarpCooldown; -import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; -import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; -import blade.addon.features.dungeon.f7.storm.DistanceToLedge; -import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; -import blade.addon.features.dungeon.f7.storm.PillarExplode; +import blade.addon.features.dungeon.*; import blade.addon.features.dungeon.f7.RelicTimer; -import blade.addon.features.dungeon.f7.storm.StormTickTimer; +import blade.addon.features.dungeon.f7.StormLBTimer; +import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.location.LocationNotifier; +import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; import blade.addon.features.dungeon.f7.maxor.MaxorStun; -import blade.addon.features.dungeon.f7.terms.CurrentSection; -import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; -import blade.addon.features.dungeon.f7.terms.LeapNotification; -import blade.addon.features.dungeon.f7.terms.MelodyWarning; -import blade.addon.features.dungeon.f7.terms.DeviceNotifier; -import blade.addon.features.dungeon.f7.terms.SectionCompletion; -import blade.addon.features.dungeon.f7.terms.SectionProgress; -import blade.addon.features.dungeon.f7.terms.TermStartTimer; +import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; +import blade.addon.features.dungeon.f7.storm.DistanceToLedge; +import blade.addon.features.dungeon.f7.storm.PillarExplode; +import blade.addon.features.dungeon.f7.storm.StormTickTimer; +import blade.addon.features.dungeon.f7.terms.*; import blade.addon.features.item.HeldItemToolTip; -import blade.addon.features.other.ArrowSwapper; -import blade.addon.features.other.KickedTimer; -import blade.addon.features.other.RagDisplay; -import blade.addon.features.other.ReaperDisplay; -import blade.addon.features.other.SelectedPet; import blade.addon.features.notifications.Notifications; +import blade.addon.features.other.*; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.config.values.Floor7; @@ -169,4 +153,7 @@ public class Components { @ConfigValue public static HUDComponent reaperDisplay = new HUDComponent(0, 0, TICK_TIMER_WIDTH, 10, 1, "reaper display", ReaperDisplay::display, ReaperDisplay::render, () -> ExtraOptions.enableReaperDisplay); + + @ConfigValue + public static HUDComponent stormLbTimer = new HUDComponent(0, 0, TICK_TIMER_WIDTH, 10, 1, "Storm lb timer", StormLBTimer::display, StormLBTimer::render, () -> Floor7.showLBTimer); } @@ -183,4 +183,10 @@ public class Floor7 { @ConfigValue public static boolean assumeSplitEE2 = false; + + @ConfigValue + public static boolean showLBTimer = false; + + @ConfigValue + public static int lbTickOffset = 10; } |
- added block "convert pet to item" while in a run查看变更src/main/java/blade/addon/Bladeaddons.java | 1 + src/main/java/blade/addon/features/other/BlockPetMenu.java | 30 ++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/SelectedPet.java | 2 +- src/main/java/blade/addon/mixin/AbstractContainerScreenMixin.java | 19 +++++++++++-------- src/main/java/blade/addon/utils/config/Config.java | 1 + src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ src/main/java/blade/addon/utils/events/interfaces/SlotClickEvent.java | 2 +- 7 files changed, 48 insertions(+), 10 deletions(-) @@ -127,6 +127,7 @@ public class Bladeaddons implements ModInitializer { CurrentSection.init(); DragonTracer.init(); ReaperDisplay.init(); + BlockPetMenu.init(); //DeathMessage.init(); TODO finish this } } \ No newline at end of file @@ -0,0 +1,30 @@ +package blade.addon.features.other; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.events.Events; + +public class BlockPetMenu { + + private static boolean inPetMenu = false; + + public static void init() { + Events.ON_SCREEN.register(screen -> { + if (screen == null) { + inPetMenu = false; + return false; + } + + inPetMenu = screen.getTitle().getString().contains("Pets"); + return false; + }); + + Events.ON_SLOT_CLICKED.register((slot,slotId, button, containerInput) -> { + if (inPetMenu && button == 1 && Dungeons.blockRemovingPet && Location.inDungeon()) { + return slotId >= 9 && slotId <= 44; + } + return false; + }); + } + +} @@ -113,7 +113,7 @@ public class SelectedPet { return false; }); - Events.ON_SLOT_CLICKED.register((slot, button,clickType) -> { + Events.ON_SLOT_CLICKED.register((slot, slotId, button,clickType) -> { if (!inLoadout || button != 0) return false; Component component = ItemUtil.findLore(slot.getItem(), "Pet: "); @@ -36,7 +36,7 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe super(title); } - @Inject(method = "extractRenderState", at=@At("TAIL")) + @Inject(method = "extractRenderState", at = @At("TAIL")) private static void render(GuiGraphicsExtractor graphics, int mouseX, int mouseY, float deltaTicks, CallbackInfo ci) { SearchBar.render(graphics, mouseX, mouseY, deltaTicks); } @@ -58,17 +58,18 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe DrawEvents.INVENTORY_SLOT_AFTER.invoke(event -> event.draw(graphics, stack, x, y)); } - @Inject(method = "keyPressed", at=@At("HEAD"), cancellable = true) + @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true) private void keyPressed(KeyEvent input, CallbackInfoReturnable<Boolean> cir) { if (SearchBar.keyPressed(input)) cir.setReturnValue(false); } - @Inject(method = "mouseClicked", at=@At("HEAD")) + @Inject(method = "mouseClicked", at = @At("HEAD")) private void onMouseClick(MouseButtonEvent click, boolean doubled, CallbackInfoReturnable<Boolean> cir) { SearchBar.onMouseClick(click); } - @Inject(method ="slotClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;onMouseClickAction(Lnet/minecraft/world/inventory/Slot;Lnet/minecraft/world/inventory/ContainerInput;)V"), cancellable = true) - public void protectItem(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci){ + + @Inject(method = "slotClicked", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;onMouseClickAction(Lnet/minecraft/world/inventory/Slot;Lnet/minecraft/world/inventory/ContainerInput;)V"), cancellable = true) + public void protectItem(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) { ItemStack held = menu.getCarried(); @@ -92,12 +93,14 @@ public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMe } } - @Inject(method = "slotClicked", at=@At("HEAD")) + @Inject(method = "slotClicked", at = @At("HEAD"), cancellable = true) public void slotClicked(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) { - Events.ON_SLOT_CLICKED.invoke(slotEvent -> slotEvent.onSlot(slot, buttonNum, containerInput)); + if (Events.ON_SLOT_CLICKED.invoke(slotEvent -> slotEvent.onSlot(slot, slotId, buttonNum, containerInput))) { + ci.cancel(); + } } - @Inject(method = "init", at=@At("HEAD")) + @Inject(method = "init", at = @At("HEAD")) public void init(CallbackInfo ci) { Events.ON_SCREEN.invoke(screenEvent -> screenEvent.onScreen(this)); } @@ -143,6 +143,7 @@ public class Config { dungeons.add(new ConfigBool(Component.literal("Draw boss health numbers"), () -> Dungeons.bossHealthNumbers, bool -> Dungeons.bossHealthNumbers = bool)); dungeons.add(new ConfigBool(Component.literal("Blood notifier on first 4 spawned"), () -> Dungeons.alertBloodSpawns, bool -> Dungeons.alertBloodSpawns = bool)); dungeons.add(new ConfigBool(Component.literal("Blood notifier on all classes"), () -> Dungeons.alertBloodForAllClasses, bool -> Dungeons.alertBloodForAllClasses = bool)); + dungeons.add(new ConfigBool(Component.literal("Block \"convert pet to item\""), () -> Dungeons.blockRemovingPet, bool -> Dungeons.blockRemovingPet = bool)); return dungeons; } @@ -154,4 +154,7 @@ public class Dungeons { @ConfigValue public static String deathMessage = ""; + + @ConfigValue + public static boolean blockRemovingPet = false; } @@ -4,5 +4,5 @@ import net.minecraft.world.inventory.ContainerInput; import net.minecraft.world.inventory.Slot; public interface SlotClickEvent { - boolean onSlot(Slot slot, int button, ContainerInput containerInput); + boolean onSlot(Slot slot, int slotId, int button, ContainerInput containerInput); } |
- added shift click to only copy one line查看变更src/main/java/blade/addon/mixin/ChatScreenMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -43,7 +43,7 @@ public class ChatScreenMixin { if (index < 0 || index >= messages.size()) return; String string; - if (ExtraOptions.copyLineOnly) { + if (ExtraOptions.copyLineOnly || click.hasShiftDown()) { GuiMessage.Line msg = messages.get(index); string = TextUtil.orderedTextToString(msg.content()); } else { |
- fixed chat scale breaking copy chat - changed blaze name tag hider to only work in dungeons查看变更src/main/java/blade/addon/mixin/ChatScreenMixin.java | 6 ++++-- src/main/java/blade/addon/mixin/EntityRendererMixin.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) @@ -34,8 +34,10 @@ public class ChatScreenMixin { if (hudAccessor.width() + 4 < click.x()) return; - final int n = (int) (9 * (mc.options.chatLineSpacing().get() + 1.0)); - int index = (int) (Mth.floor((mc.getWindow().getGuiScaledHeight() - 40) / hudAccessor.scale()) - click.y()) / n + hudAccessor.getScrolledLines(); + final int n = (int) (9 * (mc.options.chatLineSpacing().get() + 1.0) * hudAccessor.scale()); + int index = (int) (Mth.floor(mc.getWindow().getGuiScaledHeight() - 40) - click.y()) / n + hudAccessor.getScrolledLines(); + + System.out.println(index + " " + hudAccessor.getScrolledLines()); List<GuiMessage.Line> messages = hudAccessor.getVisibleMessages(); if (index < 0 || index >= messages.size()) return; @@ -21,7 +21,7 @@ public class EntityRendererMixin<T extends Entity, S extends EntityRenderState> @Inject(method = "extractRenderState", at = @At("TAIL")) public void hideFire(T entity, S state, float tickProgress, CallbackInfo ci) { - if (Dungeons.hideBlazeNameTag && state.nameTag != null) { + if (Dungeons.hideBlazeNameTag && state.nameTag != null && Location.inDungeon()) { if (state.nameTag.getString().contains("Blaze")) { state.nameTag = null; } |
- mightve improved kicked detection查看变更src/main/java/blade/addon/features/other/KickedTimer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -17,7 +17,7 @@ public class KickedTimer { String string = text.getString(); if (string == null) return false; - if (string.equals("You were kicked while joining that server!")) { + if (string.equals("You were kicked while joining that server!") || string.equals("You are no longer allowed to access this instance!")) { kickedTime = System.currentTimeMillis(); isKicked = true; } |
- fixed loadouts breaking pet display查看变更src/main/java/blade/addon/features/other/SelectedPet.java | 33 +++++++++++++++++++++++++++++++++
src/main/java/blade/addon/mixin/{HandledScreenMixin.java => AbstractContainerScreenMixin.java} | 15 +++++++++++++--
src/main/java/blade/addon/mixin/MinecraftMixin.java | 6 ++++++
src/main/java/blade/addon/utils/data/ItemUtil.java | 28 +++++++++++++++++++++++-----
src/main/java/blade/addon/utils/events/Events.java | 27 ++++++---------------------
src/main/java/blade/addon/utils/events/interfaces/ScreenEvent.java | 7 +++++++
src/main/java/blade/addon/utils/events/interfaces/SlotClickEvent.java | 8 ++++++++
src/main/resources/blade-addons.mixins.json | 2 +-
8 files changed, 97 insertions(+), 29 deletions(-)@@ -3,6 +3,7 @@ package blade.addon.features.other; import blade.addon.utils.Constants; import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.ItemUtil; import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -44,6 +45,8 @@ public class SelectedPet { private static Identifier spriteId = null; private static int tick = 0; + private static boolean inLoadout = false; + public static void init() { Events.ON_GAME_MESSAGE.register(message -> { String string = message.getString(); @@ -98,6 +101,36 @@ public class SelectedPet { return false; }); + Events.ON_SCREEN.register(screen -> { + if (screen == null) { + inLoadout = false; + return false; + } + + Component title = screen.getTitle(); + inLoadout = title.getString().contains(") Loadouts"); + + return false; + }); + + Events.ON_SLOT_CLICKED.register((slot, button,clickType) -> { + if (!inLoadout || button != 0) return false; + + Component component = ItemUtil.findLore(slot.getItem(), "Pet: "); + if (component == null) return false; + + String string = component.getString(); + Matcher matcher = TAB_PET_PATTERN.matcher(string); + if (matcher.find()) { + String petName = matcher.group(1).replace(" ✦", ""); + Style style = getStyle(component, petName); + summonPet(petName, Component.literal(petName).setStyle(style), getLevel(string), false); + } + + + return false; + }); + ClientTickEvents.END_LEVEL_TICK.register((world -> { tick = Math.max(tick - 1, 0); })); @@ -2,6 +2,7 @@ package blade.addon.mixin; import blade.addon.features.item.ProtectItem; import blade.addon.features.other.SearchBar; +import blade.addon.utils.events.Events; import blade.addon.utils.rendering.DrawEvents; import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.screens.Screen; @@ -23,7 +24,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(AbstractContainerScreen.class) -public abstract class HandledScreenMixin<T extends AbstractContainerMenu> extends Screen { +public abstract class AbstractContainerScreenMixin<T extends AbstractContainerMenu> extends Screen { @Shadow @Final @@ -31,7 +32,7 @@ public abstract class HandledScreenMixin<T extends AbstractContainerMenu> extend @Unique private static final int INVALID_SLOT_ID = -999; - protected HandledScreenMixin(Component title) { + protected AbstractContainerScreenMixin(Component title) { super(title); } @@ -90,4 +91,14 @@ public abstract class HandledScreenMixin<T extends AbstractContainerMenu> extend } } } + + @Inject(method = "slotClicked", at=@At("HEAD")) + public void slotClicked(Slot slot, int slotId, int buttonNum, ContainerInput containerInput, CallbackInfo ci) { + Events.ON_SLOT_CLICKED.invoke(slotEvent -> slotEvent.onSlot(slot, buttonNum, containerInput)); + } + + @Inject(method = "init", at=@At("HEAD")) + public void init(CallbackInfo ci) { + Events.ON_SCREEN.invoke(screenEvent -> screenEvent.onScreen(this)); + } } @@ -5,6 +5,7 @@ import blade.addon.utils.events.Events; import blade.addon.utils.events.interfaces.WorldEvent; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.BlockHitResult; @@ -42,4 +43,9 @@ public class MinecraftMixin { private void onWorld(ClientLevel world, CallbackInfo ci) { Events.ON_WORLD_CHANGE.invoke(WorldEvent::onWorldSwap); } + + @Inject(method = "setScreen", at=@At("HEAD")) + public void onClose(Screen screen, CallbackInfo ci) { + if (screen == null) Events.ON_SCREEN.invoke(screenEvent -> screenEvent.onScreen(null)); + } } @@ -43,20 +43,38 @@ public class ItemUtil { } public static boolean containsLore(ItemStack item, String contain) { - if (item ==null) return false; + List<Component> lines = getLore(item); + if (lines == null) return false; + + for (Component line : lines.reversed()) { + String string = line.getString(); + if (string.contains(contain)) { + return true; + } + } + return false; + } + + public static List<Component> getLore(ItemStack item) { + if (item ==null) return null; ItemLore lore = item.get(DataComponents.LORE); - if (lore == null) return false; + if (lore == null) return null; List<Component> lines = lore.lines(); - if (lines.isEmpty()) return false; + return lines; + } + + public static Component findLore(ItemStack item, String contain) { + List<Component> lines = getLore(item); + if (lines == null) return null; for (Component line : lines.reversed()) { String string = line.getString(); if (string.contains(contain)) { - return true; + return line; } } - return false; + return null; } public static boolean containsIgnoreCaseLore(ItemStack item, String contain) { @@ -1,25 +1,6 @@ package blade.addon.utils.events; -import blade.addon.utils.events.interfaces.BlockEntityEvent; -import blade.addon.utils.events.interfaces.BlockInteractionEvent; -import blade.addon.utils.events.interfaces.EntityEvent; -import blade.addon.utils.events.interfaces.GameMessageEvent; -import blade.addon.utils.events.interfaces.LeapEvent; -import blade.addon.utils.events.interfaces.LocationChangeEvent; -import blade.addon.utils.events.interfaces.PacketEvent; -import blade.addon.utils.events.interfaces.ParticleEvent; -import blade.addon.utils.events.interfaces.PartyMessageEvent; -import blade.addon.utils.events.interfaces.PetEvent; -import blade.addon.utils.events.interfaces.PhaseEvent; -import blade.addon.utils.events.interfaces.PlaySoundEvent; -import blade.addon.utils.events.interfaces.PlayerListEvent; -import blade.addon.utils.events.interfaces.RunEndEvent; -import blade.addon.utils.events.interfaces.ScoreBoardEvent; -import blade.addon.utils.events.interfaces.SectionEvent; -import blade.addon.utils.events.interfaces.ServerTickEvent; -import blade.addon.utils.events.interfaces.SlotChangeEvent; -import blade.addon.utils.events.interfaces.TerminalEvent; -import blade.addon.utils.events.interfaces.WorldEvent; +import blade.addon.utils.events.interfaces.*; public class Events { public static final EventHandler<ServerTickEvent> ON_SERVER_TICK = new EventHandler<>(); @@ -49,8 +30,12 @@ public class Events { public static final EventHandler<BlockEntityEvent> ON_BLOCK_ENTITY = new EventHandler<>(); - public static final EventHandler<ParticleEvent> ON_PARTICLE = new EventHandler<>(); public static final EventHandler<PacketEvent> ON_PACKET = new EventHandler<>(); + //screen + public static final EventHandler<ScreenEvent> ON_SCREEN = new EventHandler<>(); + public static final EventHandler<SlotClickEvent> ON_SLOT_CLICKED = new EventHandler<>(); + + } @@ -0,0 +1,7 @@ +package blade.addon.utils.events.interfaces; + +import net.minecraft.client.gui.screens.Screen; + +public interface ScreenEvent { + boolean onScreen(Screen screen); +} @@ -0,0 +1,8 @@ +package blade.addon.utils.events.interfaces; + +import net.minecraft.world.inventory.ContainerInput; +import net.minecraft.world.inventory.Slot; + +public interface SlotClickEvent { + boolean onSlot(Slot slot, int button, ContainerInput containerInput); +} @@ -29,7 +29,7 @@ "GuiGraphicsExtractorMixin", "EntityRendererMixin", "EntityRenderDispatcherMixin", - "HandledScreenMixin", + "AbstractContainerScreenMixin", "HeldItemRendererMixin", "GuiMixin", "InventoryScreenMixin", |
- added missing pet sprites查看变更gradle.properties | 2 +- src/main/java/blade/addon/features/other/SelectedPet.java | 3 +++ src/main/resources/assets/blade-addons/textures/gui/sprites/pets/golden-dragon-egg.png | Bin 0 -> 2647 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/pets/jade-dragon-egg.png | Bin 0 -> 2579 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/pets/rose-dragon-egg.png | Bin 0 -> 2193 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/pets/seal.png | Bin 0 -> 5993 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/pets/sloth.png | Bin 0 -> 3976 bytes 7 files changed, 4 insertions(+), 1 deletion(-) @@ -9,7 +9,7 @@ minecraft_version=26.1.2 loader_version=0.19.3 loom_version=1.17-SNAPSHOT # Mod Properties -mod_version=2.5.1 +mod_version=2.5.2 maven_group=blade.addon archives_base_name=blade-addons # Dependencies @@ -23,6 +23,9 @@ import java.util.regex.Pattern; public class SelectedPet { + //https://hypixelskyblock.minecraft.wiki/w/Pets + //https://cloudconvert.com/to-png + private static final int COLOR_OFFSET = 2; private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (?:\\[[^\\]]+\\] )?(.+)"); |
- upped version查看变更gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -9,7 +9,7 @@ minecraft_version=26.1.2 loader_version=0.19.3 loom_version=1.17-SNAPSHOT # Mod Properties -mod_version=2.5.0 +mod_version=2.5.1 maven_group=blade.addon archives_base_name=blade-addons # Dependencies |
- fixed admins doing stupid shit查看变更src/main/java/blade/addon/utils/dungeon/Phase.java | 2 +- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) @@ -21,7 +21,7 @@ import net.minecraft.network.chat.Component; public class Phase { private static final Pattern END_PATTERN = Pattern.compile("^\\s*☠ Defeated (.+) in 0?([\\dhms ]+)\\s*(\\(NEW RECORD!\\))?$"); - private static final Pattern SEARCH_PATTERN = Pattern.compile("^ ⏣ The Catacombs .*$"); + private static final Pattern SEARCH_PATTERN = Pattern.compile("The Catacombs .*$"); private static final Split DUMMY_SPLIT = new Split("test split", "if this is called idk", "if this is called idk", 43690); @@ -103,9 +103,7 @@ public class RenderUtils { float halfWidth = textRenderer.width(text.getString()) / 2f; - - //context.commandQueue().submitText(matrices, -halfWidth, 0, text.getVisualOrderText(), true, Font.DisplayMode.SEE_THROUGH, 15728880, 0xffffffff, 0, 0); - textRenderer.drawInBatch(text, -halfWidth, 0, 15728880, true, matrices.last().pose(), context.bufferSource(), Font.DisplayMode.SEE_THROUGH, 0, 0xffffffff); + textRenderer.drawInBatch(text, -halfWidth, 0, 0xffffffff, true, matrices.last().pose(), context.bufferSource(), Font.DisplayMode.SEE_THROUGH, 0, 15728880); matrices.popPose(); } |
- bumped version查看变更gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -9,7 +9,7 @@ minecraft_version=26.1.2 loader_version=0.19.3 loom_version=1.17-SNAPSHOT # Mod Properties -mod_version=2.4.1 +mod_version=2.5.0 maven_group=blade.addon archives_base_name=blade-addons # Dependencies |
- fixed readme查看变更README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -4,7 +4,7 @@ A dungeons mod made to port dungeons features to the newer Minecraft versions. H his amazing mods like Valley addons. # Current Version -1.21.10 +26.1.2 # Dependencies - Hypixel Mod API https://modrinth.com/mod/hypixel-mod-api |
- fixed player heads crashing your game查看变更src/main/java/blade/addon/mixin/GuiGraphicsExtractorMixin.java | 5 ++--- src/main/java/blade/addon/utils/config/Config.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) @@ -5,7 +5,6 @@ import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; import org.joml.Matrix3x2fStack; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -40,8 +39,8 @@ public class GuiGraphicsExtractorMixin { } } - @Inject(method = "item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;III)V", at=@At("TAIL")) - private void scaleDown(LivingEntity entity, Level world, ItemStack stack, int x, int y, int seed, CallbackInfo ci) { + @Inject(method = "item(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;III)V", at=@At("TAIL")) + private void scaleDown(LivingEntity owner, ItemStack stack, int x, int y, int seed, CallbackInfo ci) { if (Visual.oldPlayerHead && stack.getItem() == Items.PLAYER_HEAD) { pose.popMatrix(); } @@ -78,7 +78,7 @@ public class Config { ConfigSection deathMessage = new ConfigSection(Component.literal("Death message")); deathMessage.add(new ConfigBool(Component.literal("Send death message"), () -> Dungeons.sendDeathMessage, bool -> Dungeons.sendDeathMessage = bool)); deathMessage.add(new ConfigString(Component.literal("Message sent (<player> replaces with the players name) "), () -> Dungeons.deathMessage, str -> Dungeons.deathMessage = str)); - dungeons.add(deathMessage); + //dungeons.add(deathMessage); ConfigSection invincibility = new ConfigSection(Component.literal("Invincibility Timer")); invincibility.add(new ConfigBool(Component.literal("Enable invincibility display"), () -> Dungeons.displayInvincibilityTimer, bool -> Dungeons.displayInvincibilityTimer = bool)); |
- 26.1.2 port (first launchable version)查看变更.github/workflows/build.yml | 12 +++---
build.gradle | 126 ++++++++++++++++++++++++++++----------------------------------
gradle.properties | 20 ++++------
gradle/wrapper/gradle-wrapper.properties | 5 +--
src/main/java/blade/addon/features/dungeon/BloodNotifier.java | 4 +-
src/main/java/blade/addon/features/dungeon/ChestCounter.java | 11 +++---
src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 4 +-
src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 9 +++--
src/main/java/blade/addon/features/dungeon/QuizTimer.java | 6 +--
src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 13 ++++---
src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 9 +++--
src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 5 ++-
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 6 +--
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 13 ++++---
src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonHealth.java | 7 ++--
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonTracer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 23 ++++++------
src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskHighlight.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 5 ++-
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 5 ++-
src/main/java/blade/addon/features/dungeon/f7/maxor/CrystalSpawn.java | 11 +++---
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorStun.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorTickTimer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/storm/DistanceToLedge.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/storm/PillarExplode.java | 6 +--
src/main/java/blade/addon/features/dungeon/f7/storm/StormTickTimer.java | 9 +++--
src/main/java/blade/addon/features/dungeon/f7/terms/CurrentSection.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/DeviceNotifier.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 5 ++-
src/main/java/blade/addon/features/dungeon/f7/terms/MelodyWarning.java | 11 +++---
src/main/java/blade/addon/features/dungeon/f7/terms/SectionCompletion.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/SectionProgress.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 4 +-
src/main/java/blade/addon/features/filter/FilterEntry.java | 15 ++++----
src/main/java/blade/addon/features/filter/FilterList.java | 13 ++++---
src/main/java/blade/addon/features/highlight/BatHighlight.java | 6 +--
src/main/java/blade/addon/features/highlight/MimicHighlight.java | 7 ++--
src/main/java/blade/addon/features/highlight/MobHighlight.java | 7 ++--
src/main/java/blade/addon/features/highlight/SheepHighlight.java | 7 ++--
src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 5 ++-
src/main/java/blade/addon/features/highlight/WitherHighlight.java | 7 ++--
src/main/java/blade/addon/features/item/HeldItemToolTip.java | 4 +-
src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 7 ++--
src/main/java/blade/addon/features/item/ProtectItem.java | 13 ++++---
src/main/java/blade/addon/features/item/SelectedPetHighlight.java | 7 ++--
src/main/java/blade/addon/features/item/StarCountHighlight.java | 6 +--
src/main/java/blade/addon/features/notifications/NotificationEntry.java | 16 ++++----
src/main/java/blade/addon/features/notifications/NotificationList.java | 17 ++++-----
src/main/java/blade/addon/features/notifications/Notifications.java | 5 ++-
src/main/java/blade/addon/features/other/ArrowSwapper.java | 9 +++--
src/main/java/blade/addon/features/other/InventoryButton.java | 17 +++++----
src/main/java/blade/addon/features/other/KickedTimer.java | 4 +-
src/main/java/blade/addon/features/other/PracticeSS.java | 4 +-
src/main/java/blade/addon/features/other/RagDisplay.java | 6 +--
src/main/java/blade/addon/features/other/ReaperDisplay.java | 4 +-
src/main/java/blade/addon/features/other/SearchBar.java | 8 ++--
src/main/java/blade/addon/features/other/SelectedPet.java | 13 ++++---
src/main/java/blade/addon/features/sound/TubaSound.java | 2 +-
src/main/java/blade/addon/mixin/BossHealthOverlayMixin.java | 2 +-
src/main/java/blade/addon/mixin/ChatComponentMixin.java | 2 +-
src/main/java/blade/addon/mixin/ChatScreenMixin.java | 2 +-
src/main/java/blade/addon/mixin/EffectsInInventoryMixin.java | 10 ++---
src/main/java/blade/addon/mixin/{GuiGraphicsMixin.java => GuiGraphicsExtractorMixin.java} | 14 +++----
src/main/java/blade/addon/mixin/GuiMixin.java | 22 +++++------
src/main/java/blade/addon/mixin/HandledScreenMixin.java | 30 +++++++--------
src/main/java/blade/addon/mixin/InventoryScreenMixin.java | 10 ++---
src/main/java/blade/addon/mixin/RecipeBookComponentMixin.java | 6 +--
src/main/java/blade/addon/utils/Commands.java | 68 ++++++++++++++++-----------------
src/main/java/blade/addon/utils/Keybinds.java | 14 +++----
src/main/java/blade/addon/utils/Misc.java | 2 +-
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 8 ++--
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 6 +--
src/main/java/blade/addon/utils/debug/Debug.java | 44 +++++++++++-----------
src/main/java/blade/addon/utils/dungeon/Section.java | 13 ++++---
src/main/java/blade/addon/utils/dungeon/Split.java | 8 ++--
src/main/java/blade/addon/utils/rendering/RenderHandler.java | 12 +++---
src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 13 ++++---
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 56 ++++++++++++++--------------
src/main/java/blade/addon/utils/rendering/RenderingEvent.java | 5 +--
src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 14 +++----
src/main/java/blade/addon/utils/rendering/drawevents/SlotEvent.java | 4 +-
src/main/resources/blade-addons.mixins.json | 2 +-
src/main/resources/fabric.mod.json | 6 +--
86 files changed, 486 insertions(+), 473 deletions(-)@@ -11,20 +11,20 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: validate gradle wrapper - uses: gradle/actions/wrapper-validation@v4 + uses: gradle/actions/wrapper-validation@v6 - name: setup jdk - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: 'microsoft' - name: make gradle wrapper executable run: chmod +x ./gradlew - name: build run: ./gradlew build - name: capture build artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: Artifacts - path: build/libs/ \ No newline at end of file + path: build/libs/ @@ -1,17 +1,17 @@ plugins { - id 'fabric-loom' version "${loom_version}" - id 'maven-publish' + id 'net.fabricmc.fabric-loom' version "${loom_version}" + id 'maven-publish' } version = project.mod_version group = project.maven_group base { - archivesName = project.archives_base_name + archivesName = project.archives_base_name } java { - toolchain.languageVersion = JavaLanguageVersion.of(21) + toolchain.languageVersion = JavaLanguageVersion.of(25) // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. // If you remove this line, sources will not be generated. @@ -21,10 +21,11 @@ java { loom { runConfigs.named("client") { setIdeConfigGenerated(true) - vmArgs.add("-Dmixin.debug.export=true") - vmArgs.add("-Ddevauth.enabled=true") - vmArgs.add("-Ddevauth.account=main") - vmArgs.add("-XX:+AllowEnhancedClassRedefinition") + vmArgs("-XX:+IgnoreUnrecognizedVMOptions", + "-Dmixin.debug.export=true", + "-Ddevauth.enabled=true", + "-Ddevauth.account=main", + "-XX:+AllowEnhancedClassRedefinition") } runConfigs.named("server") { @@ -32,94 +33,81 @@ loom { } } +repositories { + maven { url = "https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" } + maven { url = 'https://jitpack.io' } + maven { + name = "Terraformers" + url = "https://maven.terraformersmc.com/" + } + maven { url = 'https://repo.hypixel.net/repository/Hypixel/' } -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // 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://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1" } - - repositories { - mavenCentral() - maven { url 'https://jitpack.io' } - } - - maven { - name = "Terraformers" - url = "https://maven.terraformersmc.com/" - } - - repositories { - maven { url = 'https://repo.hypixel.net/repository/Hypixel/' } - } } dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - //mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - mappings loom.officialMojangMappings() - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + //mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + implementation "net.fabricmc:fabric-loader:${project.loader_version}" - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}") - include modImplementation("net.hypixel:mod-api:${project.hypixel_api_version}") - include modImplementation("com.github.BladeMasterGabe:practical-config:${project.practical_config}") + // Fabric API. This is technically optional, but you probably want it anyway. + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" + implementation("com.terraformersmc:modmenu:${project.modmenu_version}") + include implementation("net.hypixel:mod-api:${project.hypixel_api_version}") + include implementation("com.github.BladeMasterGabe:practical-config:${project.practical_config}") - modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:1.2.2") + runtimeOnly("me.djtheredstoner:DevAuth-fabric:${project.dev_auth_version}") } processResources { - inputs.property "version", project.version + inputs.property "version", project.version - filesMatching("fabric.mod.json") { - expand "version": inputs.properties.version - } + filesMatching("fabric.mod.json") { + expand "version": inputs.properties.version + } } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 25 } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } jar { - inputs.property "archivesName", project.base.archivesName + def projectName = project.name + inputs.property "projectName", projectName - from("LICENSE") { - rename { "${it}_${inputs.properties.archivesName}"} - } + from("LICENSE") { + rename { "${it}_$projectName"} + } } // configure the maven publication publishing { - publications { - create("mavenJava", MavenPublication) { - artifactId = project.archives_base_name - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } + publications { + create("mavenJava", MavenPublication) { + artifactId = project.archives_base_name + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } } @@ -1,25 +1,21 @@ # Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx1G org.gradle.parallel=true - # IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349 org.gradle.configuration-cache=false - # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.11 -yarn_mappings=1.21.11+build.4 -loader_version=0.18.4 -loom_version=1.15-SNAPSHOT - +minecraft_version=26.1.2 +loader_version=0.19.3 +loom_version=1.17-SNAPSHOT # Mod Properties mod_version=2.4.1 maven_group=blade.addon archives_base_name=blade-addons - # Dependencies -fabric_version=0.141.3+1.21.11 +fabric_api_version=0.152.1+26.1.2 # I love dependencies sometimes breaking -practical_config=ca2e4a5ea86f1f8ef9de3ae2bd3c1c1b6f6108ac -modmenu_version =17.0.0-beta.2 -hypixel_api_version = 1.0.1 +practical_config=902a663c1b6c8917d02f12b7608eb373a9d3c1f3 +modmenu_version=18.0.0-beta.1 +hypixel_api_version=1.0.2 +dev_auth_version=1.2.2 @@ -1,7 +1,6 @@ +#Thu Jun 25 03:30:47 CEST 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip -networkTimeout=10000 -validateDistributionUrl=true +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists @@ -8,7 +8,7 @@ import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; @@ -53,7 +53,7 @@ public class BloodNotifier { return Dungeons.alertBloodSpawns && System.currentTimeMillis() - prevTime < 2000 && correctClass(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawCenteredText(graphics, component, Component.literal("First four mobs spawned!"), Constants.RED); } @@ -9,13 +9,14 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class ChestCounter { private static final Pattern PATTERN = Pattern.compile("^ Unclaimed chests: (\\d+)$"); @@ -66,14 +67,14 @@ public class ChestCounter { return Dungeons.displayChestCount && Location.inDungeon(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { int x = component.getScaledX(); int y = component.getScaledY(); if (hasUpdatedData) { RenderUtils.drawPrefixedText(component, graphics, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); } else { - graphics.drawString(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); + graphics.text(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); } } @@ -10,7 +10,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; @@ -57,7 +57,7 @@ public class ItemHighlight { RenderingEvents.FILLED_NO_DEPTH.register(ItemHighlight::render); } - private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void render(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Dungeons.highlightItems) return; double tickProgress = Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaPartialTick(false); @@ -10,7 +10,7 @@ import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; @@ -19,6 +19,7 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.ResolvableProfile; + import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,7 +42,7 @@ public class KeyNotifier { private static boolean isBloodKey = false; public static void init() { - ClientTickEvents.END_WORLD_TICK.register((world) -> { + ClientTickEvents.END_LEVEL_TICK.register((world) -> { if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier || Phase.inBoss()) return; for (Entity entity : world.entitiesForRendering()) { @@ -113,11 +114,11 @@ public class KeyNotifier { return Location.inDungeon() && hasKey && isValidClass() && !Phase.inBoss(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { int x = component.getScaledX(); int y = component.getScaledY(); Component text = isBloodKey ? BLOOD_KEY : WITHER_KEY; - RenderUtils.drawCenteredText(context, Minecraft.getInstance().font, text, x, y, component.getWidth(), 0xffffffff); + RenderUtils.drawCenteredText(graphics, Minecraft.getInstance().font, text, x, y, component.getWidth(), 0xffffffff); } } @@ -9,7 +9,7 @@ import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; public class QuizTimer { @@ -56,7 +56,7 @@ public class QuizTimer { return Dungeons.quizTimer && tick > 0; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { Font textRenderer = Minecraft.getInstance().font; if (textRenderer == null) return; @@ -65,7 +65,7 @@ public class QuizTimer { .append(Component.literal(stage + "/3").withColor(0xffffffff) .append(Component.literal("): ").withColor(ExtraOptions.timerPrefixColor)) .append(Component.literal(Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION) + "s").withColor(0xffffffff))); - graphics.drawString(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); + graphics.text(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); } else { RenderUtils.drawPrefixedTimer(component, graphics, "Quiz", tick); } @@ -8,12 +8,8 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.Component; @@ -21,6 +17,11 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Scoreboard; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class RunStartValidator { private static final Pattern STARTING_PATTERN = Pattern.compile("^Starting in \\d second(s)?"); @@ -134,7 +135,7 @@ public class RunStartValidator { return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { if (hasDupeClasses) { RenderUtils.drawCenteredText(graphics, component, DUPE_CLASS_TEXT); } else if (notEnoughPlayers) { @@ -7,12 +7,13 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class SecretSpawnTimer { private static final Pattern PATTERN = Pattern.compile("^Time Elapsed: "); @@ -41,7 +42,7 @@ public class SecretSpawnTimer { return Location.inDungeon() && Dungeons.enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphicsExtractor context) { int x = component.getScaledX(); int y = component.getScaledY(); @@ -4,9 +4,10 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.GuiGraphicsExtractor; + import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.minecraft.client.gui.GuiGraphics; public class WarpCooldown { @@ -42,7 +43,7 @@ public class WarpCooldown { } } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); RenderUtils.drawPrefixedTimer(component, graphics, "Warp Cooldown", timeRemaining); } @@ -15,7 +15,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.core.BlockPos; import net.minecraft.gizmos.GizmoStyle; @@ -141,7 +141,7 @@ public class BossWaypoints { return InteractionResult.PASS; } - private static void renderThroughWall(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void renderThroughWall(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; waypoints.forEach(waypoint -> { @@ -151,7 +151,7 @@ public class BossWaypoints { }); } - private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void render(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; waypoints.forEach(waypoint -> { @@ -16,10 +16,10 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.core.BlockPos; import net.minecraft.gizmos.GizmoStyle; import net.minecraft.gizmos.Gizmos; @@ -31,6 +31,7 @@ import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -122,7 +123,7 @@ public class RelicTimer { return false; }); - ClientTickEvents.END_WORLD_TICK.register(world -> { + ClientTickEvents.END_LEVEL_TICK.register(world -> { if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes || sentRelicTimes) return; Iterable<Entity> entities = world.entitiesForRendering(); @@ -259,7 +260,7 @@ public class RelicTimer { Misc.addChatMessage(Component.literal("Relic: " + pickedupRelic)); } - private static void worldRender(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void worldRender(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (pickedupRelic == null || !Floor7.renderRelicHighlight) return; AABB box = pickedupRelic.box; @@ -271,7 +272,7 @@ public class RelicTimer { return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && !Floor7.replaceWithProgressBar; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { int color = tick > 7 ? GREEN_COLOR : RED_COLOR; RenderUtils.drawTimer(component, graphics, tick, color); } @@ -281,7 +282,7 @@ public class RelicTimer { return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && Floor7.replaceWithProgressBar; } - public static void renderProgressBar(HUDComponent component, GuiGraphics graphics) { + public static void renderProgressBar(HUDComponent component, GuiGraphicsExtractor graphics) { int x = component.getScaledX(); int y = component.getScaledY(); @@ -6,7 +6,7 @@ import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; @@ -99,7 +99,7 @@ public class DragSpawnTimer { return Floor7.dragSpawnTimers && currentDragon != Dragon.NONE; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawTimer(component, graphics, tick, currentDragon.color); } } @@ -10,10 +10,11 @@ import blade.addon.utils.rendering.RenderingEvents; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.phys.Vec3; + import java.util.concurrent.ConcurrentLinkedQueue; public class DragonHealth { @@ -42,7 +43,7 @@ public class DragonHealth { return false; }); - ClientTickEvents.END_WORLD_TICK.register(world -> dragons.removeIf(dataHolder -> dataHolder.dragon.isRemoved())); + ClientTickEvents.END_LEVEL_TICK.register(world -> dragons.removeIf(dataHolder -> dataHolder.dragon.isRemoved())); RenderingEvents.FILLED.register(DragonHealth::render); Events.ON_LOCATION_CHANGE.register(newLocation -> { reset(); @@ -61,7 +62,7 @@ public class DragonHealth { return Constants.RED; } - private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void render(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Floor7.dragonHealth) return; dragons.forEach(dataHolder -> { @@ -5,7 +5,7 @@ import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.rendering.RenderingEvents; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; public class DragonTracer { @@ -13,7 +13,7 @@ public class DragonTracer { RenderingEvents.LINE.register(DragonTracer::render); } - private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void render(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Floor7.dragonTracer) return; Dragon dragon = DragSpawnTimer.currentDragon; @@ -4,7 +4,7 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; public class InvincibilityDuration { @@ -26,7 +26,7 @@ public class InvincibilityDuration { return ticks > 0 && Dungeons.InvincibilityDuration; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { int color = 0xffffffff; if (Dungeons.useStatusColorForInvincibility) { color = RenderUtils.getStatusColor(40, 20, ticks); @@ -8,15 +8,16 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class InvincibilityTimer { private static final int TEXT_HEIGHT = 9; @@ -152,12 +153,12 @@ public class InvincibilityTimer { return (double) spiritMaskTicks / SPIRIT_MASK_COOLDOWN; } - private static void drawSprite(GuiGraphics context, Identifier identifier, int x, int y, boolean isOn, int ticks, Component timerText) { + private static void drawSprite(GuiGraphicsExtractor context, Identifier identifier, int x, int y, boolean isOn, int ticks, Component timerText) { int color = (ticks > 0 ? Constants.RED : isOn ? Constants.YELLOW : Constants.GREEN); context.fill(x, y, x + SPRITE_SIZE, y + SPRITE_SIZE, color); context.blitSprite(RenderPipelines.GUI_TEXTURED, identifier, x, y, SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); if (ticks > 0) { - context.drawString(Minecraft.getInstance().font, timerText, x + TEXT_HEIGHT * 2, y, 0xffffffff, true); + context.text(Minecraft.getInstance().font, timerText, x + TEXT_HEIGHT * 2, y, 0xffffffff, true); } } @@ -190,7 +191,7 @@ public class InvincibilityTimer { } } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { int x = component.getScaledX(); int y = component.getScaledY(); @@ -200,13 +201,13 @@ public class InvincibilityTimer { drawSprite(graphics, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); } else { if (Dungeons.removeMaskPart) { - graphics.drawString(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo "), x, y, 0xffffffff, true); - graphics.drawString(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit "), x, y + TEXT_HEIGHT, 0xffffffff, true); + graphics.text(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo "), x, y, 0xffffffff, true); + graphics.text(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit "), x, y + TEXT_HEIGHT, 0xffffffff, true); } else { - graphics.drawString(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); - graphics.drawString(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); + graphics.text(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); + graphics.text(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); } - graphics.drawString(Minecraft.getInstance().font, getText(phoenixTicks, phoenixOn, "Phoenix "), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); + graphics.text(Minecraft.getInstance().font, getText(phoenixTicks, phoenixOn, "Phoenix "), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); } } } @@ -3,7 +3,7 @@ package blade.addon.features.dungeon.f7.invincibility; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.data.ItemUtil; import blade.addon.utils.rendering.DrawEvents; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.world.item.ItemStack; public class MaskHighlight { @@ -14,7 +14,7 @@ public class MaskHighlight { DrawEvents.INVENTORY_SLOT_AFTER.register(MaskHighlight::draw); } - private static void draw(GuiGraphics context, ItemStack stack, int x, int y) { + private static void draw(GuiGraphicsExtractor context, ItemStack stack, int x, int y) { if (!Dungeons.maskHighlight) return; MaskHolder holder = (MaskHolder) (Object) stack; @@ -11,9 +11,10 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -65,7 +66,7 @@ public class LocationNotifier { return ticks > 0 && Floor7.displayLocationNotification; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawCenteredText(graphics, component, notification); } } @@ -9,13 +9,14 @@ import blade.addon.utils.rendering.RenderingEvents; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.gizmos.GizmoStyle; import net.minecraft.gizmos.Gizmos; import net.minecraft.util.ARGB; import net.minecraft.world.phys.AABB; + import java.util.ArrayList; public class PositionMessages { @@ -97,7 +98,7 @@ public class PositionMessages { } } - private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void render(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Location.inDungeon() || !Debug.renderPositions) return; for (PositionMessage positionMessage : positionMessages) { @@ -10,14 +10,15 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class CrystalSpawn { private static final Pattern RELIC_PICK_UP = Pattern.compile("(\\w+) picked up an Energy Crystal!$"); @@ -98,7 +99,7 @@ public class CrystalSpawn { return tick > 0 && Location.inDungeon() && Phase.inP1() && Floor7.enableCrystalSpawnTime; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawTimer(component, graphics, tick, Constants.LIGHT_PURPLE); } @@ -106,7 +107,7 @@ public class CrystalSpawn { return (Floor7.instantlyDisplayCrystalReminder || tickSincePicked > REMINDER_TICK) && Location.inDungeon() && Phase.inP1() && Floor7.crystalPlaceReminder && pickedUp; } - public static void renderNotification(HUDComponent component, GuiGraphics graphics) { + public static void renderNotification(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawCenteredText(graphics, component, Component.literal("§bPlace Crystal!")); } @@ -7,7 +7,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; public class MaxorStun { @@ -51,7 +51,7 @@ public class MaxorStun { return tick > 0 && Location.inDungeon() && Phase.inP1() && Floor7.maxorStunDuration && stunned; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawPrefixedText(component, graphics, "Stunned", TextUtil.formatTicks(tick)); } @@ -6,7 +6,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; public class MaxorTickTimer { @@ -28,7 +28,7 @@ public class MaxorTickTimer { return Floor7.enableMaxorTickTimer && Location.inDungeon() && Phase.inP1(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawTimer(component, graphics, tick, 0xffffffff); } @@ -7,7 +7,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.phys.AABB; @@ -39,7 +39,7 @@ public class DistanceToLedge { return Phase.inP2() && !Phase.stormDead() && (DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER)); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawTimer(component, graphics, getDistance(), 0xffffffff); } } @@ -8,7 +8,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; @@ -43,7 +43,7 @@ public class PillarExplode { return Floor7.timePillarExplosion && tick > 0; } - public static void renderTimer(HUDComponent component, GuiGraphics graphics) { + public static void renderTimer(HUDComponent component, GuiGraphicsExtractor graphics) { int color = tick < 6 ? Constants.GREEN : Constants.RED; RenderUtils.drawTimer(component, graphics, tick, color); } @@ -52,7 +52,7 @@ public class PillarExplode { return Floor7.notifyStormCrush && tick > 0; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawCenteredText(graphics, component, Component.literal("§6||| §bStorm crushed! §6|||")); } } @@ -10,10 +10,11 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.network.chat.Component; + import java.util.regex.Matcher; import java.util.regex.Pattern; -import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.network.chat.Component; public class StormTickTimer { @@ -72,7 +73,7 @@ public class StormTickTimer { return Floor7.enableStormTickTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { double num = tick * Constants.TICK_DURATION; if (Floor7.tickDownStormTickTimer) { num = CRUSH_TICK * Constants.TICK_DURATION - num; @@ -84,7 +85,7 @@ public class StormTickTimer { return Floor7.enableStormDeathTime && Location.inDungeon() && Phase.inP2() && !Phase.stormDead() && deathTime > 0 && deathStartDisplayTime > System.currentTimeMillis() - DEATH_DISPLAY_DURATION; } - public static void renderDeathTime(HUDComponent component, GuiGraphics graphics) { + public static void renderDeathTime(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawTimer(component, graphics, deathTime, Constants.DARK_PURPLE); } } @@ -5,7 +5,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; public class CurrentSection { @@ -26,7 +26,7 @@ public class CurrentSection { return Floor7.showCurrentSection && Phase.inTerminals(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawPrefixedText(component, graphics, "Section", " " + section); } @@ -8,7 +8,7 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; @@ -74,7 +74,7 @@ public class DeviceNotifier { return showNotification; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { if (System.currentTimeMillis() - completedTime >= TOTAL_DURATION) showNotification = false; RenderUtils.drawCenteredText(graphics, component, Component.literal("§aDevice Completed!")); } @@ -7,7 +7,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; public class GoldorTickTimer { @@ -31,7 +31,7 @@ public class GoldorTickTimer { return Floor7.enableGoldorTickTimer && Location.inDungeon() && Phase.inTerminals(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { double num = tick * Constants.TICK_DURATION; double mod = num % 3; if (Floor7.inDeathTicks && !Floor7.makeGoldorTickUp) mod = 3.0 - mod; @@ -7,13 +7,14 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; + import java.util.List; /** @@ -100,7 +101,7 @@ public class LeapNotification { return Floor7.leapNotifications && inBounds && Phase.inBoss() && Location.inDungeon(); } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { int maxCount = getMaxCount(); String startFormat; @@ -10,14 +10,15 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class MelodyWarning { private static final Pattern PATTERN = Pattern.compile("(\\d+)%"); @@ -80,7 +81,7 @@ public class MelodyWarning { return melodyStarted && Floor7.notifiyMelody && !ownUsername; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { DungeonClass dungeonClass = DungeonClass.getClass(name); int num = Math.min(furthestProgress / 25, 3); @@ -6,7 +6,7 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.network.chat.Component; public class SectionCompletion { @@ -25,7 +25,7 @@ public class SectionCompletion { return System.currentTimeMillis() - prevTime < 1000 && Floor7.sectionCompletionNotification; } - public static void render(HUDComponent component, GuiGraphics graphics) { + public static void render(HUDComponent component, GuiGraphicsExtractor graphics) { RenderUtils.drawCentere …… diff 过长已截断 …… |
- hopefully should be last rendering fix查看变更src/main/java/blade/addon/Bladeaddons.java | 1 + src/main/java/blade/addon/features/dungeon/DeathMessage.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 11 ++++++++--- src/main/java/blade/addon/features/other/PracticeSS.java | 16 ++++++++-------- src/main/java/blade/addon/utils/Waypoint.java | 8 ++++++++ src/main/java/blade/addon/utils/config/Config.java | 5 +++++ src/main/java/blade/addon/utils/config/values/Dungeons.java | 6 ++++++ 7 files changed, 83 insertions(+), 11 deletions(-) @@ -127,5 +127,6 @@ public class Bladeaddons implements ModInitializer { CurrentSection.init(); DragonTracer.init(); ReaperDisplay.init(); + //DeathMessage.init(); TODO finish this } } \ No newline at end of file @@ -0,0 +1,47 @@ +package blade.addon.features.dungeon; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.events.Events; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DeathMessage { + + private static final Pattern[] patterns = new Pattern[]{ + Pattern.compile("^ ☠ (.*) was killed by *."), + Pattern.compile("^ ☠ (.*) died to a *."), + Pattern.compile("^ ☠ (.*) fell to their death *."), + }; + + public static void init() { + + Events.ON_GAME_MESSAGE.register(text -> { + + if (!Location.inDungeon() || !Dungeons.sendDeathMessage) return false; + + String msg = text.getString(); + for(Pattern pattern: patterns) { + Matcher matcher = pattern.matcher(msg); + if (matcher.find()) { + String name = matcher.group(1); + + ClientPacketListener networkHandler = Minecraft.getInstance().getConnection(); + if (networkHandler == null) return false; + networkHandler.sendCommand("pc " + createMessage(name)); + return false; + } + } + return false; + }); + + } + + private static String createMessage(String name) { + return Dungeons.deathMessage.replace("<player>", name); + } + +} @@ -18,12 +18,16 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.core.BlockPos; +import net.minecraft.gizmos.GizmoStyle; +import net.minecraft.gizmos.Gizmos; import net.minecraft.network.chat.Component; +import net.minecraft.util.ARGB; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; + import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; @@ -137,7 +141,7 @@ public class BossWaypoints { return InteractionResult.PASS; } - private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void renderThroughWall(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; waypoints.forEach(waypoint -> { @@ -147,12 +151,13 @@ public class BossWaypoints { }); } - private static void renderThroughWall(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { + private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; waypoints.forEach(waypoint -> { if (!waypoint.isThroughWall()) { - waypoint.Render(consumer, matrixStack); + float[] color = waypoint.getColor(); + Gizmos.cuboid(waypoint.getBox(), GizmoStyle.fill(ARGB.colorFromFloat(color[3], color[0], color[1], color[2]))); } }); } @@ -24,6 +24,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; + import java.util.Collections; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -352,15 +353,15 @@ public class PracticeSS { if (showingPattern) { if (!ExtraOptions.realisticDelay || totalTicks - ticksLeft > START_WAIT_DURATION || endIndex != 2) { int lastIndex = getLastDisplayIndex(); - renderButtons(matrixStack, consumer, 0, lastIndex); - renderBackground(matrixStack, consumer, lastIndex - 1); + renderButtons(0, lastIndex); + renderBackground(lastIndex - 1); } } else { - renderButtons(matrixStack, consumer, currentIndex, endIndex); + renderButtons(currentIndex, endIndex); } } - private static void renderButtons(PoseStack matrixStack, VertexConsumer consumer, int start, int end) { + private static void renderButtons(int start, int end) { AABB directionBox = getBox(direction); if (directionBox == null) return; @@ -368,8 +369,7 @@ public class PracticeSS { if (buttons.size() <= i) break; BlockPos pos = buttons.get(i); AABB box = directionBox.move(pos.getX(), pos.getY(), pos.getZ()); - float[] color = RenderUtils.toFloats(getColor(i)); - RenderUtils.renderFilledBox(matrixStack, consumer, box, color); + RenderUtils.renderFilledBlock(box, getColor(i)); } } @@ -383,7 +383,7 @@ public class PracticeSS { }; } - private static void renderBackground(PoseStack matrixStack, VertexConsumer consumer, int backgroundIndex) { + private static void renderBackground(int backgroundIndex) { if (buttons.size() > backgroundIndex && backgroundIndex >= 0) { AABB box = AABB.ofSize(buttons.get(backgroundIndex).getCenter(), 1, 1, 1); int dx, dz; @@ -408,7 +408,7 @@ public class PracticeSS { return; } } - RenderUtils.renderFilledBox(matrixStack, consumer, box.move(dx, 0, dz), new float[]{0, 0.5f, 1, 1}); + RenderUtils.renderFilledBlock(box.move(dx, 0, dz), 0xff0080ff); } } } @@ -42,6 +42,14 @@ public class Waypoint { RenderUtils.renderFilledBox(matrixStack, consumer, new AABB(x, y, z, x + dx, y + dy, z + dz), new float[]{r, g, b,a}); } + public AABB getBox() { + return new AABB(x, y, z, x + dx, y + dy, z + dz); + } + + public float[] getColor() { + return new float[]{r, g, b,a}; + } + @Override public String toString() { return "Waypoint{" + @@ -75,6 +75,11 @@ public class Config { start.add(new ConfigBool(Component.literal("Player count warning"), () -> Dungeons.detectPlayerCount, bool -> Dungeons.detectPlayerCount = bool)); dungeons.add(start); + ConfigSection deathMessage = new ConfigSection(Component.literal("Death message")); + deathMessage.add(new ConfigBool(Component.literal("Send death message"), () -> Dungeons.sendDeathMessage, bool -> Dungeons.sendDeathMessage = bool)); + deathMessage.add(new ConfigString(Component.literal("Message sent (<player> replaces with the players name) "), () -> Dungeons.deathMessage, str -> Dungeons.deathMessage = str)); + dungeons.add(deathMessage); + ConfigSection invincibility = new ConfigSection(Component.literal("Invincibility Timer")); invincibility.add(new ConfigBool(Component.literal("Enable invincibility display"), () -> Dungeons.displayInvincibilityTimer, bool -> Dungeons.displayInvincibilityTimer = bool)); invincibility.add(new ConfigOptions<>(Component.literal("Display when"), InvincibilityTimer.DisplayWhen.values(), () -> Dungeons.displayWhen, when -> Dungeons.displayWhen = when)); @@ -148,4 +148,10 @@ public class Dungeons { @ConfigValue public static boolean quizProgress = false; + + @ConfigValue + public static boolean sendDeathMessage = false; + + @ConfigValue + public static String deathMessage = ""; } |
- hopefully fixed itemhighlight查看变更src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 6 ++---- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) @@ -14,14 +14,12 @@ import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.gizmos.GizmoStyle; -import net.minecraft.gizmos.Gizmos; import net.minecraft.network.chat.Component; -import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.phys.AABB; + import java.util.HashSet; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -72,7 +70,7 @@ public class ItemHighlight { EntityDimensions dimension = itemEntity.getDimensions(itemEntity.getPose()); AABB box = dimension.makeBoundingBox(x, y, z).inflate(0.1).move(0, 0.05, 0); float[] color = RenderUtils.toFloats(getColor(itemEntity)); - Gizmos.cuboid(box, GizmoStyle.fill(ARGB.colorFromFloat(color[3], color[0], color[1], color[2]))); + RenderUtils.renderFilledBox(matrixStack, consumer, box, color); }); } @@ -13,6 +13,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.gizmos.GizmoStyle; import net.minecraft.gizmos.Gizmos; import net.minecraft.network.chat.Component; import net.minecraft.world.phys.AABB; @@ -273,4 +274,7 @@ public class RenderUtils { } + public static void renderFilledBlock(AABB box, int argb) { + Gizmos.cuboid(box, GizmoStyle.fill(argb)); + } } |
- changed some rendering i think, dont fully remember i made commit a week ago and forgot to commit (p sure it still has issues but whatever)查看变更src/main/java/blade/addon/features/other/SearchBar.java | 2 +- src/main/java/blade/addon/utils/Waypoint.java | 6 ++---- src/main/java/blade/addon/utils/config/Config.java | 19 ++++++------------- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 6 +++--- src/main/java/blade/addon/utils/rendering/RenderLayers.java | 3 +++ src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 6 ++++++ src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 2 ++ 7 files changed, 23 insertions(+), 21 deletions(-) @@ -31,7 +31,7 @@ public class SearchBar { DrawEvents.INVENTORY_SLOT_AFTER.register((context, item, x, y) -> { if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar && Double.isNaN(parsedValue)) { if (!matches(item)) { - context.fill(x, y, x + 16, y + 16, 0xaa111111); + context.fill(x, y, x + 16, y + 16, ExtraOptions.searchbarMissColor); } } @@ -1,10 +1,8 @@ package blade.addon.utils; +import blade.addon.utils.rendering.RenderUtils; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.gizmos.GizmoStyle; -import net.minecraft.gizmos.Gizmos; -import net.minecraft.util.ARGB; import net.minecraft.world.phys.AABB; public class Waypoint { @@ -41,7 +39,7 @@ public class Waypoint { } public void Render(VertexConsumer consumer, PoseStack matrixStack) { - Gizmos.cuboid(new AABB(x, y, z, x + dx, y + dy, z + dz), GizmoStyle.fill(ARGB.colorFromFloat(a, r, g, b))); + RenderUtils.renderFilledBox(matrixStack, consumer, new AABB(x, y, z, x + dx, y + dy, z + dz), new float[]{r, g, b,a}); } @Override @@ -7,35 +7,28 @@ import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.filter.FilterList; import blade.addon.features.highlight.MobHighlight; import blade.addon.features.item.ProtectItem; -import blade.addon.features.other.DianaNotifier; import blade.addon.features.notifications.NotificationList; +import blade.addon.features.other.DianaNotifier; import blade.addon.utils.config.components.Components; -import blade.addon.utils.config.values.Buttons; -import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.config.values.Floor7; -import blade.addon.utils.config.values.Visual; +import blade.addon.utils.config.values.*; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; import blade.addon.utils.dungeon.Split; import config.practical.ConfigurableScreen; import config.practical.category.ConfigCategory; import config.practical.manager.ConfigManager; -import config.practical.widgets.ConfigBool; -import config.practical.widgets.ConfigButton; -import config.practical.widgets.ConfigSection; -import config.practical.widgets.ConfigString; -import config.practical.widgets.ConfigTextArea; +import config.practical.widgets.*; import config.practical.widgets.color.ConfigColor; import config.practical.widgets.options.ConfigOptions; import config.practical.widgets.sliders.ConfigDouble; import config.practical.widgets.sliders.ConfigInt; import config.practical.widgets.sound.ConfigSound; -import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import java.util.List; + public class Config { private static final Component TITLE = Component.literal("Blade Addons"); @@ -323,9 +316,9 @@ public class Config { extra.add(new ConfigBool(Component.literal("Display selected arrow"), () -> ExtraOptions.displayCurrentArrow, bool -> ExtraOptions.displayCurrentArrow = bool)); extra.add(new ConfigBool(Component.literal("Title on arrow swap"), () -> ExtraOptions.arrowSwapNotification, bool -> ExtraOptions.arrowSwapNotification = bool)); extra.add(new ConfigBool(Component.literal("Toggleable searchbar (ctrl + f)"), () -> ExtraOptions.toggleableSearchBar, bool -> ExtraOptions.toggleableSearchBar = bool)); + extra.add(new ConfigColor(Component.literal("Searchbar miss color"), () -> ExtraOptions.searchbarMissColor, color -> ExtraOptions.searchbarMissColor = color, "search-bar-miss-color", true)); extra.add(new ConfigBool(Component.literal("Disable protect item (resets on launch)"), () -> ProtectItem.stopProtectItem, bool -> ProtectItem.stopProtectItem = bool)); extra.add(new ConfigBool(Component.literal("Display reaper duration"), () -> ExtraOptions.enableReaperDisplay, bool -> ExtraOptions.enableReaperDisplay = bool)); - //extra.add(new ConfigBool(Text.literal("Kuudra stun waypoint"), () -> ExtraOptions.stunWaypoint, bool -> ExtraOptions.stunWaypoint = bool)); ConfigSection sound = new ConfigSection(Component.literal("Sound options")); @@ -112,9 +112,6 @@ public class ExtraOptions { @ConfigValue public static boolean arrowSwapNotification = false; - @ConfigValue - public static boolean stunWaypoint = false; - @ConfigValue public static int petHighlightColor = 0xffff0000; @@ -141,4 +138,7 @@ public class ExtraOptions { @ConfigValue public static boolean disableAllFilters = false; + + @ConfigValue + public static int searchbarMissColor = 0xaa111111; } @@ -9,6 +9,9 @@ public class RenderLayers { public static final RenderType FILLED_DEBUG = RenderType.create("filled-debug-layer", RenderSetup.builder(RenderPipelines.FILLED_DEBUG).createRenderSetup()); + public static final RenderType FILLED_DEBUG_NO_DEPTH = + RenderType.create("filled-debug-no-depth-layer", RenderSetup.builder(RenderPipelines.FILLED_DEBUG).createRenderSetup()); + public static final RenderType FILLED = RenderType.create("filled-layer", RenderSetup.builder(RenderPipelines.FILLED).createRenderSetup()); @@ -11,6 +11,12 @@ public class RenderPipelines { public static final RenderPipeline FILLED_DEBUG = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug-pipe")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withDepthWrite(true) + .build()); + + public static final RenderPipeline FILLED_DEBUG_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug-no-depth-pipe")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) .build()); @@ -5,6 +5,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; public class RenderingEvents { public static RenderHandler FILLED_DEBUG = new RenderHandler(RenderLayers.FILLED_DEBUG); + public static RenderHandler FILLED_DEBUG_NO_DEPTH = new RenderHandler(RenderLayers.FILLED_DEBUG_NO_DEPTH); public static RenderHandler FILLED = new RenderHandler(RenderLayers.FILLED); public static RenderHandler LINE = new RenderHandler(RenderLayers.LINE); public static RenderHandler FILLED_NO_DEPTH = new RenderHandler(RenderLayers.FILLED_NO_DEPTH); @@ -13,6 +14,7 @@ public class RenderingEvents { public static void init() { WorldRenderEvents.BEFORE_DEBUG_RENDER.register(FILLED_DEBUG::init); + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(FILLED_DEBUG_NO_DEPTH::init); WorldRenderEvents.AFTER_ENTITIES.register(FILLED::init); WorldRenderEvents.AFTER_ENTITIES.register(LINE::init); WorldRenderEvents.AFTER_ENTITIES.register(FILLED_NO_DEPTH::init); |
- fixed identifier naming for renderlayers and renderpipelines查看变更src/main/java/blade/addon/utils/rendering/RenderLayers.java | 10 +++++----- src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) @@ -7,20 +7,20 @@ import net.minecraft.client.renderer.rendertype.RenderType; public class RenderLayers { public static final RenderType FILLED_DEBUG = - RenderType.create("filled-debug", RenderSetup.builder(RenderPipelines.FILLED_DEBUG).createRenderSetup()); + RenderType.create("filled-debug-layer", RenderSetup.builder(RenderPipelines.FILLED_DEBUG).createRenderSetup()); public static final RenderType FILLED = - RenderType.create("filled", RenderSetup.builder(RenderPipelines.FILLED).createRenderSetup()); + RenderType.create("filled-layer", RenderSetup.builder(RenderPipelines.FILLED).createRenderSetup()); public static final RenderType LINE = - RenderType.create("line", RenderSetup.builder(RenderPipelines.LINE).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); + RenderType.create("line-layer", RenderSetup.builder(RenderPipelines.LINE).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); public static final RenderType FILLED_NO_DEPTH = - RenderType.create("filled-no-depth", RenderSetup.builder(RenderPipelines.FILLED_NO_DEPTH).createRenderSetup()); + RenderType.create("filled-no-depth-layer", RenderSetup.builder(RenderPipelines.FILLED_NO_DEPTH).createRenderSetup()); public static final RenderType LINE_NO_DEPTH = - RenderType.create("line-no-depth", RenderSetup.builder(RenderPipelines.LINE_NO_DEPTH).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); + RenderType.create("line-no-depth-layer", RenderSetup.builder(RenderPipelines.LINE_NO_DEPTH).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); } @@ -9,34 +9,34 @@ import net.minecraft.resources.Identifier; public class RenderPipelines { public static final RenderPipeline FILLED_DEBUG = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug")) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug-pipe")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) .build()); public static final RenderPipeline FILLED = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled")) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-pipe")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) .withDepthWrite(true) .build()); public static final RenderPipeline LINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "line")) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "line-pipe")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) .withDepthWrite(true) .build()); public static final RenderPipeline FILLED_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-no-depth")) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-no-depth-pipe")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) .build()); public static final RenderPipeline LINE_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(blade.addon.utils.Constants.NAMESPACE, "line-no-depth")) + .withLocation(Identifier.fromNamespaceAndPath(blade.addon.utils.Constants.NAMESPACE, "line-no-depth-pipe")) .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) .build()); |
- remade rendering查看变更src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 5 +-- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/dragons/DragonHealth.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 3 +- src/main/java/blade/addon/features/highlight/BatHighlight.java | 11 +++--- src/main/java/blade/addon/features/highlight/MimicHighlight.java | 8 ++-- src/main/java/blade/addon/features/highlight/MobHighlight.java | 8 ++-- src/main/java/blade/addon/features/highlight/SheepHighlight.java | 8 ++-- src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 4 +- src/main/java/blade/addon/features/highlight/WitherHighlight.java | 8 ++-- src/main/java/blade/addon/features/other/PracticeSS.java | 16 ++++---- src/main/java/blade/addon/utils/rendering/RenderHandler.java | 31 +++++++++++++++ src/main/java/blade/addon/utils/rendering/RenderLayers.java | 45 +++++---------------- src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 35 ++++++++++------- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 134 +++++--------------------------------------------------------- 17 files changed, 251 insertions(+), 231 deletions(-) @@ -56,7 +56,7 @@ public class ItemHighlight { } }); - RenderingEvents.NO_DEPTH_FILLED.register(ItemHighlight::render); + RenderingEvents.FILLED_NO_DEPTH.register(ItemHighlight::render); } private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { @@ -42,9 +42,8 @@ public class BossWaypoints { public static void init() { load(); - //needs separate consumers because of depth checking or smth - RenderingEvents.FILLED_BLOCK.register(BossWaypoints::render); - RenderingEvents.NO_DEPTH_FILLED.register(BossWaypoints::renderThroughWall); + RenderingEvents.FILLED.register(BossWaypoints::render); + RenderingEvents.FILLED_NO_DEPTH.register(BossWaypoints::renderThroughWall); UseBlockCallback.EVENT.register(BossWaypoints::onBlock); } @@ -157,7 +157,7 @@ public class RelicTimer { Events.ON_BLOCK_INTERACTION.register(RelicTimer::blockInteraction); - RenderingEvents.FILLED_BLOCK.register(RelicTimer::worldRender); + RenderingEvents.FILLED.register(RelicTimer::worldRender); } @@ -43,7 +43,7 @@ public class DragonHealth { }); ClientTickEvents.END_WORLD_TICK.register(world -> dragons.removeIf(dataHolder -> dataHolder.dragon.isRemoved())); - RenderingEvents.FILLED_ENTITY.register(DragonHealth::render); + RenderingEvents.FILLED.register(DragonHealth::render); Events.ON_LOCATION_CHANGE.register(newLocation -> { reset(); return false; @@ -35,7 +35,7 @@ public class PositionMessages { public static void init() { ClientTickEvents.END_CLIENT_TICK.register(PositionMessages::tick); - RenderingEvents.OUTLINE_ENTITY.register(PositionMessages::render); + RenderingEvents.LINE.register(PositionMessages::render); Events.ON_LOCATION_CHANGE.register(newLocation -> { disableAll(); return false; @@ -100,7 +100,6 @@ public class PositionMessages { private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Location.inDungeon() || !Debug.renderPositions) return; - PoseStack.Pose entry = matrixStack.last(); for (PositionMessage positionMessage : positionMessages) { AABB box = positionMessage.getBox(); if (positionMessage.sent()) { @@ -10,6 +10,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.world.entity.ambient.Bat; + import java.util.concurrent.ConcurrentLinkedQueue; public class BatHighlight { @@ -37,24 +38,24 @@ public class BatHighlight { return false; }); - ClientTickEvents.END_CLIENT_TICK.register(client -> bats.removeIf(bat -> bat.isRemoved() ||bat.isDeadOrDying())); + ClientTickEvents.END_CLIENT_TICK.register(client -> bats.removeIf(bat -> bat.isRemoved() || bat.isDeadOrDying())); - RenderingEvents.FILLED_ENTITY.register(BatHighlight::renderFilled); - RenderingEvents.OUTLINE_ENTITY.register(BatHighlight::renderOutline); + RenderingEvents.FILLED.register(BatHighlight::renderFilled); + RenderingEvents.LINE.register(BatHighlight::renderOutline); } private static void renderFilled(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.batFilledColor); - bats.forEach(entity -> RenderUtils.renderFilled(EntityUtil.getBox(entity), rgba)); + bats.forEach(entity -> RenderUtils.renderFilledBox(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.batOutlineColor); - bats.forEach(entity -> RenderUtils.renderOutline(EntityUtil.getBox(entity), rgba)); + bats.forEach(entity -> RenderUtils.renderOutlinedBox(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } } @@ -36,8 +36,8 @@ public class MimicHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> mimics.removeIf(BlockEntity::isRemoved)); - RenderingEvents.FILLED_ENTITY.register(MimicHighlight::renderFilled); - RenderingEvents.OUTLINE_ENTITY.register(MimicHighlight::renderOutline); + RenderingEvents.FILLED.register(MimicHighlight::renderFilled); + RenderingEvents.LINE.register(MimicHighlight::renderOutline); } @@ -45,13 +45,13 @@ public class MimicHighlight { if (!MobHighlight.highlightMimicChests || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicFilledColor); - mimics.forEach(mimic -> RenderUtils.renderFilled(box.move(mimic.getBlockPos()), rgba)); + mimics.forEach(mimic -> RenderUtils.renderFilledBox(matrixStack, consumer, box.move(mimic.getBlockPos()), rgba)); } private static void renderOutline(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.highlightMimicChests || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); - mimics.forEach(mimic -> RenderUtils.renderOutline(box.move(mimic.getBlockPos()), rgba)); + mimics.forEach(mimic -> RenderUtils.renderOutlinedBox(matrixStack, consumer,box.move(mimic.getBlockPos()), rgba)); } } @@ -165,8 +165,8 @@ public class MobHighlight { } }); - RenderingEvents.FILLED_ENTITY.register(MobHighlight::renderFilled); - RenderingEvents.OUTLINE_ENTITY.register(MobHighlight::renderOutline); + RenderingEvents.FILLED.register(MobHighlight::renderFilled); + RenderingEvents.LINE.register(MobHighlight::renderOutline); } private static void testArmorStand(ArmorStand armorStand) { @@ -314,7 +314,7 @@ public class MobHighlight { int filledColor = getFilledColor(type); float[] rgba = RenderUtils.toFloats(filledColor); - RenderUtils.renderFilled(box, rgba); + RenderUtils.renderFilledBox(matrixStack, consumer,box, rgba); } } @@ -332,7 +332,7 @@ public class MobHighlight { int outlineColor = getOutlineColor(type); float[] rgba = RenderUtils.toFloats(outlineColor); - RenderUtils.renderOutline(box, rgba); + RenderUtils.renderOutlinedBox(matrixStack, consumer,box, rgba); } } } @@ -33,22 +33,22 @@ public class SheepHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> sheeps.removeIf(sheep -> sheep.isRemoved() || sheep.isDeadOrDying())); - RenderingEvents.FILLED_ENTITY.register(SheepHighlight::renderFilled); - RenderingEvents.OUTLINE_ENTITY.register(SheepHighlight::renderOutline); + RenderingEvents.FILLED.register(SheepHighlight::renderFilled); + RenderingEvents.LINE.register(SheepHighlight::renderOutline); } private static void renderFilled(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.highlightSheep || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); - sheeps.forEach(entity -> RenderUtils.renderFilled(EntityUtil.getBox(entity), rgba)); + sheeps.forEach(entity -> RenderUtils.renderFilledBox(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.highlightSheep || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); - sheeps.forEach(entity -> RenderUtils.renderOutline(EntityUtil.getBox(entity), rgba)); + sheeps.forEach(entity -> RenderUtils.renderOutlinedBox(matrixStack, consumer,EntityUtil.getBox(entity), rgba)); } } @@ -42,7 +42,7 @@ public class TeammateHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> teammates.removeIf(Entity::isRemoved)); - RenderingEvents.NO_DEPTH_OUTLINE_ENTITY.register(TeammateHighlight::renderOutline); + RenderingEvents.LINE_NO_DEPTH.register(TeammateHighlight::renderOutline); } private static void renderOutline(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { @@ -57,7 +57,7 @@ public class TeammateHighlight { if (Dungeons.highlightTeammates) { float[] rgba = RenderUtils.toFloats(color); - RenderUtils.renderOutline(EntityUtil.getBox(player), rgba); + RenderUtils.renderOutlinedBox(matrixStack, consumer,EntityUtil.getBox(player), rgba); } if (Dungeons.renderClassName) { @@ -43,8 +43,8 @@ public class WitherHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> {withers.removeIf(wither -> wither.isRemoved() || wither.isDeadOrDying());}); - RenderingEvents.FILLED_ENTITY.register(WitherHighlight::renderFilled); - RenderingEvents.OUTLINE_ENTITY.register(WitherHighlight::renderOutline); + RenderingEvents.FILLED.register(WitherHighlight::renderFilled); + RenderingEvents.LINE.register(WitherHighlight::renderOutline); } private static AABB getBox(WitherBoss wither) { @@ -55,14 +55,14 @@ public class WitherHighlight { if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled() || MobHighlight.dontRenderHighlight) return; float[] rgba = RenderUtils.toFloats(MobHighlight.witherFilledColor); - withers.forEach(entity -> RenderUtils.renderFilled(getBox(entity), rgba)); + withers.forEach(entity -> RenderUtils.renderFilledBox(matrixStack, consumer, getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline() || MobHighlight.dontRenderHighlight) return; float[] rgba = RenderUtils.toFloats(MobHighlight.witherOutlineColor); - withers.forEach(entity -> RenderUtils.renderOutline(getBox(entity), rgba)); + withers.forEach(entity -> RenderUtils.renderOutlinedBox(matrixStack, consumer,getBox(entity), rgba)); } } @@ -111,7 +111,7 @@ public class PracticeSS { } }); - RenderingEvents.FILLED_BLOCK.register(PracticeSS::render); + RenderingEvents.FILLED.register(PracticeSS::render); Events.ON_LOCATION_CHANGE.register(location -> { reset(); return false; @@ -352,15 +352,15 @@ public class PracticeSS { if (showingPattern) { if (!ExtraOptions.realisticDelay || totalTicks - ticksLeft > START_WAIT_DURATION || endIndex != 2) { int lastIndex = getLastDisplayIndex(); - renderButtons(0, lastIndex); - renderBackground(lastIndex - 1); + renderButtons(matrixStack, consumer, 0, lastIndex); + renderBackground(matrixStack, consumer, lastIndex - 1); } } else { - renderButtons(currentIndex, endIndex); + renderButtons(matrixStack, consumer, currentIndex, endIndex); } } - private static void renderButtons(int start, int end) { + private static void renderButtons(PoseStack matrixStack, VertexConsumer consumer, int start, int end) { AABB directionBox = getBox(direction); if (directionBox == null) return; @@ -369,7 +369,7 @@ public class PracticeSS { BlockPos pos = buttons.get(i); AABB box = directionBox.move(pos.getX(), pos.getY(), pos.getZ()); float[] color = RenderUtils.toFloats(getColor(i)); - RenderUtils.renderFilled(box, color); + RenderUtils.renderFilledBox(matrixStack, consumer, box, color); } } @@ -383,7 +383,7 @@ public class PracticeSS { }; } - private static void renderBackground(int backgroundIndex) { + private static void renderBackground(PoseStack matrixStack, VertexConsumer consumer, int backgroundIndex) { if (buttons.size() > backgroundIndex && backgroundIndex >= 0) { AABB box = AABB.ofSize(buttons.get(backgroundIndex).getCenter(), 1, 1, 1); int dx, dz; @@ -408,7 +408,7 @@ public class PracticeSS { return; } } - RenderUtils.renderFilled(box.move(dx, 0, dz), new float[]{0, 0.5f, 1, 1}); + RenderUtils.renderFilledBox(matrixStack, consumer, box.move(dx, 0, dz), new float[]{0, 0.5f, 1, 1}); } } } @@ -1,11 +1,25 @@ package blade.addon.utils.rendering; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.rendertype.RenderType; +import net.minecraft.client.renderer.state.LevelRenderState; +import net.minecraft.world.phys.Vec3; + import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; public class RenderHandler { + private final RenderType renderType; + + public RenderHandler(RenderType renderType) { + this.renderType = renderType; + } + private final List<RenderingEvent> listeners = new ArrayList<>(); public void register(RenderingEvent listener) { @@ -19,4 +33,21 @@ public class RenderHandler { } } + public void init(WorldRenderContext context) { + LevelRenderState worldState = context.worldState(); + if (worldState == null) return; + Vec3 camera = worldState.cameraRenderState.pos; + PoseStack matrices = context.matrices(); + if (matrices == null) return; + matrices.pushPose(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + MultiBufferSource consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer consumer = consumers.getBuffer(renderType); + + invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); + matrices.popPose(); + } + } @@ -4,48 +4,23 @@ import net.minecraft.client.renderer.rendertype.LayeringTransform; import net.minecraft.client.renderer.rendertype.RenderSetup; import net.minecraft.client.renderer.rendertype.RenderType; -import java.util.HashMap; - public class RenderLayers { - private static final HashMap<Integer, RenderType> OUTLINE_WIDTHS = new HashMap<>(); - private static final HashMap<Integer, RenderType> OUTLINE_WIDTHS_NO_DEPTH = new HashMap<>(); - - public static final RenderType FILLED_LAYER = - RenderType.create("filled", RenderSetup.builder(RenderPipelines.FILLED_PIPELINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); - - - public static final RenderType FILLED_LAYER_NO_DEPTH = - RenderType.create("through_wall_filled", RenderSetup.builder(RenderPipelines.FILLED_PIPELINE_NO_DEPTH).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); - - public static final RenderType FILLED_ENTITY_LAYER = - RenderType.create("filled-entity", RenderSetup.builder(RenderPipelines.FILLED_ENTITY_PIPELINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); - - public static RenderType getOutline(int width, boolean depthCheck) { - if (depthCheck) { - if (OUTLINE_WIDTHS.containsKey(width)) { - return OUTLINE_WIDTHS.get(width); - } - - RenderType outline_layer = - RenderType.create("outline-entity-" + width, RenderSetup.builder(RenderPipelines.OUTLINE_ENTITY_PIPELINE).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); + public static final RenderType FILLED_DEBUG = + RenderType.create("filled-debug", RenderSetup.builder(RenderPipelines.FILLED_DEBUG).createRenderSetup()); - OUTLINE_WIDTHS.put(width, outline_layer); - return outline_layer; - } else { - if (OUTLINE_WIDTHS_NO_DEPTH.containsKey(width)) { - return OUTLINE_WIDTHS_NO_DEPTH.get(width); - } + public static final RenderType FILLED = + RenderType.create("filled", RenderSetup.builder(RenderPipelines.FILLED).createRenderSetup()); - RenderType outline_layer = - RenderType.create("outline-entity-" + width, RenderSetup.builder(RenderPipelines.OUTLINE_ENTITY_PIPELINE).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); + public static final RenderType LINE = + RenderType.create("line", RenderSetup.builder(RenderPipelines.LINE).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); - OUTLINE_WIDTHS_NO_DEPTH.put(width, outline_layer); - return outline_layer; - } + public static final RenderType FILLED_NO_DEPTH = + RenderType.create("filled-no-depth", RenderSetup.builder(RenderPipelines.FILLED_NO_DEPTH).createRenderSetup()); - } + public static final RenderType LINE_NO_DEPTH = + RenderType.create("line-no-depth", RenderSetup.builder(RenderPipelines.LINE_NO_DEPTH).setOutline(RenderSetup.OutlineProperty.IS_OUTLINE).setLayeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).createRenderSetup()); } @@ -8,31 +8,36 @@ import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.resources.Identifier; public class RenderPipelines { - public static final RenderPipeline FILLED_PIPELINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP) + public static final RenderPipeline FILLED_DEBUG = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-debug")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) .build()); - public static final RenderPipeline FILLED_PIPELINE_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "through-walls-filled")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP) - .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) - .build()); - public static final RenderPipeline FILLED_ENTITY_PIPELINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-entity")) - .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP) + public static final RenderPipeline FILLED = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) .withDepthWrite(true) .build()); - public static final RenderPipeline OUTLINE_ENTITY_PIPELINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "outline-entity")) + public static final RenderPipeline LINE = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "line")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) .withDepthWrite(true) .build()); - public static final RenderPipeline OUTLINE_ENTITY_PIPELINE_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) - .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "outline-entity-no-depth")) + + public static final RenderPipeline FILLED_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.DEBUG_FILLED_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(Constants.NAMESPACE, "filled-no-depth")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS) + .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) + .build()); + + + public static final RenderPipeline LINE_NO_DEPTH = net.minecraft.client.renderer.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.renderer.RenderPipelines.LINES_SNIPPET) + .withLocation(Identifier.fromNamespaceAndPath(blade.addon.utils.Constants.NAMESPACE, "line-no-depth")) + .withVertexFormat(DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH, VertexFormat.Mode.LINES) .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) .build()); @@ -1,22 +1,23 @@ package blade.addon.utils.rendering; +import blade.addon.features.highlight.MobHighlight; import blade.addon.utils.Constants; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.data.EntityUtil; import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.gizmos.GizmoStyle; import net.minecraft.gizmos.Gizmos; import net.minecraft.network.chat.Component; -import net.minecraft.util.ARGB; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4f; import org.joml.Vector3f; public class RenderUtils { @@ -88,19 +89,6 @@ public class RenderUtils { context.drawString(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); } - public static void renderFilled(AABB box, float[] rgba) { - if (rgba[3] == 0) return; - Gizmos.cuboid(box, GizmoStyle.fill(ARGB.colorFromFloat(rgba[3], rgba[0], rgba[1], rgba[2]))); // Could be filledAndStroked - //VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - } - - public static void renderOutline(AABB box, float[] rgba) { - if (rgba[3] == 0) return; - Gizmos.cuboid(box, GizmoStyle.stroke(ARGB.colorFromFloat(rgba[3], rgba[0], rgba[1], rgba[2]))); // Could be filledAndStroked - //VertexRendering.drawBox(matrixStack.peek(), consumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - } - - public static void renderText(WorldRenderContext context, PoseStack matrices, Component text, double x, double y, double z, float scale) { Minecraft client = Minecraft.getInstance(); Font textRenderer = client.font; @@ -137,7 +125,7 @@ public class RenderUtils { renderLineTo(context, pos.x, pos.y, pos.z, color); } - public static String formatNumber(float num) { + public static String formatNumber(float num) { if (Floor7.capitalizeHealthNumbers) { if (num >= 1e9) return String.format("%.1fB", num / 1e9); if (num >= 1e6) return String.format("%.1fM", num / 1e6); @@ -147,6 +135,142 @@ public class RenderUtils { if (num >= 1e6) return String.format("%.1fm", num / 1e6); if (num >= 1e3) return String.format("%.1fk", num / 1e3); } - return num + ""; - } + return num + ""; + } + + private static void quad(Matrix4f matrix, + VertexConsumer consumer, + double x1, double y1, double z1, + double x2, double y2, double z2, + double x3, double y3, double z3, + double x4, double y4, double z4, + + float r, float g, float b, float a) { + + consumer.addVertex(matrix, (float) x1, (float) y1, (float) z1) + .setColor(r, g, b, a) + .setNormal(0, 1, 0); + + consumer.addVertex(matrix, (float) x2, (float) y2, (float) z2) + .setColor(r, g, b, a) + .setNormal(0, 1, 0); + + consumer.addVertex(matrix, (float) x3, (float) y3, (float) z3) + .setColor(r, g, b, a) + .setNormal(0, 1, 0); + + consumer.addVertex(matrix, (float) x4, (float) y4, (float) z4) + .setColor(r, g, b, a) + .setNormal(0, 1, 0); + + } + + private static void verticalLine(Matrix4f matrix, + VertexConsumer consumer, + double x1, double y1, double z1, + double x2, double y2, double z2, + float r, float g, float b, float a, float width) { + + consumer.addVertex(matrix, (float) x1, (float) y1, (float) z1) + .setColor(r, g, b, a) + .setNormal(1, 0, 0).setLineWidth(width); + + consumer.addVertex(matrix, (float) x2, (float) y2, (float) z2) + .setColor(r, g, b, a) + .setNormal(1, 0, 0).setLineWidth(width); + + consumer.addVertex(matrix, (float) x1, (float) y1, (float) z1) + .setColor(r, g, b, a) + .setNormal(0, 0, 1).setLineWidth(width); + + consumer.addVertex(matrix, (float) x2, (float) y2, (float) z2) + .setColor(r, g, b, a) + .setNormal(0, 0, 1).setLineWidth(width); + } + + private static void horizontalLine(Matrix4f matrix, + VertexConsumer consumer, + double x1, double y1, double z1, + double x2, double y2, double z2, + float r, float g, float b, float a, float width) { + + consumer.addVertex(matrix, (float) x1, (float) y1, (float) z1) + .setColor(r, g, b, a) + .setNormal(0, 1, 0).setLineWidth(width); + + consumer.addVertex(matrix, (float) x2, (float) y2, (float) z2) + .setColor(r, g, b, a) + .setNormal(0, 1, 0).setLineWidth(width); + } + + public static void renderOutlinedBox(PoseStack matrices, + VertexConsumer consumer, + AABB box, + float[] rgba) { + + + if (rgba[3] == 0) return; + float r = rgba[0]; + float g = rgba[1]; + float b = rgba[2]; + float a = rgba[3]; + + Matrix4f matrix = matrices.last().pose(); + + double minX = box.minX; + double minY = box.minY; + double minZ = box.minZ; + double maxX = box.maxX; + double maxY = box.maxY; + double maxZ = box.maxZ; + + horizontalLine(matrix, consumer, minX, minY, minZ, minX, maxY, minZ, r, g, b, a, MobHighlight.outlineWidth); + horizontalLine(matrix, consumer, maxX, minY, minZ, maxX, maxY, minZ, r, g, b, a, MobHighlight.outlineWidth); + horizontalLine(matrix, consumer, minX, minY, maxZ, minX, maxY, maxZ, r, g, b, a, MobHighlight.outlineWidth); + horizontalLine(matrix, consumer, maxX, minY, maxZ, maxX, maxY, maxZ, r, g, b, a, MobHighlight.outlineWidth); + + verticalLine(matrix, consumer, minX, maxY, minZ, maxX, maxY, minZ, r, g, b, a, MobHighlight.outlineWidth); + verticalLine(matrix, consumer, maxX, maxY, minZ, maxX, maxY, maxZ, r, g, b, a, MobHighlight.outlineWidth); + verticalLine(matrix, consumer, maxX, maxY, maxZ, minX, maxY, maxZ, r, g, b, a, MobHighlight.outlineWidth); + verticalLine(matrix, consumer, minX, maxY, maxZ, minX, maxY, minZ, r, g, b, a, MobHighlight.outlineWidth); + + verticalLine(matrix, consumer, minX, minY, minZ, maxX, minY, minZ, r, g, b, a, MobHighlight.outlineWidth); + verticalLine(matrix, consumer, maxX, minY, minZ, maxX, minY, maxZ, r, g, b, a, MobHighlight.outlineWidth); + verticalLine(matrix, consumer, maxX, minY, maxZ, minX, minY, maxZ, r, g, b, a, MobHighlight.outlineWidth); + verticalLine(matrix, consumer, minX, minY, maxZ, minX, minY, minZ, r, g, b, a, MobHighlight.outlineWidth); + + + } + + public static void renderFilledBox(PoseStack matrices, + VertexConsumer consumer, + AABB box, + float[] rgba) { + + if (rgba[3] == 0) return; + float r = rgba[0]; + float g = rgba[1]; + float b = rgba[2]; + float a = rgba[3]; + + Matrix4f matrix = matrices.last().pose(); + + double minX = box.minX; + double minY = box.minY; + double minZ = box.minZ; + double maxX = box.maxX; + double maxY = box.maxY; + double maxZ = box.maxZ; + + quad(matrix, consumer, minX, minY, minZ, minX, maxY, minZ, maxX, maxY, minZ, maxX, minY, minZ, r, g, b, a); + quad(matrix, consumer, maxX, minY, minZ, maxX, maxY, minZ, maxX, maxY, maxZ, maxX, minY, maxZ, r, g, b, a); + + quad(matrix, consumer, maxX, minY, maxZ, maxX, maxY, maxZ, minX, maxY, maxZ, minX, minY, maxZ, r, g, b, a); + quad(matrix, consumer, minX, minY, maxZ, minX, maxY, maxZ, minX, maxY, minZ, minX, minY, minZ, r, g, b, a); + + quad(matrix, consumer, minX, maxY, minZ, minX, maxY, maxZ, maxX, maxY, maxZ, maxX, maxY, minZ, r, g, b, a); + quad(matrix, consumer, maxX, minY, minZ, maxX, minY, maxZ, minX, minY, maxZ, minX, minY, minZ, r, g, b, a); + + } + } @@ -1,135 +1,21 @@ package blade.addon.utils.rendering; -import blade.addon.features.highlight.MobHighlight; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.state.LevelRenderState; -import net.minecraft.world.phys.Vec3; public class RenderingEvents { - public static RenderHandler FILLED_BLOCK = new RenderHandler(); - public static RenderHandler NO_DEPTH_FILLED = new RenderHandler(); - public static RenderHandler FILLED_ENTITY = new RenderHandler(); - public static RenderHandler OUTLINE_ENTITY = new RenderHandler(); - public static RenderHandler NO_DEPTH_OUTLINE_ENTITY = new RenderHandler(); - public static RenderHandler LINE = new RenderHandler(); + public static RenderHandler FILLED_DEBUG = new RenderHandler(RenderLayers.FILLED_DEBUG); + public static RenderHandler FILLED = new RenderHandler(RenderLayers.FILLED); + public static RenderHandler LINE = new RenderHandler(RenderLayers.LINE); + public static RenderHandler FILLED_NO_DEPTH = new RenderHandler(RenderLayers.FILLED_NO_DEPTH); + public static RenderHandler LINE_NO_DEPTH = new RenderHandler(RenderLayers.LINE_NO_DEPTH); public static void init() { - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::filled); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::filledNoDepth); - WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityFilled); - WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityOutline); - WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityOutlineNoDepth); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::debugLine); - - } - - private static void filled(WorldRenderContext context) { - LevelRenderState worldState = context.worldState(); - if (worldState == null) return; - Vec3 camera = worldState.cameraRenderState.pos; - PoseStack matrices = context.matrices(); - if (matrices == null) return; - matrices.pushPose(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - MultiBufferSource consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.FILLED_LAYER); - - FILLED_BLOCK.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); - matrices.popPose(); - } - - private static void filledNoDepth(WorldRenderContext context) { - LevelRenderState worldState = context.worldState(); - if (worldState == null) return; - Vec3 camera = worldState.cameraRenderState.pos; - PoseStack matrices = context.matrices(); - if (matrices == null) return; - matrices.pushPose(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - MultiBufferSource consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.FILLED_LAYER_NO_DEPTH); - - NO_DEPTH_FILLED.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); - matrices.popPose(); + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(FILLED_DEBUG::init); + WorldRenderEvents.AFTER_ENTITIES.register(FILLED::init); + WorldRenderEvents.AFTER_ENTITIES.register(LINE::init); + WorldRenderEvents.AFTER_ENTITIES.register(FILLED_NO_DEPTH::init); + WorldRenderEvents.AFTER_ENTITIES.register(LINE_NO_DEPTH::init); } - - private static void entityFilled(WorldRenderContext context) { - LevelRenderState worldState = context.worldState(); - if (worldState == null) return; - Vec3 camera = worldState.cameraRenderState.pos; - PoseStack matrices = context.matrices(); - if (matrices == null) return; - matrices.pushPose(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - MultiBufferSource consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - - FILLED_ENTITY.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); - matrices.popPose(); - } - - - private static void entityOutline(WorldRenderContext context) { - LevelRenderState worldState = context.worldState(); - if (worldState == null) return; - Vec3 camera = worldState.cameraRenderState.pos; - PoseStack matrices = context.matrices(); - if (matrices == null) return; - matrices.pushPose(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - MultiBufferSource consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth, true)); - - OUTLINE_ENTITY.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); - matrices.popPose(); - } - - private static void entityOutlineNoDepth(WorldRenderContext context) { - LevelRenderState worldState = context.worldState(); - if (worldState == null) return; - Vec3 camera = worldState.cameraRenderState.pos; - PoseStack matrices = context.matrices(); - if (matrices == null) return; - matrices.pushPose(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - MultiBufferSource consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth, false)); - - NO_DEPTH_OUTLINE_ENTITY.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); - matrices.popPose(); - } - - private static void debugLine(WorldRenderContext context) { - LevelRenderState worldState = context.worldState(); - if (worldState == null) return; - Vec3 camera = context.worldState().cameraRenderState.pos; - PoseStack matrices = context.matrices(); - if (matrices == null) return; - matrices.pushPose(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - MultiBufferSource consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.getOutline(4, true)); - - LINE.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); - matrices.popPose(); - } - } |
- swapped drawcontext variable name to graphics查看变更src/main/java/blade/addon/features/dungeon/BloodNotifier.java | 4 ++-- src/main/java/blade/addon/features/dungeon/ChestCounter.java | 6 +++--- src/main/java/blade/addon/features/dungeon/QuizTimer.java | 6 +++--- src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 18 +++++++++--------- src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/maxor/CrystalSpawn.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorStun.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorTickTimer.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/storm/DistanceToLedge.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/storm/PillarExplode.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/f7/storm/StormTickTimer.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/f7/terms/CurrentSection.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/terms/DeviceNotifier.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/terms/MelodyWarning.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/terms/SectionCompletion.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/terms/SectionProgress.java | 6 +++--- src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 4 ++-- src/main/java/blade/addon/features/item/HeldItemToolTip.java | 4 ++-- src/main/java/blade/addon/features/notifications/Notifications.java | 4 ++-- src/main/java/blade/addon/features/other/ArrowSwapper.java | 8 ++++---- src/main/java/blade/addon/features/other/KickedTimer.java | 4 ++-- src/main/java/blade/addon/features/other/RagDisplay.java | 4 ++-- src/main/java/blade/addon/features/other/ReaperDisplay.java | 4 ++-- src/main/java/blade/addon/features/other/SelectedPet.java | 4 ++-- src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 26 +++++++++++++------------- src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 14 +++++++------- 33 files changed, 104 insertions(+), 104 deletions(-) @@ -53,8 +53,8 @@ public class BloodNotifier { return Dungeons.alertBloodSpawns && System.currentTimeMillis() - prevTime < 2000 && correctClass(); } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, Component.literal("First four mobs spawned!"), Constants.RED); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, Component.literal("First four mobs spawned!"), Constants.RED); } } @@ -66,14 +66,14 @@ public class ChestCounter { return Dungeons.displayChestCount && Location.inDungeon(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { int x = component.getScaledX(); int y = component.getScaledY(); if (hasUpdatedData) { - RenderUtils.drawPrefixedText(component, context, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); + RenderUtils.drawPrefixedText(component, graphics, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); } else { - context.drawString(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); + graphics.drawString(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); } } @@ -56,7 +56,7 @@ public class QuizTimer { return Dungeons.quizTimer && tick > 0; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { Font textRenderer = Minecraft.getInstance().font; if (textRenderer == null) return; @@ -65,9 +65,9 @@ public class QuizTimer { .append(Component.literal(stage + "/3").withColor(0xffffffff) .append(Component.literal("): ").withColor(ExtraOptions.timerPrefixColor)) .append(Component.literal(Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION) + "s").withColor(0xffffffff))); - context.drawString(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); + graphics.drawString(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); } else { - RenderUtils.drawPrefixedTimer(component, context, "Quiz", tick); + RenderUtils.drawPrefixedTimer(component, graphics, "Quiz", tick); } } @@ -134,13 +134,13 @@ public class RunStartValidator { return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { if (hasDupeClasses) { - RenderUtils.drawCenteredText(context, component, DUPE_CLASS_TEXT); + RenderUtils.drawCenteredText(graphics, component, DUPE_CLASS_TEXT); } else if (notEnoughPlayers) { - RenderUtils.drawCenteredText(context, component, PLAYER_COUNT_TEXT); + RenderUtils.drawCenteredText(graphics, component, PLAYER_COUNT_TEXT); } else { - RenderUtils.drawCenteredText(context, component, Component.literal("§cSome warning text")); + RenderUtils.drawCenteredText(graphics, component, Component.literal("§cSome warning text")); } } } @@ -42,8 +42,8 @@ public class WarpCooldown { } } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); - RenderUtils.drawPrefixedTimer(component, context, "Warp Cooldown", timeRemaining); + RenderUtils.drawPrefixedTimer(component, graphics, "Warp Cooldown", timeRemaining); } } @@ -271,9 +271,9 @@ public class RelicTimer { return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && !Floor7.replaceWithProgressBar; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { int color = tick > 7 ? GREEN_COLOR : RED_COLOR; - RenderUtils.drawTimer(component, context, tick, color); + RenderUtils.drawTimer(component, graphics, tick, color); } public static boolean displayProgressBar() { @@ -281,7 +281,7 @@ public class RelicTimer { return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && Floor7.replaceWithProgressBar; } - public static void renderProgressBar(HUDComponent component, GuiGraphics context) { + public static void renderProgressBar(HUDComponent component, GuiGraphics graphics) { int x = component.getScaledX(); int y = component.getScaledY(); @@ -307,7 +307,7 @@ public class RelicTimer { message.append("§8]"); } - RenderUtils.drawCenteredText(context, Minecraft.getInstance().font, Component.literal(message.toString()), x, y, component.getWidth(), 0xffffffff); + RenderUtils.drawCenteredText(graphics, Minecraft.getInstance().font, Component.literal(message.toString()), x, y, component.getWidth(), 0xffffffff); } } @@ -99,7 +99,7 @@ public class DragSpawnTimer { return Floor7.dragSpawnTimers && currentDragon != Dragon.NONE; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, tick, currentDragon.color); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, tick, currentDragon.color); } } @@ -26,11 +26,11 @@ public class InvincibilityDuration { return ticks > 0 && Dungeons.InvincibilityDuration; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { int color = 0xffffffff; if (Dungeons.useStatusColorForInvincibility) { color = RenderUtils.getStatusColor(40, 20, ticks); } - RenderUtils.drawTimer(component, context, ticks, color); + RenderUtils.drawTimer(component, graphics, ticks, color); } } @@ -190,23 +190,23 @@ public class InvincibilityTimer { } } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { int x = component.getScaledX(); int y = component.getScaledY(); if (Dungeons.useSprites) { - drawSprite(context, BONZO_SPRITE, x, y, bonzoMaskOn, bonzoMaskTicks, formatTimer(bonzoMaskTicks)); - drawSprite(context, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, spiritMaskOn, spiritMaskTicks, formatTimer(spiritMaskTicks)); - drawSprite(context, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); + drawSprite(graphics, BONZO_SPRITE, x, y, bonzoMaskOn, bonzoMaskTicks, formatTimer(bonzoMaskTicks)); + drawSprite(graphics, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, spiritMaskOn, spiritMaskTicks, formatTimer(spiritMaskTicks)); + drawSprite(graphics, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); } else { if (Dungeons.removeMaskPart) { - context.drawString(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo "), x, y, 0xffffffff, true); - context.drawString(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit "), x, y + TEXT_HEIGHT, 0xffffffff, true); + graphics.drawString(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo "), x, y, 0xffffffff, true); + graphics.drawString(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit "), x, y + TEXT_HEIGHT, 0xffffffff, true); } else { - context.drawString(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); - context.drawString(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); + graphics.drawString(Minecraft.getInstance().font, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); + graphics.drawString(Minecraft.getInstance().font, getText(spiritMaskTicks, spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); } - context.drawString(Minecraft.getInstance().font, getText(phoenixTicks, phoenixOn, "Phoenix "), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); + graphics.drawString(Minecraft.getInstance().font, getText(phoenixTicks, phoenixOn, "Phoenix "), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); } } } @@ -65,7 +65,7 @@ public class LocationNotifier { return ticks > 0 && Floor7.displayLocationNotification; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, notification); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, notification); } } @@ -98,16 +98,16 @@ public class CrystalSpawn { return tick > 0 && Location.inDungeon() && Phase.inP1() && Floor7.enableCrystalSpawnTime; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, tick, Constants.LIGHT_PURPLE); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, tick, Constants.LIGHT_PURPLE); } public static boolean displayNotification() { return (Floor7.instantlyDisplayCrystalReminder || tickSincePicked > REMINDER_TICK) && Location.inDungeon() && Phase.inP1() && Floor7.crystalPlaceReminder && pickedUp; } - public static void renderNotification(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, Component.literal("§bPlace Crystal!")); + public static void renderNotification(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, Component.literal("§bPlace Crystal!")); } @@ -51,8 +51,8 @@ public class MaxorStun { return tick > 0 && Location.inDungeon() && Phase.inP1() && Floor7.maxorStunDuration && stunned; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawPrefixedText(component, context, "Stunned", TextUtil.formatTicks(tick)); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawPrefixedText(component, graphics, "Stunned", TextUtil.formatTicks(tick)); } @@ -28,8 +28,8 @@ public class MaxorTickTimer { return Floor7.enableMaxorTickTimer && Location.inDungeon() && Phase.inP1(); } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, tick, 0xffffffff); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, tick, 0xffffffff); } } @@ -39,7 +39,7 @@ public class DistanceToLedge { return Phase.inP2() && !Phase.stormDead() && (DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER)); } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, getDistance(), 0xffffffff); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, getDistance(), 0xffffffff); } } @@ -43,16 +43,16 @@ public class PillarExplode { return Floor7.timePillarExplosion && tick > 0; } - public static void renderTimer(HUDComponent component, GuiGraphics context) { + public static void renderTimer(HUDComponent component, GuiGraphics graphics) { int color = tick < 6 ? Constants.GREEN : Constants.RED; - RenderUtils.drawTimer(component, context, tick, color); + RenderUtils.drawTimer(component, graphics, tick, color); } public static boolean display() { return Floor7.notifyStormCrush && tick > 0; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, Component.literal("§6||| §bStorm crushed! §6|||")); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, Component.literal("§6||| §bStorm crushed! §6|||")); } } @@ -72,19 +72,19 @@ public class StormTickTimer { return Floor7.enableStormTickTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { double num = tick * Constants.TICK_DURATION; if (Floor7.tickDownStormTickTimer) { num = CRUSH_TICK * Constants.TICK_DURATION - num; } - RenderUtils.drawTimer(component, context, num, Floor7.stormTickTimerColor); + RenderUtils.drawTimer(component, graphics, num, Floor7.stormTickTimerColor); } public static boolean displayDeathTime() { return Floor7.enableStormDeathTime && Location.inDungeon() && Phase.inP2() && !Phase.stormDead() && deathTime > 0 && deathStartDisplayTime > System.currentTimeMillis() - DEATH_DISPLAY_DURATION; } - public static void renderDeathTime(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, deathTime, Constants.DARK_PURPLE); + public static void renderDeathTime(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, deathTime, Constants.DARK_PURPLE); } } @@ -26,8 +26,8 @@ public class CurrentSection { return Floor7.showCurrentSection && Phase.inTerminals(); } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawPrefixedText(component, context, "Section", " " + section); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawPrefixedText(component, graphics, "Section", " " + section); } } @@ -74,8 +74,8 @@ public class DeviceNotifier { return showNotification; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { if (System.currentTimeMillis() - completedTime >= TOTAL_DURATION) showNotification = false; - RenderUtils.drawCenteredText(context, component, Component.literal("§aDevice Completed!")); + RenderUtils.drawCenteredText(graphics, component, Component.literal("§aDevice Completed!")); } } @@ -31,7 +31,7 @@ public class GoldorTickTimer { return Floor7.enableGoldorTickTimer && Location.inDungeon() && Phase.inTerminals(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { double num = tick * Constants.TICK_DURATION; double mod = num % 3; if (Floor7.inDeathTicks && !Floor7.makeGoldorTickUp) mod = 3.0 - mod; @@ -39,6 +39,6 @@ public class GoldorTickTimer { int color = (mod < 1 ? Constants.GREEN : mod < 2 ? Constants.GOLD : Constants.RED); - RenderUtils.drawTimer(component, context, num, color); + RenderUtils.drawTimer(component, graphics, num, color); } } @@ -100,12 +100,12 @@ public class LeapNotification { return Floor7.leapNotifications && inBounds && Phase.inBoss() && Location.inDungeon(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { int maxCount = getMaxCount(); String startFormat; startFormat = (maxCount - count <= 1? "§9" : "§4"); - RenderUtils.drawCenteredText(context, component, Component.literal(startFormat + count + "§9/" + maxCount + " Players Leaped")); + RenderUtils.drawCenteredText(graphics, component, Component.literal(startFormat + count + "§9/" + maxCount + " Players Leaped")); } } @@ -80,7 +80,7 @@ public class MelodyWarning { return melodyStarted && Floor7.notifiyMelody && !ownUsername; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { DungeonClass dungeonClass = DungeonClass.getClass(name); int num = Math.min(furthestProgress / 25, 3); @@ -94,7 +94,7 @@ public class MelodyWarning { Component text = nameText.append(infoText); - RenderUtils.drawCenteredText(context, component, text); + RenderUtils.drawCenteredText(graphics, component, text); } } @@ -25,8 +25,8 @@ public class SectionCompletion { return System.currentTimeMillis() - prevTime < 1000 && Floor7.sectionCompletionNotification; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, Component.literal("Section completed!").withStyle(ChatFormatting.GREEN)); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, Component.literal("Section completed!").withStyle(ChatFormatting.GREEN)); } } @@ -100,11 +100,11 @@ public class SectionProgress { return Floor7.showSectionProgress && Phase.inTerminals(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { if (Floor7.sectionPrevObjective) { - RenderUtils.drawCenteredText(context, component, Component.literal(objectiveFormat + prevObjective + " ").append(getProgressText())); + RenderUtils.drawCenteredText(graphics, component, Component.literal(objectiveFormat + prevObjective + " ").append(getProgressText())); } else { - RenderUtils.drawCenteredText(context, component, getProgressText()); + RenderUtils.drawCenteredText(graphics, component, getProgressText()); } } @@ -32,8 +32,8 @@ public class TermStartTimer { return Floor7.enableTermStartTimer && Location.inDungeon() && Phase.inP2() && Phase.stormDead(); } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { double num = tick * Constants.TICK_DURATION; - RenderUtils.drawCenteredText(context, component, Component.literal(Constants.DECIMAL_FORMAT.format(num)), Constants.YELLOW); + RenderUtils.drawCenteredText(graphics, component, Component.literal(Constants.DECIMAL_FORMAT.format(num)), Constants.YELLOW); } } @@ -29,9 +29,9 @@ public class HeldItemToolTip { return ExtraOptions.moveToolTip && heldItemFade > 0; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { int currentColor = heldItemFade > 0? color: 0xffffffff; - RenderUtils.drawCenteredText(context, component, tooltip, currentColor); + RenderUtils.drawCenteredText(graphics, component, tooltip, currentColor); } } @@ -77,9 +77,9 @@ public class Notifications { return tick > 0; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { Component text = Component.literal(message != null ? message : "Some notification"); - RenderUtils.drawCenteredText(context, component, text); + RenderUtils.drawCenteredText(graphics, component, text); } public static void setNotification(Notification notification) { @@ -80,15 +80,15 @@ public class ArrowSwapper { return ExtraOptions.displayCurrentArrow; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawText(context, component, displayedText, 0xffffffff); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawText(graphics, component, displayedText, 0xffffffff); } public static boolean displayNotification() { return ExtraOptions.arrowSwapNotification && tick > 0; } - public static void renderNotification(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, displayedText, 0xffffffff); + public static void renderNotification(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, displayedText, 0xffffffff); } } @@ -30,11 +30,11 @@ public class KickedTimer { return isKicked; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { long diff = System.currentTimeMillis() - kickedTime; if (diff > 60 * 1000) isKicked = false; double drawnTime = Math.min(diff / 1000.0, 60.0); - RenderUtils.drawPrefixedTimer(component, context, "Time kicked", drawnTime); + RenderUtils.drawPrefixedTimer(component, graphics, "Time kicked", drawnTime); } } @@ -53,8 +53,8 @@ public class RagDisplay { return tick > 0; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, tick, Constants.YELLOW); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, tick, Constants.YELLOW); } } @@ -34,7 +34,7 @@ public class ReaperDisplay { return tick > 0; } - public static void render(HUDComponent component, GuiGraphics context) { - RenderUtils.drawTimer(component, context, tick, Constants.RED); + public static void render(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawTimer(component, graphics, tick, Constants.RED); } } @@ -191,8 +191,8 @@ public class SelectedPet { return ExtraOptions.sendPetSwapNotification && tick > 0; } - public static void renderNotification(HUDComponent component, GuiGraphics context) { - RenderUtils.drawCenteredText(context, component, currentPetText); + public static void renderNotification(HUDComponent component, GuiGraphics graphics) { + RenderUtils.drawCenteredText(graphics, component, currentPetText); } } @@ -48,31 +48,31 @@ public class CombinedScreenNotifications { return false; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { if (RunStartValidator.display()) { - RunStartValidator.render(component, context); + RunStartValidator.render(component, graphics); } else if (KeyNotifier.display()) { - KeyNotifier.render(component, context); + KeyNotifier.render(component, graphics); } else if (DeviceNotifier.display()) { - DeviceNotifier.render(component, context); + DeviceNotifier.render(component, graphics); } else if (MelodyWarning.display()) { - MelodyWarning.render(component, context); + MelodyWarning.render(component, graphics); } else if (PillarExplode.display()) { - PillarExplode.render(component, context); + PillarExplode.render(component, graphics); } else if (CrystalSpawn.displayNotification()) { - CrystalSpawn.renderNotification(component, context); + CrystalSpawn.renderNotification(component, graphics); }else if (Notifications.display()) { - Notifications.render(component, context); + Notifications.render(component, graphics); } else if (SelectedPet.displayNotification()) { - SelectedPet.renderNotification(component, context); + SelectedPet.renderNotification(component, graphics); } else if (ArrowSwapper.displayNotification()) { - ArrowSwapper.renderNotification(component, context); + ArrowSwapper.renderNotification(component, graphics); } else if (SectionCompletion.display()) { - SectionCompletion.render(component, context); + SectionCompletion.render(component, graphics); }else if (BloodNotifier.display()) { - BloodNotifier.render(component, context); + BloodNotifier.render(component, graphics); }else { - RenderUtils.drawCenteredText(context, component, Component.literal("Some notification")); + RenderUtils.drawCenteredText(graphics, component, Component.literal("Some notification")); } } @@ -31,19 +31,19 @@ public class CombinedTickTimer { return false; } - public static void render(HUDComponent component, GuiGraphics context) { + public static void render(HUDComponent component, GuiGraphics graphics) { if (CrystalSpawn.display()) { - CrystalSpawn.render(component, context); + CrystalSpawn.render(component, graphics); } else if (StormTickTimer.display()) { - StormTickTimer.render(component, context); + StormTickTimer.render(component, graphics); } else if (TermStartTimer.display()) { - TermStartTimer.render(component, context); + TermStartTimer.render(component, graphics); } else if (GoldorTickTimer.display()) { - GoldorTickTimer.render(component, context); + GoldorTickTimer.render(component, graphics); } else if (RelicTimer.display()) { - RelicTimer.render(component, context); + RelicTimer.render(component, graphics); } else { - RenderUtils.drawCenteredText(context, component, Component.literal(Constants.DECIMAL_FORMAT.format(0.0))); + RenderUtils.drawCenteredText(graphics, component, Component.literal(Constants.DECIMAL_FORMAT.format(0.0))); } } |
- migrated to mojang mappings查看变更build.gradle | 3 +-
gradle.properties | 6 +-
src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 11 +-
src/main/java/blade/addon/features/dungeon/BloodNotifier.java | 12 +-
src/main/java/blade/addon/features/dungeon/ChestCounter.java | 19 +-
src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 5 +-
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 16 +-
src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 54 +++---
src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 45 +++--
src/main/java/blade/addon/features/dungeon/LeapMessage.java | 8 +-
src/main/java/blade/addon/features/dungeon/LeapOrder.java | 25 ++-
src/main/java/blade/addon/features/dungeon/QuizTimer.java | 22 +--
src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 35 ++--
src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 11 +-
src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 5 +-
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 37 ++--
src/main/java/blade/addon/features/dungeon/f7/PredevTimer.java | 8 +-
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 94 +++++-----
src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 28 +--
src/main/java/blade/addon/features/dungeon/f7/dragons/Dragon.java | 18 +-
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonHealth.java | 25 ++-
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonTracer.java | 6 +-
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 57 +++---
src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskHighlight.java | 6 +-
src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 13 +-
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 18 +-
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 52 +++---
src/main/java/blade/addon/features/dungeon/f7/maxor/CrystalSpawn.java | 23 ++-
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorStun.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorTickTimer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/storm/DistanceToLedge.java | 18 +-
src/main/java/blade/addon/features/dungeon/f7/storm/PillarExplode.java | 14 +-
src/main/java/blade/addon/features/dungeon/f7/storm/StormTickTimer.java | 13 +-
src/main/java/blade/addon/features/dungeon/f7/terms/CurrentSection.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/DeviceNotifier.java | 34 ++--
src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 59 +++---
src/main/java/blade/addon/features/dungeon/f7/terms/MelodyWarning.java | 17 +-
src/main/java/blade/addon/features/dungeon/f7/terms/SectionCompletion.java | 10 +-
src/main/java/blade/addon/features/dungeon/f7/terms/SectionProgress.java | 14 +-
src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 8 +-
src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 5 +-
src/main/java/blade/addon/features/filter/FilterEntry.java | 89 +++++----
src/main/java/blade/addon/features/filter/FilterList.java | 62 +++----
src/main/java/blade/addon/features/filter/Filters.java | 5 +-
src/main/java/blade/addon/features/highlight/BatHighlight.java | 17 +-
src/main/java/blade/addon/features/highlight/MimicHighlight.java | 21 +--
src/main/java/blade/addon/features/highlight/MobHighlight.java | 101 +++++-----
src/main/java/blade/addon/features/highlight/SheepHighlight.java | 17 +-
src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 25 ++-
src/main/java/blade/addon/features/highlight/WitherHighlight.java | 23 ++-
src/main/java/blade/addon/features/item/DropAnimation.java | 4 +-
src/main/java/blade/addon/features/item/HeldItemToolTip.java | 14 +-
src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 31 ++--
src/main/java/blade/addon/features/item/ProtectItem.java | 63 ++++---
src/main/java/blade/addon/features/item/SelectedPetHighlight.java | 19 +-
src/main/java/blade/addon/features/item/StarCountHighlight.java | 28 +--
src/main/java/blade/addon/features/notifications/Notification.java | 9 +-
src/main/java/blade/addon/features/notifications/NotificationEditScreen.java | 40 ++--
src/main/java/blade/addon/features/notifications/NotificationEntry.java | 60 +++---
src/main/java/blade/addon/features/notifications/NotificationList.java | 46 ++---
src/main/java/blade/addon/features/notifications/Notifications.java | 15 +-
src/main/java/blade/addon/features/other/ArrowSwapper.java | 31 ++--
src/main/java/blade/addon/features/other/CompactHoppity.java | 5 +-
src/main/java/blade/addon/features/other/DianaNotifier.java | 18 +-
src/main/java/blade/addon/features/other/InventoryButton.java | 25 ++-
src/main/java/blade/addon/features/other/KickedTimer.java | 4 +-
src/main/java/blade/addon/features/other/PracticeSS.java | 83 +++++----
src/main/java/blade/addon/features/other/RagDisplay.java | 16 +-
src/main/java/blade/addon/features/other/ReaperDisplay.java | 8 +-
src/main/java/blade/addon/features/other/SearchBar.java | 48 ++---
src/main/java/blade/addon/features/other/SelectedPet.java | 57 +++---
src/main/java/blade/addon/features/other/SwingAnimation.java | 2 +-
src/main/java/blade/addon/features/sound/BonzoSound.java | 10 +-
src/main/java/blade/addon/features/sound/TubaSound.java | 12 +-
src/main/java/blade/addon/mixin/{StuckArrowsFeatureRendererMixin.java => ArrowLayerMixin.java} | 8 +-
src/main/java/blade/addon/mixin/{BossBarHudMixin.java => BossHealthOverlayMixin.java} | 20 +-
src/main/java/blade/addon/mixin/ChatComponentMixin.java | 26 +++
src/main/java/blade/addon/mixin/ChatHudAccessor.java | 26 ---
src/main/java/blade/addon/mixin/ChatScreenMixin.java | 44 ++---
src/main/java/blade/addon/mixin/ClientPacketListenerMixin.java | 121 ++++++++++++
src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 121 ------------
src/main/java/blade/addon/mixin/{ClientConnectionMixin.java => ConnectionMixin.java} | 24 +--
src/main/java/blade/addon/mixin/DrawContextMixin.java | 50 -----
src/main/java/blade/addon/mixin/EffectsInInventoryMixin.java | 30 +++
src/main/java/blade/addon/mixin/EnderPearlItemMixin.java | 12 +-
src/main/java/blade/addon/mixin/EntityMixin.java | 4 +-
src/main/java/blade/addon/mixin/{EntityRenderManagerMixin.java => EntityRenderDispatcherMixin.java} | 42 ++---
src/main/java/blade/addon/mixin/EntityRendererMixin.java | 28 +--
src/main/java/blade/addon/mixin/GuiGraphicsMixin.java | 50 +++++
src/main/java/blade/addon/mixin/GuiMixin.java | 96 ++++++++++
src/main/java/blade/addon/mixin/HandledScreenMixin.java | 60 +++---
src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 44 ++---
src/main/java/blade/addon/mixin/InGameHudMixin.java | 96 ----------
src/main/java/blade/addon/mixin/{PlayerInventoryMixin.java => InventoryMixin.java} | 10 +-
src/main/java/blade/addon/mixin/InventoryScreenMixin.java | 36 ++--
src/main/java/blade/addon/mixin/ItemStackMixin.java | 2 +-
src/main/java/blade/addon/mixin/KeyboardHandlerMixin.java | 26 +++
src/main/java/blade/addon/mixin/KeyboardMixin.java | 26 ---
src/main/java/blade/addon/mixin/{ChunkMixin.java => LevelChunkMixin.java} | 8 +-
src/main/java/blade/addon/mixin/LivingEntityMixin.java | 10 +-
src/main/java/blade/addon/mixin/{ClientPlayerEntityMixin.java => LocalPlayerMixin.java} | 18 +-
src/main/java/blade/addon/mixin/{MinecraftClientMixin.java => MinecraftMixin.java} | 26 +--
src/main/java/blade/addon/mixin/{MouseMixin.java => MouseHandlerMixin.java} | 8 +-
src/main/java/blade/addon/mixin/{RecipeBookWidgetMixin.java => RecipeBookComponentMixin.java} | 14 +-
src/main/java/blade/addon/mixin/RecipeBookScreenMixin.java | 6 +-
src/main/java/blade/addon/mixin/ShovelItemMixin.java | 10 +-
src/main/java/blade/addon/mixin/SkullBlockEntityRendererMixin.java | 44 -----
src/main/java/blade/addon/mixin/SkullBlockRendererMixin.java | 44 +++++
src/main/java/blade/addon/mixin/StatusEffectsDisplayMixin.java | 32 ----
src/main/java/blade/addon/utils/Commands.java | 18 +-
src/main/java/blade/addon/utils/Keybinds.java | 134 +++++++-------
src/main/java/blade/addon/utils/Location.java | 4 +-
src/main/java/blade/addon/utils/Misc.java | 68 +++----
src/main/java/blade/addon/utils/Scheduler.java | 19 +-
src/main/java/blade/addon/utils/Waypoint.java | 17 +-
src/main/java/blade/addon/utils/config/Config.java | 519 ++++++++++++++++++++++++++--------------------------
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 8 +-
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 8 +-
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 10 +-
src/main/java/blade/addon/utils/config/values/Floor7.java | 6 +-
src/main/java/blade/addon/utils/data/EntityUtil.java | 59 +++---
src/main/java/blade/addon/utils/data/ItemUtil.java | 51 +++---
src/main/java/blade/addon/utils/data/TextUtil.java | 26 +--
src/main/java/blade/addon/utils/debug/Debug.java | 34 ++--
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 15 +-
src/main/java/blade/addon/utils/dungeon/FillHelper.java | 34 ++--
src/main/java/blade/addon/utils/dungeon/Phase.java | 15 +-
src/main/java/blade/addon/utils/dungeon/Section.java | 35 ++--
src/main/java/blade/addon/utils/dungeon/Split.java | 34 ++--
src/main/java/blade/addon/utils/events/interfaces/BlockEntityEvent.java | 2 +-
src/main/java/blade/addon/utils/events/interfaces/BlockInteractionEvent.java | 4 +-
src/main/java/blade/addon/utils/events/interfaces/EntityEvent.java | 6 +-
src/main/java/blade/addon/utils/events/interfaces/GameMessageEvent.java | 4 +-
src/main/java/blade/addon/utils/events/interfaces/LeapEvent.java | 4 +-
src/main/java/blade/addon/utils/events/interfaces/PacketEvent.java | 2 +-
src/main/java/blade/addon/utils/events/interfaces/ParticleEvent.java | 4 +-
src/main/java/blade/addon/utils/events/interfaces/PlaySoundEvent.java | 2 +-
src/main/java/blade/addon/utils/events/interfaces/PlayerListEvent.java | 4 +-
src/main/java/blade/addon/utils/events/interfaces/SlotChangeEvent.java | 2 +-
src/main/java/blade/addon/utils/interfaces/GameHud.java | 4 +-
src/main/java/blade/addon/utils/rendering/RenderLayers.java | 33 ++--
src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 30 +--
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 100 +++++-----
src/main/java/blade/addon/utils/rendering/RenderingEvent.java | 6 +-
src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 82 ++++-----
src/main/java/blade/addon/utils/rendering/drawevents/SlotEvent.java | 6 +-
src/main/java/blade/addon/utils/times/PersonalBest.java | 14 +-
src/main/resources/blade-addons.mixins.json | 36 ++--
150 files changed, 2256 insertions(+), 2307 deletions(-)@@ -60,7 +60,8 @@ repositories { dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + //mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + mappings loom.officialMojangMappings() modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" // Fabric API. This is technically optional, but you probably want it anyway. @@ -13,13 +13,13 @@ loader_version=0.18.4 loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=2.4.0 +mod_version=2.4.1 maven_group=blade.addon archives_base_name=blade-addons # Dependencies fabric_version=0.141.3+1.21.11 # I love dependencies sometimes breaking -practical_config=1.4.3 -modmenu_version = 17.0.0-beta.2 +practical_config=ca2e4a5ea86f1f8ef9de3ae2bd3c1c1b6f6108ac +modmenu_version =17.0.0-beta.2 hypixel_api_version = 1.0.1 @@ -5,8 +5,7 @@ import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; -import net.minecraft.text.Text; - +import net.minecraft.network.chat.Component; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -25,12 +24,12 @@ public class AutoRequeue { if (playerHashMap.containsKey(username)) { if (message.contains("!undt")) { playerHashMap.remove(username); - Misc.addChatMessage(Text.literal("§aDowntime removed")); + Misc.addChatMessage(Component.literal("§aDowntime removed")); } } else { if (message.contains("!dt")) { playerHashMap.put(username, message); - Misc.addChatMessage(Text.literal("§aDowntime added")); + Misc.addChatMessage(Component.literal("§aDowntime added")); } } return false; @@ -51,8 +50,8 @@ public class AutoRequeue { if (playerHashMap.isEmpty()) { Misc.executeCommand("instancerequeue"); } else { - Misc.addChatMessage(Text.literal("Downtime reasons:")); - playerHashMap.forEach((name, string) -> Misc.addChatMessage((Text.literal(name + "> " + string)))); + Misc.addChatMessage(Component.literal("Downtime reasons:")); + playerHashMap.forEach((name, string) -> Misc.addChatMessage((Component.literal(name + "> " + string)))); } @@ -8,9 +8,9 @@ import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Text; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; public class BloodNotifier { @@ -28,7 +28,7 @@ public class BloodNotifier { prevTime = System.currentTimeMillis(); if (correctClass()) { - Misc.sendSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0); + Misc.sendSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0); } } @@ -53,8 +53,8 @@ public class BloodNotifier { return Dungeons.alertBloodSpawns && System.currentTimeMillis() - prevTime < 2000 && correctClass(); } - public static void render(HUDComponent component, DrawContext context) { - RenderUtils.drawCenteredText(context, component, Text.literal("First four mobs spawned!"), Constants.RED); + public static void render(HUDComponent component, GuiGraphics context) { + RenderUtils.drawCenteredText(context, component, Component.literal("First four mobs spawned!"), Constants.RED); } } @@ -9,13 +9,12 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Text; - import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; public class ChestCounter { @@ -35,7 +34,7 @@ public class ChestCounter { Events.ON_PLAYER_ENTRY.register(receivedEntry -> { if (receivedEntry == null || !Location.in(Location.DUNGEON_HUB)) return false; - Text text = receivedEntry.displayName(); + Component text = receivedEntry.displayName(); if (text == null) return false; String string = text.getString(); @@ -54,8 +53,8 @@ public class ChestCounter { Events.ON_RUN_END.register(() -> { countedChests++; if (Dungeons.sendChestWarning && chestDisplayCount + countedChests >= Dungeons.chestWarningCount) { - Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); - Misc.setTitle(Text.literal("§cChest count reached")); + Scheduler.scheduleSound(SoundEvents.NOTE_BLOCK_PLING.value(), 2, 1); + Misc.setTitle(Component.literal("§cChest count reached")); } return false; @@ -67,14 +66,14 @@ public class ChestCounter { return Dungeons.displayChestCount && Location.inDungeon(); } - public static void render(HUDComponent component, DrawContext context) { + public static void render(HUDComponent component, GuiGraphics context) { int x = component.getScaledX(); int y = component.getScaledY(); if (hasUpdatedData) { RenderUtils.drawPrefixedText(component, context, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); } else { - context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, Constants.RED, true); + context.drawString(Minecraft.getInstance().font, Component.literal("go to the dungeon hub"), x, y, Constants.RED, true); } } @@ -5,11 +5,10 @@ import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import net.minecraft.text.Text; - import java.text.DecimalFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.minecraft.network.chat.Component; public class ExplosiveShot { @@ -37,7 +36,7 @@ public class ExplosiveShot { double damagePerEntity = amountNum / countNum; - Misc.addChatMessage(Text.literal("§aExplosive shot did §e" + FORMAT.format(damagePerEntity) +"§a damage per enemy.")); + Misc.addChatMessage(Component.literal("§aExplosive shot did §e" + FORMAT.format(damagePerEntity) +"§a damage per enemy.")); } catch (NumberFormatException ignored) { } @@ -6,9 +6,9 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.player.Player; public class HidePlayers { @@ -38,25 +38,25 @@ public class HidePlayers { return true; } - public static boolean testHideAtSS(PlayerEntity player) { + public static boolean testHideAtSS(Player player) { if (!Dungeons.hideAtSS || !Phase.inBoss()) return false; if (Dungeons.hideBeforeTermsOnly && Phase.inP3()) return false; return DeviceNotifier.atSS(player); } - public static boolean testHideInRange(PlayerEntity player) { + public static boolean testHideInRange(Player player) { if (!Dungeons.hidePlayersInRange) return false; - ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; + LocalPlayer clientPlayer = Minecraft.getInstance().player; if (clientPlayer == null) return false; - double distance = player.getEntityPos().distanceTo(clientPlayer.getEntityPos()); + double distance = player.position().distanceTo(clientPlayer.position()); if (!Double.isFinite(distance) || !Double.isFinite(Dungeons.hidePlayerRange)) return false; return distance <= Dungeons.hidePlayerRange; } - public static boolean shouldHidePlayers(PlayerEntity player) { + public static boolean shouldHidePlayers(Player player) { if (!Location.inDungeon() || !EntityUtil.isARealPlayer(player) || EntityUtil.isClientPlayer(player)) return false; if (testHideAtLeap()) { @@ -6,24 +6,22 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.rendering.RenderingEvents; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.DrawStyle; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexRendering; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.ItemEntity; -import net.minecraft.text.Text; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.ColorHelper; -import net.minecraft.util.math.MathHelper; -import net.minecraft.world.debug.gizmo.GizmoDrawing; - +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.gizmos.GizmoStyle; +import net.minecraft.gizmos.Gizmos; +import net.minecraft.network.chat.Component; +import net.minecraft.util.ARGB; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.phys.AABB; import java.util.HashSet; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -37,10 +35,10 @@ public class ItemHighlight { public static void init() { ClientTickEvents.END_CLIENT_TICK.register(minecraftClient -> { - ClientWorld world = minecraftClient.world; + ClientLevel world = minecraftClient.level; if (world == null) return; - world.getEntities().forEach(entity -> { + world.entitiesForRendering().forEach(entity -> { if (entity instanceof ItemEntity item) { if (trackedItems.containsKey(item)) return; @@ -61,27 +59,27 @@ public class ItemHighlight { RenderingEvents.NO_DEPTH_FILLED.register(ItemHighlight::render); } - private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!Dungeons.highlightItems) return; - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + double tickProgress = Minecraft.getInstance().getDeltaTracker().getGameTimeDeltaPartialTick(false); trackedItems.forEach((itemEntity, integer) -> { - double x = MathHelper.lerp(tickProgress, itemEntity.lastRenderX, itemEntity.getX()); - double y = MathHelper.lerp(tickProgress, itemEntity.lastRenderY, itemEntity.getY()); - double z = MathHelper.lerp(tickProgress, itemEntity.lastRenderZ, itemEntity.getZ()); + double x = Mth.lerp(tickProgress, itemEntity.xOld, itemEntity.getX()); + double y = Mth.lerp(tickProgress, itemEntity.yOld, itemEntity.getY()); + double z = Mth.lerp(tickProgress, itemEntity.zOld, itemEntity.getZ()); EntityDimensions dimension = itemEntity.getDimensions(itemEntity.getPose()); - Box box = dimension.getBoxAt(x, y, z).expand(0.1).offset(0, 0.05, 0); + AABB box = dimension.makeBoundingBox(x, y, z).inflate(0.1).move(0, 0.05, 0); float[] color = RenderUtils.toFloats(getColor(itemEntity)); - GizmoDrawing.box(box, DrawStyle.filled(ColorHelper.fromFloats(color[3], color[0], color[1], color[2]))); + Gizmos.cuboid(box, GizmoStyle.fill(ARGB.colorFromFloat(color[3], color[0], color[1], color[2]))); }); } public static boolean highlightItem(ItemEntity item) { if (!Dungeons.highlightItems || !Location.inDungeon() || Phase.inBoss()) return false; - Text itemText = item.getStack().getName(); + Component itemText = item.getItem().getHoverName(); if (itemText == null) return false; String itemName = itemText.getString(); @@ -89,14 +87,14 @@ public class ItemHighlight { } public static int getColor(ItemEntity item) { - ClientPlayerEntity player = MinecraftClient.getInstance().player; + LocalPlayer player = Minecraft.getInstance().player; if (player == null) return 0; - double distance = item.getEntityPos().distanceTo(player.getEntityPos()); + double distance = item.position().distanceTo(player.position()); if (distance > 20) { return 0; } else if (distance > 3.5) { return Constants.RED; - } else if (item.age > 11){ + } else if (item.tickCount > 11){ return Constants.GREEN; } else { return Constants.GOLD; @@ -9,25 +9,24 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.ProfileComponent; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Text; - +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.ResolvableProfile; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public class KeyNotifier { - private final static Text BLOOD_KEY = Text.literal("§l§cBlood Key Dropped"); - private final static Text WITHER_KEY = Text.literal("§l§7Wither Key Dropped"); + private final static Component BLOOD_KEY = Component.literal("§l§cBlood Key Dropped"); + private final static Component WITHER_KEY = Component.literal("§l§7Wither Key Dropped"); //Thanks to mio for this key detection system private final static String WITHER_UUID = "2865274b-3097-394e-8149-ec629c72d850"; @@ -45,19 +44,19 @@ public class KeyNotifier { ClientTickEvents.END_WORLD_TICK.register((world) -> { if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier || Phase.inBoss()) return; - for (Entity entity : world.getEntities()) { - if (entity instanceof ArmorStandEntity armorStand && !foundKeys.contains(entity)) { - ItemStack head = armorStand.getEquippedStack(EquipmentSlot.HEAD); - ProfileComponent profile = head.get(DataComponentTypes.PROFILE); + for (Entity entity : world.entitiesForRendering()) { + if (entity instanceof ArmorStand armorStand && !foundKeys.contains(entity)) { + ItemStack head = armorStand.getItemBySlot(EquipmentSlot.HEAD); + ResolvableProfile profile = head.get(DataComponents.PROFILE); if (profile == null) continue; - String uuid = profile.getGameProfile().id().toString(); + String uuid = profile.partialProfile().id().toString(); if (uuid == null) continue; if (uuid.equals(WITHER_UUID)) { foundKeys.add(entity); hasKey = true; if (isValidClass()) { - Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + Scheduler.scheduleSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0.5f); } return; } @@ -68,7 +67,7 @@ public class KeyNotifier { hasKey = true; if (isValidClass()) { - Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + Scheduler.scheduleSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 2, 0.5f); } return; } @@ -114,11 +113,11 @@ public class KeyNotifier { return Location.inDungeon() && hasKey && isValidClass() && !Phase.inBoss(); } - public static void render(HUDComponent component, DrawContext context) { + public static void render(HUDComponent component, GuiGraphics context) { int x = component.getScaledX(); int y = component.getScaledY(); - Text text = isBloodKey ? BLOOD_KEY : WITHER_KEY; - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, text, x, y, component.getWidth(), 0xffffffff); + Component text = isBloodKey ? BLOOD_KEY : WITHER_KEY; + RenderUtils.drawCenteredText(context, Minecraft.getInstance().font, text, x, y, component.getWidth(), 0xffffffff); } } @@ -2,8 +2,8 @@ package blade.addon.features.dungeon; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; public class LeapMessage { @@ -13,9 +13,9 @@ public class LeapMessage { Events.ON_LEAP.register(message -> { if (!Dungeons.enableLeapMessages) return false; - ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); + ClientPacketListener networkHandler = Minecraft.getInstance().getConnection(); if (networkHandler == null) return false; - networkHandler.sendChatCommand("pc " + message.getString().substring(INDEX_REMOVAL)); + networkHandler.sendCommand("pc " + message.getString().substring(INDEX_REMOVAL)); return false; }); } @@ -3,16 +3,15 @@ package blade.addon.features.dungeon; import blade.addon.utils.debug.Debug; import blade.addon.utils.Misc; import blade.addon.utils.dungeon.DungeonClass; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.Team; -import net.minecraft.text.Text; - import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.scores.PlayerTeam; +import net.minecraft.world.scores.Scoreboard; public class LeapOrder { @@ -31,16 +30,16 @@ public class LeapOrder { HashMap<DungeonClass, String> classNameMap = new HashMap<>(); DungeonClass playersClass = null; - ClientPlayerEntity player = MinecraftClient.getInstance().player; - ClientWorld world = MinecraftClient.getInstance().world; + LocalPlayer player = Minecraft.getInstance().player; + ClientLevel world = Minecraft.getInstance().level; if (player == null || world == null) { Debug.LOGGER.warn("Player or World is null"); return; } Scoreboard scoreboard = world.getScoreboard(); - for (Team team : scoreboard.getTeams()) { - String teamStr = (team.getPrefix().getString() + team.getSuffix().getString()).replaceAll("§.", ""); + for (PlayerTeam team : scoreboard.getPlayerTeams()) { + String teamStr = (team.getPlayerPrefix().getString() + team.getPlayerSuffix().getString()).replaceAll("§.", ""); Matcher matcher = PATTERN.matcher(teamStr); if (matcher.find()) { DungeonClass dungeonClass = getClass(matcher.group(1)); @@ -61,7 +60,7 @@ public class LeapOrder { } if (classNameMap.size() != 4 || playersClass == null) { - Misc.addChatMessage(Text.literal("Cant find all players or the players class")); + Misc.addChatMessage(Component.literal("Cant find all players or the players class")); return; } DungeonClass[] order; @@ -78,7 +77,7 @@ public class LeapOrder { } String leapOrder = "odin leaporder " + classNameMap.get(order[0]) + " " + classNameMap.get(order[1]) + " " + classNameMap.get(order[2]) + " " + classNameMap.get(order[3]); - Misc.addChatMessage(Text.literal("Executing command: " + leapOrder)); + Misc.addChatMessage(Component.literal("Executing command: " + leapOrder)); Misc.executeCommand(leapOrder); } @@ -7,10 +7,10 @@ import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; public class QuizTimer { @@ -56,16 +56,16 @@ public class QuizTimer { return Dungeons.quizTimer && tick > 0; } - public static void render(HUDComponent component, DrawContext context) { - TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + public static void render(HUDComponent component, GuiGraphics context) { + Font textRenderer = Minecraft.getInstance().font; if (textRenderer == null) return; if (Dungeons.quizProgress) { - Text drawnText = Text.literal("Quiz " + "(").withColor(ExtraOptions.timerPrefixColor) - .append(Text.literal(stage + "/3").withColor(0xffffffff) - .append(Text.literal("): ").withColor(ExtraOptions.timerPrefixColor)) - .append(Text.literal(Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION) + "s").withColor(0xffffffff))); - context.drawText(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); + Component drawnText = Component.literal("Quiz " + "(").withColor(ExtraOptions.timerPrefixColor) + .append(Component.literal(stage + "/3").withColor(0xffffffff) + .append(Component.literal("): ").withColor(ExtraOptions.timerPrefixColor)) + .append(Component.literal(Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION) + "s").withColor(0xffffffff))); + context.drawString(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); } else { RenderUtils.drawPrefixedTimer(component, context, "Quiz", tick); } @@ -8,27 +8,26 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.Team; -import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Text; - import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.scores.PlayerTeam; +import net.minecraft.world.scores.Scoreboard; public class RunStartValidator { private static final Pattern STARTING_PATTERN = Pattern.compile("^Starting in \\d second(s)?"); private static final Pattern CLASS_PATTERN = Pattern.compile("\\[([ABHMT])]"); - private static final Text DUPE_CLASS_TEXT = Text.literal("§cDuplicate Class Detected"); - private static final Text PLAYER_COUNT_TEXT = Text.literal("§cNot enough players"); + private static final Component DUPE_CLASS_TEXT = Component.literal("§cDuplicate Class Detected"); + private static final Component PLAYER_COUNT_TEXT = Component.literal("§cNot enough players"); private static boolean hasDupeClasses = false; private static boolean notEnoughPlayers = false; @@ -44,7 +43,7 @@ public class RunStartValidator { hasTicked = true; if (validate()) { - Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); + Scheduler.scheduleSound(SoundEvents.NOTE_BLOCK_PLING.value(), 2, 1); } return false; }); @@ -69,8 +68,8 @@ public class RunStartValidator { } private static boolean validate() { - ClientWorld world = MinecraftClient.getInstance().world; - ClientPlayerEntity player = MinecraftClient.getInstance().player; + ClientLevel world = Minecraft.getInstance().level; + LocalPlayer player = Minecraft.getInstance().player; if (world == null || player == null) return false; Scoreboard scoreboard = world.getScoreboard(); @@ -118,8 +117,8 @@ public class RunStartValidator { private static HashMap<String, Integer> readScoreBoard(Scoreboard scoreboard) { HashMap<String, Integer> map = new HashMap<>(); - for (Team team : scoreboard.getTeams()) { - String teamStr = team.getPrefix().getString() + team.getSuffix().getString(); + for (PlayerTeam team : scoreboard.getPlayerTeams()) { + String teamStr = team.getPlayerPrefix().getString() + team.getPlayerSuffix().getString(); Matcher matcher = CLASS_PATTERN.matcher(teamStr); if (!matcher.find()) continue; @@ -135,13 +134,13 @@ public class RunStartValidator { return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers); } - public static void render(HUDComponent component, DrawContext context) { + public static void render(HUDComponent component, GuiGraphics context) { if (hasDupeClasses) { RenderUtils.drawCenteredText(context, component, DUPE_CLASS_TEXT); } else if (notEnoughPlayers) { RenderUtils.drawCenteredText(context, component, PLAYER_COUNT_TEXT); } else { - RenderUtils.drawCenteredText(context, component, Text.literal("§cSome warning text")); + RenderUtils.drawCenteredText(context, component, Component.literal("§cSome warning text")); } } } @@ -7,12 +7,11 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; - import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; public class SecretSpawnTimer { @@ -42,13 +41,13 @@ public class SecretSpawnTimer { return Location.inDungeon() && Dungeons.enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(); } - public static void render(HUDComponent component, DrawContext context) { + public static void render(HUDComponent component, GuiGraphics context) { int x = component.getScaledX(); int y = component.getScaledY(); int color = tick > 10 ? Constants.GREEN : tick > 5 ? Constants.GOLD : Constants.RED; - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(tick + ""), x, y, component.getWidth(), color); + RenderUtils.drawCenteredText(context, Minecraft.getInstance().font, Component.literal(tick + ""), x, y, component.getWidth(), color); } } @@ -4,10 +4,9 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.DrawContext; - import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.minecraft.client.gui.GuiGraphics; public class WarpCooldown { @@ -43,7 +42,7 @@ public class WarpCooldown { } } - public static void render(HUDComponent component, DrawContext context) { + public static void render(HUDComponent component, GuiGraphics context) { double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); RenderUtils.drawPrefixedTimer(component, context, "Warp Cooldown", timeRemaining); } @@ -13,18 +13,17 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; @@ -66,12 +65,12 @@ public class BossWaypoints { public static void setPlace(boolean shouldPlace) { place = shouldPlace; - Misc.addChatMessage(Text.literal("Edit mode: ").append(Misc.getStatusText(place))); + Misc.addChatMessage(Component.literal("Edit mode: ").append(Misc.getStatusText(place))); } public static void setIgnoreBoss(boolean shouldIgnoreBoss) { ignoreBoss = shouldIgnoreBoss; - Misc.addChatMessage(Text.literal("Ignore boss: ").append(Misc.getStatusText(ignoreBoss))); + Misc.addChatMessage(Component.literal("Ignore boss: ").append(Misc.getStatusText(ignoreBoss))); } public static void togglePlace() { @@ -116,9 +115,9 @@ public class BossWaypoints { save(); } - private static ActionResult onBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) { - if (!isInValidArea() || !EntityUtil.isClientPlayer(playerEntity)) return ActionResult.PASS; - if (hand == Hand.OFF_HAND) return ActionResult.PASS; + private static InteractionResult onBlock(Player playerEntity, Level world, InteractionHand hand, BlockHitResult blockHitResult) { + if (!isInValidArea() || !EntityUtil.isClientPlayer(playerEntity)) return InteractionResult.PASS; + if (hand == InteractionHand.OFF_HAND) return InteractionResult.PASS; BlockPos pos = blockHitResult.getBlockPos(); @@ -126,7 +125,7 @@ public class BossWaypoints { int y = pos.getY(); int z = pos.getZ(); - if (!place) return ActionResult.PASS; + if (!place) return InteractionResult.PASS; Waypoint waypoint = getWaypoint(x, y, z); if (waypoint == null) { @@ -136,10 +135,10 @@ public class BossWaypoints { } save(); - return ActionResult.PASS; + return InteractionResult.PASS; } - private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + private static void render(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; waypoints.forEach(waypoint -> { @@ -149,7 +148,7 @@ public class BossWaypoints { }); } - private static void renderThroughWall(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + private static void renderThroughWall(WorldRenderContext context, PoseStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; waypoints.forEach(waypoint -> { @@ -7,8 +7,8 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.times.PersonalBests; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.text.Text; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; public class PredevTimer { @@ -33,7 +33,7 @@ public class PredevTimer { ClientTickEvents.END_CLIENT_TICK.register(client -> { if (!shouldTrack || at3rdDev || (!Floor7.predevForAll && !DungeonClass.isClass(DungeonClass.HEALER))) return; - ClientPlayerEntity player = client.player; + LocalPlayer player = client.player; if (player == null) return; if (Misc.getDistance(player.getX(), player.getZ(), 1, 77) <= 3) { at3rdDev = true; @@ -42,7 +42,7 @@ public class PredevTimer { Events.ON_LEAP.register(message -> { if (at3rdDev && shouldTrack && (DungeonClass.isClass(DungeonClass.HEALER) || Floor7.predevForAll)) { - PersonalBests.predevTime.testNewTime(Text.literal("§aPredev completed in "), bossEnterTime); + PersonalBests.predevTime.testNewTime(Component.literal("§aPredev completed in "), bossEnterTime); at3rdDev = false; shouldTrack = false; } @@ -12,45 +12,43 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.rendering.RenderingEvents; import blade.addon.utils.times.PersonalBests; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.DrawStyle; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexRendering; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.ColorHelper; -import net.minecraft.world.debug.gizmo.GizmoDrawing; - +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.core.BlockPos; +import net.minecraft.gizmos.GizmoStyle; +import net.minecraft.gizmos.Gizmos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.ARGB; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.BlockHitResult; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RelicTimer { public enum Relic { - GREEN(new Box(49, 7, 44, 50, 8, 45), 0xff55ff55, "§cRed"), - RED(new Box(51, 7, 42, 52, 8, 43), 0xffff5555, "§aGreen"), - PURPLE(new Box(54, 7, 41, 55, 8, 42), 0xffff55ff, "§5Purple"), - ORANGE(new Box(57, 7, 42, 58, 8, 43), 0xffffaa00, "§6Orange"), - BLUE(new Box(59, 7, 44, 60, 8, 45), 0xff55ffff, "§bBlue"); + GREEN(new AABB(49, 7, 44, 50, 8, 45), 0xff55ff55, "§cRed"), + RED(new AABB(51, 7, 42, 52, 8, 43), 0xffff5555, "§aGreen"), + PURPLE(new AABB(54, 7, 41, 55, 8, 42), 0xffff55ff, "§5Purple"), + ORANGE(new AABB(57, 7, 42, 58, 8, 43), 0xffffaa00, "§6Orange"), + BLUE(new AABB(59, 7, 44, 60, 8, 45), 0xff55ffff, "§bBlue"); - final Box box; + final AABB box; final int color; final String name; int placedTick = 0; - Relic(Box box, int color, String name) { + Relic(AABB box, int color, String name) { this.box = box; this.color = color; this.name = name; @@ -117,7 +115,7 @@ public class RelicTimer { if (EntityUtil.isClientPlayer(name)) { pickedupRelic = Relic.valueOf(relicString.toUpperCase()); - Debug.sendDebugMessage(Text.literal("Picked up relic " + relicString)); + Debug.sendDebugMessage(Component.literal("Picked up relic " + relicString)); } } @@ -127,15 +125,15 @@ public class RelicTimer { ClientTickEvents.END_WORLD_TICK.register(world -> { if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes || sentRelicTimes) return; - Iterable<Entity> entities = world.getEntities(); + Iterable<Entity> entities = world.entitiesForRendering(); for (Entity entity : entities) { - if (entity instanceof ArmorStandEntity armorStand) { - ItemStack item = armorStand.getWeaponStack(); + if (entity instanceof ArmorStand armorStand) { + ItemStack item = armorStand.getWeaponItem(); String id = ItemUtil.getId(item); if (id == null || !id.contains("RELIC")) continue; - Debug.sendDebugMessage(Text.literal("item id is " + id)); + Debug.sendDebugMessage(Component.literal("item id is " + id)); double ax = armorStand.getX(); double az = armorStand.getZ(); @@ -143,7 +141,7 @@ public class RelicTimer { for (Relic relic : Relic.values()) { if (relic.placedTick != 0 && Misc.getDistance(relic.box.maxX, relic.box.maxZ, ax, az) < 1.5) { relic.placedTick = placeTick; - Debug.sendDebugMessage(Text.literal("Set" + relic.name + " time to " + relic.placedTick + ", item id is " + id)); + Debug.sendDebugMessage(Component.literal("Set" + relic.name + " time to " + relic.placedTick + ", item id is " + id)); } } } @@ -151,7 +149,7 @@ public class RelicTimer { if (allRelicsPlaced()) { for (Relic relic : Relic.values()) { - Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + TextUtil.formatTicks(relic.placedTick) + "s&a.")); + Misc.addChatMessage(Component.literal(relic.name + " &aRelic placed in &e" + TextUtil.formatTicks(relic.placedTick) + "s&a.")); sentRelicTimes = true; } } @@ -175,8 +173,8 @@ public class RelicTimer { //skyblock menu check is there incase the item doesnt get updated if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu")) { if (Floor7.blockIncorrectRelicPlace) { - Debug.sendDebugMessage(Text.literal("Name: " + itemStack.getName() + " Item: " + itemStack)); - Misc.addChatMessage(Text.literal("Blocked a weird click")); + Debug.sendDebugMessage(Component.literal("Name: " + itemStack.getHoverName() + " Item: " + itemStack)); + Misc.addChatMessage(Component.literal("Blocked a weird click")); return true; } else { return false; @@ -185,9 +183,9 @@ public class RelicTimer { if (clickedRelic(pickedupRelic, pos)) { if (Floor7.enableRelicPlaceTime) { - MutableText text = Text.literal("The ").formatted(Formatting.GREEN) - .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) - .append(" relic was placed in ").formatted(Formatting.GREEN); + MutableComponent text = Component.literal("The …… diff 过长已截断 …… |
- readded copy chat查看变更src/main/java/blade/addon/mixin/ChatHudAccessor.java | 26 ++++++++++++++++++++ src/main/java/blade/addon/mixin/ChatScreenMixin.java | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/resources/blade-addons.mixins.json | 2 ++ 3 files changed, 162 insertions(+) @@ -0,0 +1,26 @@ +package blade.addon.mixin; + +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(ChatHud.class) +public interface ChatHudAccessor { + + @Accessor("visibleMessages") + List<ChatHudLine.Visible> getVisibleMessages(); + + @Accessor("scrolledLines") + int getScrolledLines(); + + @Invoker("getWidth") + int width(); + + @Invoker("getChatScale") + double getScale(); + +} @@ -0,0 +1,134 @@ +package blade.addon.mixin; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.TextUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Click; +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.text.Text; +import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(ChatScreen.class) +public class ChatScreenMixin { + + @Inject(method = "mouseClicked", at = @At("HEAD")) + private void click(Click click, boolean doubled, CallbackInfoReturnable<Boolean> cir) { + + if (!ExtraOptions.copyChat || click.button() != GLFW.GLFW_MOUSE_BUTTON_RIGHT) return; + + MinecraftClient mc = MinecraftClient.getInstance(); + ChatHud chatHud = mc.inGameHud.getChatHud(); + ChatHudAccessor hudAccessor = (ChatHudAccessor) chatHud; + if (chatHud == null) return; + + if (hudAccessor.width() + 4 < click.x()) return; + + final int n = (int) (9 * (mc.options.getChatLineSpacing().getValue() + 1.0)); + int index = (int) (MathHelper.floor((mc.getWindow().getScaledHeight() - 40) / hudAccessor.getScale()) - click.y()) / n + hudAccessor.getScrolledLines(); + + List<ChatHudLine.Visible> messages = hudAccessor.getVisibleMessages(); + if (index < 0 || index >= messages.size()) return; + + String string; + if (ExtraOptions.copyLineOnly) { + ChatHudLine.Visible msg = messages.get(index); + string = TextUtil.orderedTextToString(msg.content()); + } else { + string = copyChat(messages, index); + } + + if (string == null) return; + + if (ExtraOptions.removeColorCodes) { + string = string.replaceAll("§.", ""); + } + + if (ExtraOptions.replaceColorChars) { + string = string.replace("§", "&"); + } + + mc.keyboard.setClipboard(string); + + if (ExtraOptions.copyChatFeedback) { + Misc.addChatMessage(Text.literal("Copied chat message")); + } + + } + + @Unique + private static String copyChat(List<ChatHudLine.Visible> messages, int index) { + int endIndex = index; + + if (messages == null || endIndex < 0 || endIndex >= messages.size()) return null; + + int startIndex = endIndex; + + + //edge case where the index is end of entry + //but there are lines above that needs to be included + ChatHudLine.Visible currentLine = messages.get(endIndex); + if (endIndex + 1 < messages.size() && currentLine.endOfEntry() && !messages.get(startIndex + 1).endOfEntry()) { + endIndex++; + } + + + //find start of msg + for (int i = endIndex; i >= 0; i--) { + ChatHudLine.Visible chatHudLine = messages.get(i); + if (chatHudLine.endOfEntry()) { + startIndex = i; + break; + } + } + + if (!messages.get(endIndex).endOfEntry()) { + //find end of msg + for (int i = endIndex + 1; i < messages.size(); i++) { + ChatHudLine.Visible chatHudLine = messages.get(i); + if (chatHudLine.endOfEntry()) { + endIndex = i - 1; + break; + } + } + } + StringBuilder builder = new StringBuilder(); + for (int i = endIndex; i >= startIndex; i--) { + ChatHudLine.Visible chatHudLine = messages.get(i); + TextUtil.acceptOrderedText(builder, chatHudLine.content()); + } + return builder.toString(); + } + + + //final int l = 9; + //double d = this.client.options.getChatLineSpacing().getValue(); + //final int k = MathHelper.floor((windowHeight - 40) / f); + //final int n = (int)(l * (d + 1.0)); + //int lx = k - y * n; + //float f = (float)this.getChatScale(); + + // + // + //MATH PART + //mx <= click.y <= lx + //lx + y * n = k + //(k - lx) / n = y = forEachVisibleLine.k + //lineIndex = forEachVisibleLine.l = forEachVisibleLine.k + this.scrolledLines + +} + + + + + @@ -22,6 +22,8 @@ }, "client": [ "BossBarHudMixin", + "ChatHudAccessor", + "ChatScreenMixin", "ClientPlayerEntityMixin", "ClientPlayNetworkHandlerMixin", "DrawContextMixin", |
forgot to push these查看变更src/main/java/blade/addon/features/highlight/BatHighlight.java | 4 ++-- src/main/java/blade/addon/features/highlight/MimicHighlight.java | 4 ++-- src/main/java/blade/addon/features/highlight/MobHighlight.java | 4 ++-- src/main/java/blade/addon/features/highlight/SheepHighlight.java | 4 ++-- src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 2 +- src/main/java/blade/addon/features/highlight/WitherHighlight.java | 4 ++-- src/main/java/blade/addon/features/other/PracticeSS.java | 14 +++++++------- src/main/java/blade/addon/features/other/StunWaypoint.java | 62 -------------------------------------------------------------- 8 files changed, 18 insertions(+), 80 deletions(-) @@ -48,14 +48,14 @@ public class BatHighlight { if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.batFilledColor); - bats.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); + bats.forEach(entity -> RenderUtils.renderFilled(EntityUtil.getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.batOutlineColor); - bats.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); + bats.forEach(entity -> RenderUtils.renderOutline(EntityUtil.getBox(entity), rgba)); } } @@ -46,13 +46,13 @@ public class MimicHighlight { if (!MobHighlight.highlightMimicChests || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicFilledColor); - mimics.forEach(mimic -> RenderUtils.renderFilled(matrixStack, consumer, box.offset(mimic.getPos()), rgba)); + mimics.forEach(mimic -> RenderUtils.renderFilled(box.offset(mimic.getPos()), rgba)); } private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.highlightMimicChests || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); - mimics.forEach(mimic -> RenderUtils.renderOutline(matrixStack, consumer, box.offset(mimic.getPos()), rgba)); + mimics.forEach(mimic -> RenderUtils.renderOutline(box.offset(mimic.getPos()), rgba)); } } @@ -315,7 +315,7 @@ public class MobHighlight { int filledColor = getFilledColor(type); float[] rgba = RenderUtils.toFloats(filledColor); - RenderUtils.renderFilled(matrixStack, consumer, box, rgba); + RenderUtils.renderFilled(box, rgba); } } @@ -333,7 +333,7 @@ public class MobHighlight { int outlineColor = getOutlineColor(type); float[] rgba = RenderUtils.toFloats(outlineColor); - RenderUtils.renderOutline(matrixStack, consumer, box, rgba); + RenderUtils.renderOutline(box, rgba); } } } @@ -42,14 +42,14 @@ public class SheepHighlight { if (!MobHighlight.highlightSheep || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); - sheeps.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); + sheeps.forEach(entity -> RenderUtils.renderFilled(EntityUtil.getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.highlightSheep || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); - sheeps.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); + sheeps.forEach(entity -> RenderUtils.renderOutline(EntityUtil.getBox(entity), rgba)); } } @@ -58,7 +58,7 @@ public class TeammateHighlight { if (Dungeons.highlightTeammates) { float[] rgba = RenderUtils.toFloats(color); - RenderUtils.renderOutline(matrixStack, consumer, EntityUtil.getBox(player), rgba); + RenderUtils.renderOutline(EntityUtil.getBox(player), rgba); } if (Dungeons.renderClassName) { @@ -56,14 +56,14 @@ public class WitherHighlight { if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled() || MobHighlight.dontRenderHighlight) return; float[] rgba = RenderUtils.toFloats(MobHighlight.witherFilledColor); - withers.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, getBox(entity), rgba)); + withers.forEach(entity -> RenderUtils.renderFilled(getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline() || MobHighlight.dontRenderHighlight) return; float[] rgba = RenderUtils.toFloats(MobHighlight.witherOutlineColor); - withers.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, getBox(entity), rgba)); + withers.forEach(entity -> RenderUtils.renderOutline(getBox(entity), rgba)); } } @@ -353,15 +353,15 @@ public class PracticeSS { if (showingPattern) { if (!ExtraOptions.realisticDelay || totalTicks - ticksLeft > START_WAIT_DURATION || endIndex != 2) { int lastIndex = getLastDisplayIndex(); - renderButtons(matrixStack, consumer, 0, lastIndex); - renderBackground(matrixStack, consumer, lastIndex - 1); + renderButtons(0, lastIndex); + renderBackground(lastIndex - 1); } } else { - renderButtons(matrixStack, consumer, currentIndex, endIndex); + renderButtons(currentIndex, endIndex); } } - private static void renderButtons(MatrixStack matrixStack, VertexConsumer consumer, int start, int end) { + private static void renderButtons(int start, int end) { Box directionBox = getBox(direction); if (directionBox == null) return; @@ -370,7 +370,7 @@ public class PracticeSS { BlockPos pos = buttons.get(i); Box box = directionBox.offset(pos.getX(), pos.getY(), pos.getZ()); float[] color = RenderUtils.toFloats(getColor(i)); - RenderUtils.renderFilled(matrixStack, consumer, box, color); + RenderUtils.renderFilled(box, color); } } @@ -384,7 +384,7 @@ public class PracticeSS { }; } - private static void renderBackground(MatrixStack matrixStack, VertexConsumer consumer, int backgroundIndex) { + private static void renderBackground(int backgroundIndex) { if (buttons.size() > backgroundIndex && backgroundIndex >= 0) { Box box = Box.of(buttons.get(backgroundIndex).toCenterPos(), 1, 1, 1); int dx, dz; @@ -409,7 +409,7 @@ public class PracticeSS { return; } } - RenderUtils.renderFilled(matrixStack, consumer, box.offset(dx, 0, dz), new float[]{0, 0.5f, 1, 1}); + RenderUtils.renderFilled(box.offset(dx, 0, dz), new float[]{0, 0.5f, 1, 1}); } } } @@ -1,62 +0,0 @@ -package blade.addon.features.other; - -import blade.addon.utils.Location; -import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import blade.addon.utils.rendering.RenderingEvents; -import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; - -public class StunWaypoint { - - private static final Box BLOCK = new Box(-168, 27, -169, -167, 28, -168); - - private static boolean inBelly = false; - private static boolean inP3 = false; - - public static void init() { - - Events.ON_GAME_MESSAGE.register(text -> { - if (!Location.in(Location.KUUDRA) || !ExtraOptions.stunWaypoint) return false; - String string = text.getString(); - - if (string.equals("[NPC] Elle: Phew! The Ballista is finally ready! It should be strong enough to tank Kuudra's blows now!")) { - inP3 = true; - return false; - } - - if (string.equals("[NPC] Elle: POW! SURELY THAT'S IT! I don't think he has any more in him!")) { - reset(); - return false; - } - - return false; - }); - - Events.ON_PACKET.register(packet -> { - if (!Location.in(Location.KUUDRA) || !ExtraOptions.stunWaypoint) return false; - - if (packet instanceof PlayerPositionLookS2CPacket posPacket) { - Vec3d pos = posPacket.change().position(); - if (pos.x == -161 && pos.y == 49 && pos.z == -186) { - inBelly = true; - } - - } - return false; - }); - - RenderingEvents.NO_DEPTH_OUTLINE_ENTITY.register((context, matrixStack, consumer) -> { - if (!inP3 || !inBelly || !Location.in(Location.KUUDRA) || !ExtraOptions.stunWaypoint) return; - RenderUtils.renderOutline(matrixStack, consumer, BLOCK, new float[]{0, 1, 1, 1}); - }); - } - - - private static void reset() { - inBelly = false; - inP3 = false; - } -} |
- fixed renderLineTo(tracer) not working correctly - refactored some rendering methods to use the new rendering methods - removed "StunWaypoint.java", not needed as it was never tested or accessible and all kuudra mods have already ported anyway查看变更src/main/java/blade/addon/Bladeaddons.java | 47 +++++------------------------------------------ src/main/java/blade/addon/features/dungeon/f7/dragons/DragonTracer.java | 2 +- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 20 ++++++++------------ 3 files changed, 14 insertions(+), 55 deletions(-) @@ -1,17 +1,6 @@ package blade.addon; -import blade.addon.features.dungeon.AutoRequeue; -import blade.addon.features.dungeon.BloodNotifier; -import blade.addon.features.dungeon.ChestCounter; -import blade.addon.features.dungeon.ExplosiveShot; -import blade.addon.features.dungeon.HidePlayers; -import blade.addon.features.dungeon.ItemHighlight; -import blade.addon.features.dungeon.KeyNotifier; -import blade.addon.features.dungeon.LeapMessage; -import blade.addon.features.dungeon.QuizTimer; -import blade.addon.features.dungeon.RunStartValidator; -import blade.addon.features.dungeon.SecretSpawnTimer; -import blade.addon.features.dungeon.WarpCooldown; +import blade.addon.features.dungeon.*; import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; @@ -29,37 +18,12 @@ import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; import blade.addon.features.dungeon.f7.storm.DistanceToLedge; import blade.addon.features.dungeon.f7.storm.PillarExplode; import blade.addon.features.dungeon.f7.storm.StormTickTimer; -import blade.addon.features.dungeon.f7.terms.CurrentSection; -import blade.addon.features.dungeon.f7.terms.DeviceNotifier; -import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; -import blade.addon.features.dungeon.f7.terms.LeapNotification; -import blade.addon.features.dungeon.f7.terms.MelodyWarning; -import blade.addon.features.dungeon.f7.terms.SectionCompletion; -import blade.addon.features.dungeon.f7.terms.SectionProgress; -import blade.addon.features.dungeon.f7.terms.TermStartTimer; +import blade.addon.features.dungeon.f7.terms.*; import blade.addon.features.filter.Filters; -import blade.addon.features.highlight.BatHighlight; -import blade.addon.features.highlight.MimicHighlight; -import blade.addon.features.highlight.MobHighlight; -import blade.addon.features.highlight.SheepHighlight; -import blade.addon.features.highlight.TeammateHighlight; -import blade.addon.features.highlight.WitherHighlight; -import blade.addon.features.item.DropAnimation; -import blade.addon.features.item.ItemRarityHighlight; -import blade.addon.features.item.ProtectItem; -import blade.addon.features.item.SelectedPetHighlight; -import blade.addon.features.item.StarCountHighlight; +import blade.addon.features.highlight.*; +import blade.addon.features.item.*; import blade.addon.features.notifications.Notifications; -import blade.addon.features.other.ArrowSwapper; -import blade.addon.features.other.CompactHoppity; -import blade.addon.features.other.DianaNotifier; -import blade.addon.features.other.KickedTimer; -import blade.addon.features.other.PracticeSS; -import blade.addon.features.other.RagDisplay; -import blade.addon.features.other.ReaperDisplay; -import blade.addon.features.other.SearchBar; -import blade.addon.features.other.SelectedPet; -import blade.addon.features.other.StunWaypoint; +import blade.addon.features.other.*; import blade.addon.features.sound.BonzoSound; import blade.addon.features.sound.TubaSound; import blade.addon.utils.Commands; @@ -152,7 +116,6 @@ public class Bladeaddons implements ModInitializer { ArrowSwapper.init(); StarCountHighlight.init(); MaskHighlight.init(); - StunWaypoint.init(); ItemRarityHighlight.init(); ProtectItem.init(); SelectedPetHighlight.init(); @@ -19,6 +19,6 @@ public class DragonTracer { Dragon dragon = DragSpawnTimer.currentDragon; if (dragon == null || dragon == Dragon.NONE || !DragSpawnTimer.hasDoneSplit) return; - RenderUtils.renderLineTo(context, matrixStack, consumer, dragon.spawnPos, dragon.color); + RenderUtils.renderLineTo(context, dragon.spawnPos, dragon.color); } } @@ -11,7 +11,6 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.DrawStyle; -import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.math.Box; @@ -89,13 +88,13 @@ public class RenderUtils { context.drawText(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); } - public static void renderFilled(MatrixStack matrixStack, VertexConsumer consumer, Box box, float[] rgba) { + public static void renderFilled(Box box, float[] rgba) { if (rgba[3] == 0) return; GizmoDrawing.box(box, DrawStyle.filled(ColorHelper.fromFloats(rgba[3], rgba[0], rgba[1], rgba[2]))); // Could be filledAndStroked //VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); } - public static void renderOutline(MatrixStack matrixStack, VertexConsumer consumer, Box box, float[] rgba) { + public static void renderOutline(Box box, float[] rgba) { if (rgba[3] == 0) return; GizmoDrawing.box(box, DrawStyle.stroked(ColorHelper.fromFloats(rgba[3], rgba[0], rgba[1], rgba[2]))); // Could be filledAndStroked //VertexRendering.drawBox(matrixStack.peek(), consumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); @@ -123,22 +122,19 @@ public class RenderUtils { renderText(context, matrices, text, pos.x, pos.y, pos.z, scale); } - public static void renderLineTo(WorldRenderContext context, MatrixStack matrices, VertexConsumer consumer, double x, double y, double z, int color) { + public static void renderLineTo(WorldRenderContext context, double x, double y, double z, int color) { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player == null) return; Vec3d playerPos = EntityUtil.getLerpedPos(player); double eyeHeight = player.getStandingEyeHeight(); - Vector3f lookat = new Vector3f(0, 0, -1f).rotate(context.worldState().cameraRenderState.orientation); - Vec3d startPos = playerPos.add(0, eyeHeight, 0).add(lookat.x, lookat.y + eyeHeight, lookat.z); - Vec3d endPos = new Vec3d(x, y, z).subtract(playerPos).subtract(lookat.x, lookat.y + eyeHeight, lookat.z); - - //VertexRendering.drawVector(matrices, consumer, startPos, endPos, color); - GizmoDrawing.line(startPos, endPos, color); + Vector3f lookAt = new Vector3f(0, 0, -1f).rotate(context.worldState().cameraRenderState.orientation); + Vec3d startPos = playerPos.add(0, eyeHeight, 0).add(lookAt.x, lookAt.y, lookAt.z); + GizmoDrawing.line(startPos, new Vec3d(x, y, z), color); } - public static void renderLineTo(WorldRenderContext context, MatrixStack matrices, VertexConsumer consumer, Vec3d pos, int color) { - renderLineTo(context, matrices, consumer, pos.x, pos.y, pos.z, color); + public static void renderLineTo(WorldRenderContext context, Vec3d pos, int color) { + renderLineTo(context, pos.x, pos.y, pos.z, color); } public static String formatNumber(float num) { |
- should actually launch on 1.21.11 now - fixed heldItemRenderer - possibly fixed tracers - copy chat still missing查看变更build.gradle | 2 +- gradle.properties | 4 ++-- src/main/java/blade/addon/features/other/SwingAnimation.java | 15 ++++++++++++- src/main/java/blade/addon/mixin/ChatHudInvoker.java | 25 ---------------------- src/main/java/blade/addon/mixin/ChatScreenMixin.java | 103 ----------------------------------------------------------------------------------------- src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 27 +++++++++++++----------- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 12 +++++------ src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 2 ++ src/main/resources/blade-addons.mixins.json | 2 -- 9 files changed, 40 insertions(+), 152 deletions(-) @@ -69,7 +69,7 @@ dependencies { include modImplementation("net.hypixel:mod-api:${project.hypixel_api_version}") include modImplementation("com.github.BladeMasterGabe:practical-config:${project.practical_config}") - modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:1.2.1") + modRuntimeOnly("me.djtheredstoner:DevAuth-fabric:1.2.2") } @@ -13,7 +13,7 @@ loader_version=0.18.4 loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=2.3.6 +mod_version=2.4.0 maven_group=blade.addon archives_base_name=blade-addons @@ -21,5 +21,5 @@ archives_base_name=blade-addons fabric_version=0.141.3+1.21.11 # I love dependencies sometimes breaking practical_config=1.4.3 -modmenu_version = 16.0.0-rc.2 +modmenu_version = 17.0.0-beta.2 hypixel_api_version = 1.0.1 @@ -1,5 +1,8 @@ package blade.addon.features.other; +import blade.addon.features.item.DropAnimation; +import net.minecraft.item.ItemStack; + public class SwingAnimation { private static int ignoreCount = 0; @@ -17,14 +20,24 @@ public class SwingAnimation { public static void consumeSwing() { if (ignoreCount > 0) { ignoreCount--; + System.out.println("Consumed a swing, now at count: " + ignoreCount); } } /** * Checks if it should ignore the swing + * * @return true if it should ignore the swing animation, else false */ public static boolean shouldIgnore() { - return ignoreCount > 0; + if (ignoreCount > 0) { + return true; + } + + if (DropAnimation.shouldProceed()) { + ItemStack prevDropped = DropAnimation.getPrevDroppedItem(); + return prevDropped != null; + } + return false; } } @@ -1,25 +0,0 @@ -package blade.addon.mixin; - -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.client.gui.hud.ChatHudLine; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - -import java.util.List; - -@Mixin(ChatHud.class) -public interface ChatHudInvoker { - - @Invoker("toChatLineY") - double lineY(double y); - - @Invoker("toChatLineX") - double lineX(double X); - - @Invoker("getMessageLineIndex") - int getLineIndex(double chatLineX, double chatLineY); - - @Accessor("visibleMessages") - List<ChatHudLine.Visible> getVisibleMessages(); -} @@ -1,103 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.utils.Misc; -import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.data.TextUtil; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Click; -import net.minecraft.client.gui.hud.ChatHudLine; -import net.minecraft.client.gui.screen.ChatScreen; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; - -@Mixin(ChatScreen.class) -public class ChatScreenMixin extends Screen { - - protected ChatScreenMixin(Text title) { - super(title); - } - - @Inject(method = "mouseClicked", at = @At("HEAD")) - private static void mouseClicked(Click click, boolean doubled, CallbackInfoReturnable<Boolean> cir) { - if (!ExtraOptions.copyChat || click.button() != GLFW.GLFW_MOUSE_BUTTON_RIGHT) return; - - MinecraftClient mc = MinecraftClient.getInstance(); - ChatHudInvoker hudInvoker = (ChatHudInvoker) mc.inGameHud.getChatHud(); - if (hudInvoker == null) return; - - double x = hudInvoker.lineX(click.x()); - double y = hudInvoker.lineY(click.y()); - - String string; - if (ExtraOptions.copyLineOnly) { - int index = hudInvoker.getLineIndex(x, y); - List<ChatHudLine.Visible> visibleMessages = hudInvoker.getVisibleMessages(); - if (visibleMessages == null || index < 0 || index >= visibleMessages.size()) return; - - ChatHudLine.Visible msg = visibleMessages.get(index); - string = TextUtil.orderedTextToString(msg.content()); - } else { - string = copyChat(hudInvoker, x, y); - } - - if (string == null) return; - - if (ExtraOptions.removeColorCodes) { - string = string.replaceAll("§.", ""); - } - - if (ExtraOptions.replaceColorChars) { - string = string.replaceAll("§", "&"); - } - - mc.keyboard.setClipboard(string); - - if (ExtraOptions.copyChatFeedback) { - Misc.addChatMessage(Text.literal("Copied chat message")); - } - } - - @Unique - private static String copyChat(ChatHudInvoker hudInvoker, double x, double y) { - List<ChatHudLine.Visible> messages = hudInvoker.getVisibleMessages(); - int endIndex = hudInvoker.getLineIndex(x, y); - - if (messages == null || endIndex < 0 || endIndex >= messages.size()) return null; - - int startIndex = endIndex; - - //find start of msg - for (int i = endIndex; i >= 0; i--) { - ChatHudLine.Visible chatHudLine = messages.get(i); - if (chatHudLine.endOfEntry()) { - startIndex = i; - break; - } - } - - if (!messages.get(endIndex).endOfEntry()) { - //find end of msg - for (int i = endIndex + 1; i < messages.size(); i++) { - ChatHudLine.Visible chatHudLine = messages.get(i); - if (chatHudLine.endOfEntry()) { - endIndex = i - 1; - break; - } - } - } - StringBuilder builder = new StringBuilder(); - for (int i = endIndex; i >= startIndex; i--) { - ChatHudLine.Visible chatHudLine = messages.get(i); - TextUtil.acceptOrderedText(builder, chatHudLine.content()); - } - return builder.toString(); - } -} @@ -9,6 +9,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.Arm; +import net.minecraft.util.math.MathHelper; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -53,19 +54,21 @@ public abstract class HeldItemRendererMixin { this.equipProgressMainHand = 1; } - @Inject(method = "swingArm", at = @At("HEAD"), cancellable = true) - private void stopSwing(float swingProgress, float equipProgress, MatrixStack matrices, int armX, Arm arm, CallbackInfo ci) { - - //TODO: refactor this - if (!SwingAnimation.shouldIgnore()) { - if (!DropAnimation.shouldProceed()) return; - ItemStack prevDropped = DropAnimation.getPrevDroppedItem(); - if (prevDropped == null) return; - } - + @Inject(method = "applyEquipOffset", at = @At("HEAD"), cancellable = true) + private void applyEquipOffset(MatrixStack matrices, Arm arm, float swingProgress, CallbackInfo ci) { + if (!SwingAnimation.shouldIgnore()) return; + int side = arm == Arm.RIGHT ? 1 : -1; + matrices.translate((float) side * 0.56F, -0.52F, -0.72F); + ci.cancel(); + } - int i = arm == Arm.RIGHT ? 1 : -1; - matrices.translate((float) i * 0.56F, -0.52F, -0.72F); + @Inject(method = "swingArm", at = @At("HEAD"), cancellable = true) + private void swingArm(float swingProgress, MatrixStack matrixStack, int i, Arm arm, CallbackInfo ci) { + if (!SwingAnimation.shouldIgnore()) return; + float f = -0.4F * MathHelper.sin(MathHelper.sqrt(1) * (float) Math.PI); + float g = 0.2F * MathHelper.sin(MathHelper.sqrt(1) * (float) (Math.PI * 2)); + float h = -0.2F * MathHelper.sin(1 * (float) Math.PI); + matrixStack.translate(i * f, g, h); ci.cancel(); } } @@ -12,13 +12,13 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.DrawStyle; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.math.Box; import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.debug.gizmo.GizmoDrawing; +import org.joml.Vector3f; public class RenderUtils { @@ -130,10 +130,11 @@ public class RenderUtils { Vec3d playerPos = EntityUtil.getLerpedPos(player); double eyeHeight = player.getStandingEyeHeight(); Vector3f lookat = new Vector3f(0, 0, -1f).rotate(context.worldState().cameraRenderState.orientation); - - Vector3f startPos = playerPos.toVector3f().add(0f, (float)eyeHeight, 0f).add(lookat); + Vec3d startPos = playerPos.add(0, eyeHeight, 0).add(lookat.x, lookat.y + eyeHeight, lookat.z); Vec3d endPos = new Vec3d(x, y, z).subtract(playerPos).subtract(lookat.x, lookat.y + eyeHeight, lookat.z); - VertexRendering.drawVector(matrices, consumer, startPos, endPos, color); + + //VertexRendering.drawVector(matrices, consumer, startPos, endPos, color); + GizmoDrawing.line(startPos, endPos, color); } public static void renderLineTo(WorldRenderContext context, MatrixStack matrices, VertexConsumer consumer, Vec3d pos, int color) { @@ -145,12 +146,11 @@ public class RenderUtils { if (num >= 1e9) return String.format("%.1fB", num / 1e9); if (num >= 1e6) return String.format("%.1fM", num / 1e6); if (num >= 1e3) return String.format("%.1fK", num / 1e3); - return num + ""; } else { if (num >= 1e9) return String.format("%.1fb", num / 1e9); if (num >= 1e6) return String.format("%.1fm", num / 1e6); if (num >= 1e3) return String.format("%.1fk", num / 1e3); + } return num + ""; } - } } @@ -116,6 +116,8 @@ public class RenderingEvents { } private static void debugLine(WorldRenderContext context) { + WorldRenderState worldState = context.worldState(); + if (worldState == null) return; Vec3d camera = context.worldState().cameraRenderState.pos; MatrixStack matrices = context.matrices(); if (matrices == null) return; @@ -22,8 +22,6 @@ }, "client": [ "BossBarHudMixin", - "ChatHudInvoker", - "ChatScreenMixin", "ClientPlayerEntityMixin", "ClientPlayNetworkHandlerMixin", "DrawContextMixin", |
| Merge pull request #4 from SteinGaming/new refactor: incomplete 1.21.11 implementation 查看变更gradle.properties | 8 ++++---- gradlew | 0 src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 5 ++++- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 5 ++++- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 7 +++++-- src/main/java/blade/addon/mixin/HandledScreenMixin.java | 4 ++-- src/main/java/blade/addon/mixin/StatusEffectsDisplayMixin.java | 11 ++++++++--- src/main/java/blade/addon/utils/Waypoint.java | 6 +++++- src/main/java/blade/addon/utils/rendering/RenderLayers.java | 37 ++++++++++++++----------------------- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 10 +++++++--- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 21 ++++++++++++++++----- 11 files changed, 69 insertions(+), 45 deletions(-) |
Merge branch 'new' into new查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 4 ++++ src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 10 +++++----- src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 9 +++++---- src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/dragons/Dragon.java | 17 ++++++++++------- src/main/java/blade/addon/features/dungeon/f7/dragons/DragonTracer.java | 24 ++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 6 +++--- src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 49 ++++++++++++++++++++++++++++++++----------------- src/main/java/blade/addon/features/filter/Filters.java | 2 +- src/main/java/blade/addon/features/item/ItemRarity.java | 22 +++++++++++----------- src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 12 +++++++++++- src/main/java/blade/addon/features/other/ReaperDisplay.java | 40 ++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/SearchBar.java | 14 ++++++++++---- src/main/java/blade/addon/features/other/SelectedPet.java | 8 ++++---- src/main/java/blade/addon/features/other/SwingAnimation.java | 30 ++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/EnderPearlItemMixin.java | 24 ++++++++++++++++++++++++ src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 15 +++++++++++---- src/main/java/blade/addon/mixin/LivingEntityMixin.java | 23 +++++++++++++++++++++++ src/main/java/blade/addon/mixin/ShovelItemMixin.java | 23 +++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 17 ++++++++++++++--- src/main/java/blade/addon/utils/config/components/Components.java | 4 ++++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 6 ++++++ src/main/java/blade/addon/utils/config/values/Floor7.java | 9 +++++++++ src/main/java/blade/addon/utils/config/values/Visual.java | 9 +++++++++ src/main/java/blade/addon/utils/rendering/RenderUtils.java | 20 +++++++++++++++++++- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 19 +++++++++++++++++++ src/main/resources/assets/blade-addons/textures/gui/sprites/pets/witch.png | Bin 0 -> 3768 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/rarity-background-circle.png | Bin 0 -> 570 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/rarity-background.png | Bin 0 -> 374 bytes src/main/resources/blade-addons.mixins.json | 3 +++ src/main/resources/fabric.mod.json | 4 ++-- 33 files changed, 363 insertions(+), 74 deletions(-) |
- fixed leap notifications breaking weirdly查看变更src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) @@ -58,11 +58,12 @@ public class LeapNotification { currentSpot = getSpot(player); if (currentSpot < 1) { count = 0; + inBounds = false; return; + } else { + inBounds = true; } - inBounds = currentSpot > 1; - Box box = REGIONS[currentSpot - 1]; count = getCount(world, player, box); }); @@ -97,7 +98,7 @@ public class LeapNotification { } public static boolean display() { - return Floor7.leapNotifications && inBounds; + return Floor7.leapNotifications && inBounds && Phase.inBoss() && Location.inDungeon(); } public static void render(HUDComponent component, DrawContext context) { |
| - added a disable all chat filters toggle - updated pregenerated stuff like contacts 查看变更src/main/java/blade/addon/features/filter/Filters.java | 2 +- src/main/java/blade/addon/utils/config/Config.java | 5 +++-- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 +++ src/main/resources/assets/blade-addons/textures/gui/sprites/pets/witch.png | Bin 0 -> 3768 bytes src/main/resources/fabric.mod.json | 4 ++-- 5 files changed, 9 insertions(+), 5 deletions(-) @@ -23,7 +23,7 @@ public class Filters { public static void init() { filterManager.load(); ClientReceiveMessageEvents.ALLOW_GAME.register((message, overlay) -> { - if (overlay) return true; + if (overlay || ExtraOptions.disableAllFilters) return true; String string = message.getString(); if (ExtraOptions.ignoreColorCodesFilter) { @@ -69,6 +69,7 @@ public class Config { ConfigSection chatFilter = new ConfigSection(Text.literal("Chat filter")); chatFilter.add(new ConfigButton(Text.literal("Edit"), () -> MinecraftClient.getInstance().setScreen(new FilterList()))); chatFilter.add(new ConfigBool(Text.literal("Ignore color codes"), () -> ExtraOptions.ignoreColorCodesFilter, bool -> ExtraOptions.ignoreColorCodesFilter = bool)); + chatFilter.add(new ConfigBool(Text.literal("Disable all filters"), () -> ExtraOptions.disableAllFilters, bool -> ExtraOptions.disableAllFilters = bool)); general.add(chatFilter); return general; } @@ -200,7 +201,7 @@ public class Config { goldor.add(new ConfigBool(Text.literal("Melody warning notification"), () -> Floor7.notifiyMelody, bool -> Floor7.notifiyMelody = bool)); goldor.add(new ConfigBool(Text.literal("Send terminal time stamps"), () -> Floor7.terminalTimeStamps, bool -> Floor7.terminalTimeStamps = bool)); goldor.add(new ConfigBool(Text.literal("Section completion notification"), () -> Floor7.sectionCompletionNotification, bool -> Floor7.sectionCompletionNotification = bool)); - goldor.add(new ConfigSound(Text.literal("Section complete sound"), Floor7.sectionChangeSound, 2, 2, true)); + goldor.add(new ConfigSound(Text.literal("Section complete sound"), Floor7.sectionChangeSound)); goldor.add(new ConfigBool(Text.literal("Current section display"), () -> Floor7.showCurrentSection, bool -> Floor7.showCurrentSection = bool)); floor7.add(goldor); @@ -221,7 +222,7 @@ public class Config { locationNotifier.add(new ConfigBool(Text.literal("Display Location messages on screen"), () -> Floor7.displayLocationNotification, bool -> Floor7.displayLocationNotification = bool)); locationNotifier.add(new ConfigBool(Text.literal("Hide your own notifications"), () -> Floor7.dontNotifiyForYourself, bool -> Floor7.dontNotifiyForYourself = bool)); locationNotifier.add(new ConfigInt(Text.literal("Display duration (in client ticks)"), () -> Floor7.notificationDuration, num -> Floor7.notificationDuration = num, 1, 1, 20)); - locationNotifier.add(new ConfigSound(Text.literal("Notification sound"), Floor7.atLocationSound, 2, 2, false)); + locationNotifier.add(new ConfigSound(Text.literal("Notification sound"), Floor7.atLocationSound, 4, 2, false)); locationNotifier.add(new ConfigInt(Text.literal("Sound repetitions"), () -> Floor7.notificationRepetitions, num -> Floor7.notificationRepetitions = num, 1, 0, 20)); locationNotifier.add(new ConfigButton(Text.literal("Test notification"), () -> LocationNotifier.startNotification("Someone", " At <location>!!"))); @@ -138,4 +138,7 @@ public class ExtraOptions { @ConfigValue public static boolean enableReaperDisplay = false; + + @ConfigValue + public static boolean disableAllFilters = false; } @@ -8,8 +8,8 @@ "BladeMasterGabe" ], "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" + "homepage": "https://modrinth.com/mod/blade-addons", + "sources": "https://github.com/BladeMasterGabe/blade-addons" }, "license": "CC0-1.0", "icon": "assets/blade-addons/icon.png", |
- fixed player leap count assuming only 3 players for its color yet still saying "x/4" - added assume core and split ee2 for leap player count查看变更src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 52 +++++++++++++++++++++++++++++++++------------------- src/main/java/blade/addon/utils/config/Config.java | 7 ++++++- src/main/java/blade/addon/utils/config/values/Floor7.java | 6 ++++++ 3 files changed, 45 insertions(+), 20 deletions(-) @@ -24,21 +24,24 @@ import java.util.List; public class LeapNotification { private static final Box[] REGIONS = { - new Box(90, 106, 50, 111, 145, 123), + new Box(91, 105, 46, 111, 127, 123), new Box(17, 106, 121, 108, 145, 143), new Box(-2, 106, 51, 20, 145, 142), new Box(-1, 26, 29, 191, 145, 58), new Box(3, 5, 0, 128, 48, 140) }; + private static final Box RED_PILLAR_BOX = Box.of(new Vec3d(100, 116, 46), 2, 2, 2); + private static final Box SS_BOX = new Box(107, 119, 92, 108, 121, 95); private static final Box EE2_BOX = new Box(57, 108, 130, 59, 110, 132); private static final Box HEE2_BOX = new Box(59, 132, 138, 62, 133, 140); private static final Box EE3_BOX = new Box(1, 108, 103, 3, 110, 105); private static final Box CORE_BOX = new Box(53.5, 114, 49.5, 55.5, 116, 51.5); private static final Box RELIC_BOX = new Box(51.5, 3, 73.5, 57.5, 8, 79.5); + private static int count = 0; - private static int currentSpot = 0; + private static int currentSpot = -1; private static boolean inBounds = false; public static void init() { @@ -53,24 +56,28 @@ public class LeapNotification { if (player == null || world == null) return; currentSpot = getSpot(player); - if (currentSpot < 2) { + if (currentSpot < 1) { count = 0; - inBounds = false; return; - } else { - inBounds = true; } + + inBounds = currentSpot > 1; + Box box = REGIONS[currentSpot - 1]; - List<Entity> entities = world.getOtherEntities(player, box); - int currentCount = 0; - for (Entity entity : entities) { - if (EntityUtil.isARealPlayer(entity)) { - currentCount++; - } + count = getCount(world, player, box); + }); + } + + private static int getCount(ClientWorld world, ClientPlayerEntity player, Box box) { + List<Entity> entities = world.getOtherEntities(player, box); + int currentCount = 0; + for (Entity entity : entities) { + if (EntityUtil.isARealPlayer(entity)) { + currentCount++; } + } - count = currentCount; - }); + return currentCount; } private static int getSpot(ClientPlayerEntity player) { @@ -80,7 +87,13 @@ public class LeapNotification { else if (EE3_BOX.contains(pos)) return 3; else if (CORE_BOX.contains(pos)) return 4; else if (RELIC_BOX.contains(pos) && !Phase.inP5()) return 5; - else return 0; + else return -1; + } + + private static int getMaxCount() { + if (currentSpot == 2 && Floor7.assumeSplitEE2) return 3; + if (currentSpot == 3 && Floor7.assumeCore) return 3; + return 4; } public static boolean display() { @@ -88,10 +101,11 @@ public class LeapNotification { } public static void render(HUDComponent component, DrawContext context) { - String start; - if (currentSpot == 3) start = (count > 2 ? "§9" : "§4"); - else start = (count > 3 ? "§9" : "§4"); + int maxCount = getMaxCount(); + + String startFormat; + startFormat = (maxCount - count <= 1? "§9" : "§4"); - RenderUtils.drawCenteredText(context, component, Text.literal(start + count + "§9/4 Players Leaped")); + RenderUtils.drawCenteredText(context, component, Text.literal(startFormat + count + "§9/" + maxCount + " Players Leaped")); } } @@ -151,9 +151,14 @@ public class Config { private static ConfigCategory floor7() { ConfigCategory floor7 = new ConfigCategory("Floor 7"); floor7.add(new ConfigBool(Text.literal("Combine tick timers"), () -> Floor7.combineTickTimers, bool -> Floor7.combineTickTimers = bool)); - floor7.add(new ConfigBool(Text.literal("Enable player leap count"), () -> Floor7.leapNotifications, bool -> Floor7.leapNotifications = bool)); floor7.add(new ConfigBool(Text.literal("Capitalize health numbers"), () -> Floor7.capitalizeHealthNumbers, bool -> Floor7.capitalizeHealthNumbers = bool)); + ConfigSection leapCount = new ConfigSection(Text.literal("Leap count")); + leapCount.add(new ConfigBool(Text.literal("Enable player leap count"), () -> Floor7.leapNotifications, bool -> Floor7.leapNotifications = bool)); + leapCount.add(new ConfigBool(Text.literal("Assume core (max 3 on ee3)"), () -> Floor7.assumeCore, bool -> Floor7.assumeCore = bool)); + leapCount.add(new ConfigBool(Text.literal("Assume split ee2 (max 3 on ee2)"), () -> Floor7.assumeSplitEE2, bool -> Floor7.assumeSplitEE2 = bool)); + floor7.add(leapCount); + ConfigSection waypoints = new ConfigSection(Text.literal("Waypoints")); waypoints.add(new ConfigBool(Text.literal("Enable boss waypoints"), () -> Floor7.enableBossWaypoints, bool -> Floor7.enableBossWaypoints = bool)); waypoints.add(new ConfigBool(Text.literal("Enable placing waypoints"), BossWaypoints::getPlace, BossWaypoints::setPlace)); @@ -177,4 +177,10 @@ public class Floor7 { @ConfigValue public static boolean dragonTracer = false; + + @ConfigValue + public static boolean assumeCore = true; + + @ConfigValue + public static boolean assumeSplitEE2 = false; } |
- added reaper duration display - fixed orange drag tracer being wrong查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/dungeon/f7/dragons/Dragon.java | 10 +++++----- src/main/java/blade/addon/features/other/ReaperDisplay.java | 40 ++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 1 + src/main/java/blade/addon/utils/config/components/Components.java | 4 ++++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 +++ 6 files changed, 55 insertions(+), 5 deletions(-) @@ -56,6 +56,7 @@ import blade.addon.features.other.DianaNotifier; import blade.addon.features.other.KickedTimer; import blade.addon.features.other.PracticeSS; import blade.addon.features.other.RagDisplay; +import blade.addon.features.other.ReaperDisplay; import blade.addon.features.other.SearchBar; import blade.addon.features.other.SelectedPet; import blade.addon.features.other.StunWaypoint; @@ -162,5 +163,6 @@ public class Bladeaddons implements ModInitializer { BloodNotifier.init(); CurrentSection.init(); DragonTracer.init(); + ReaperDisplay.init(); } } \ No newline at end of file @@ -4,11 +4,11 @@ import blade.addon.utils.dungeon.DungeonClass; import net.minecraft.util.math.Vec3d; public enum Dragon { - PURPLE(0xffff55ff, 0, 4, new Vec3d(56, 14, 125)), - BLUE(0xff55ffff, 1, 3, new Vec3d(84, 14, 94)), - RED(0xffff5555, 2, 2, new Vec3d (27, 14, 59)), - GREEN(0xff55ff55, 3, 1, new Vec3d(27, 14, 94)), - ORANGE(0xffffaa00, 4, 0, new Vec3d(84, 14, 94)), + PURPLE(0xffff55ff, 0, 4, new Vec3d(56.5, 14, 125.5)), + BLUE(0xff55ffff, 1, 3, new Vec3d(84.5, 14, 94.5)), + RED(0xffff5555, 2, 2, new Vec3d (27.5, 14, 59.5)), + GREEN(0xff55ff55, 3, 1, new Vec3d(27.5, 14, 94.5)), + ORANGE(0xffffaa00, 4, 0, new Vec3d(84.5, 14, 56.5)), NONE(0xffffffff, 99, 99, new Vec3d(0, 0, 0)); final int color; @@ -0,0 +1,40 @@ +package blade.addon.features.other; + +import blade.addon.utils.Constants; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.sound.SoundEvents; + +public class ReaperDisplay { + + private static final int TOTAL_TICKS = 20 * 6; + + private static int tick = 0; + + public static void init() { + Events.ON_SOUND.register((soundEvent, volume, pitch) -> { + if (!ExtraOptions.enableReaperDisplay) return false; + if (soundEvent != SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE) return false; + if (volume != 0.5 && pitch != 1.0) return false; + + tick = TOTAL_TICKS; + return false; + }); + + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + return false; + }); + } + + public static boolean display() { + return tick > 0; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawTimer(component, context, tick, Constants.RED); + } +} @@ -319,6 +319,7 @@ public class Config { extra.add(new ConfigBool(Text.literal("Title on arrow swap"), () -> ExtraOptions.arrowSwapNotification, bool -> ExtraOptions.arrowSwapNotification = bool)); extra.add(new ConfigBool(Text.literal("Toggleable searchbar (ctrl + f)"), () -> ExtraOptions.toggleableSearchBar, bool -> ExtraOptions.toggleableSearchBar = bool)); extra.add(new ConfigBool(Text.literal("Disable protect item (resets on launch)"), () -> ProtectItem.stopProtectItem, bool -> ProtectItem.stopProtectItem = bool)); + extra.add(new ConfigBool(Text.literal("Display reaper duration"), () -> ExtraOptions.enableReaperDisplay, bool -> ExtraOptions.enableReaperDisplay = bool)); //extra.add(new ConfigBool(Text.literal("Kuudra stun waypoint"), () -> ExtraOptions.stunWaypoint, bool -> ExtraOptions.stunWaypoint = bool)); @@ -30,6 +30,7 @@ import blade.addon.features.item.HeldItemToolTip; import blade.addon.features.other.ArrowSwapper; import blade.addon.features.other.KickedTimer; import blade.addon.features.other.RagDisplay; +import blade.addon.features.other.ReaperDisplay; import blade.addon.features.other.SelectedPet; import blade.addon.features.notifications.Notifications; import blade.addon.utils.config.values.Dungeons; @@ -165,4 +166,7 @@ public class Components { @ConfigValue public static HUDComponent currentSectionDisplay = new HUDComponent(0, 0, 50, 10, 1, "Current section", CurrentSection::display, CurrentSection::render, () -> Floor7.showCurrentSection); + + @ConfigValue + public static HUDComponent reaperDisplay = new HUDComponent(0, 0, TICK_TIMER_WIDTH, 10, 1, "reaper display", ReaperDisplay::display, ReaperDisplay::render, () -> ExtraOptions.enableReaperDisplay); } @@ -135,4 +135,7 @@ public class ExtraOptions { @ConfigValue public static boolean ignoreColorCodesNotification = false; + + @ConfigValue + public static boolean enableReaperDisplay = false; } |
- added circular rarity background - added dragon tracers (needs testing) - fixed some features not working if you filter out their detection msgs - bumped version查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 10 +++++----- src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 8 ++++---- src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 9 +++++---- src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 4 ++-- src/main/java/blade/addon/features/dungeon/f7/dragons/Dragon.java | 17 ++++++++++------- src/main/java/blade/addon/features/dungeon/f7/dragons/DragonTracer.java | 24 ++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 6 +++--- src/main/java/blade/addon/features/item/ItemRarity.java | 22 +++++++++++----------- src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 12 +++++++++++- src/main/java/blade/addon/features/other/SelectedPet.java | 8 ++++---- src/main/java/blade/addon/utils/config/Config.java | 2 ++ src/main/java/blade/addon/utils/config/values/Floor7.java | 3 +++ src/main/java/blade/addon/utils/config/values/Visual.java | 3 +++ src/main/java/blade/addon/utils/rendering/RenderUtils.java | 21 ++++++++++++++++++++- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 19 +++++++++++++++++++ src/main/resources/assets/blade-addons/textures/gui/sprites/rarity-background-circle.png | Bin 0 -> 570 bytes src/main/resources/assets/blade-addons/textures/gui/sprites/rarity-background.png | Bin 0 -> 374 bytes 19 files changed, 129 insertions(+), 43 deletions(-) @@ -13,7 +13,7 @@ loader_version=0.18.4 loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=2.3.5 +mod_version=2.3.6 maven_group=blade.addon archives_base_name=blade-addons @@ -17,6 +17,7 @@ import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; import blade.addon.features.dungeon.f7.dragons.DragonHealth; +import blade.addon.features.dungeon.f7.dragons.DragonTracer; import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.invincibility.MaskHighlight; @@ -160,5 +161,6 @@ public class Bladeaddons implements ModInitializer { MaxorTickTimer.init(); BloodNotifier.init(); CurrentSection.init(); + DragonTracer.init(); } } \ No newline at end of file @@ -4,7 +4,7 @@ import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import blade.addon.utils.events.Events; import net.minecraft.text.Text; import java.text.DecimalFormat; @@ -19,9 +19,9 @@ public class ExplosiveShot { public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !Dungeons.calculateCriticalHit) return; - if (Dungeons.onlyInBoss && !Phase.inBoss()) return; + Events.ON_GAME_MESSAGE.register(message -> { + if (!Location.inDungeon() || !Dungeons.calculateCriticalHit) return false; + if (Dungeons.onlyInBoss && !Phase.inBoss()) return false; String string = message.getString(); @@ -42,7 +42,7 @@ public class ExplosiveShot { } catch (NumberFormatException ignored) { } } - + return false; }); } @@ -8,7 +8,6 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; @@ -37,16 +36,17 @@ public class RunStartValidator { private static boolean hasTicked = false; public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return; + Events.ON_GAME_MESSAGE.register(message -> { + if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return false; Matcher matcher = STARTING_PATTERN.matcher(message.getString()); - if (!matcher.find()) return; + if (!matcher.find()) return false; hasTicked = true; if (validate()) { Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); } + return false; }); Events.ON_LOCATION_CHANGE.register(location -> { @@ -1,9 +1,9 @@ package blade.addon.features.dungeon; import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.gui.DrawContext; import java.util.regex.Matcher; @@ -18,16 +18,17 @@ public class WarpCooldown { private static boolean displayCooldown = false; public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Dungeons.enableWarpCooldown) return; + Events.ON_GAME_MESSAGE.register(message -> { + if (!Dungeons.enableWarpCooldown) return false; - if ((endTime - System.currentTimeMillis()) > 0) return; + if ((endTime - System.currentTimeMillis()) > 0) return false; Matcher matcher = PATTERN.matcher(message.getString()); if (matcher.find()) { endTime = System.currentTimeMillis() + WARP_COOLDOWN_MS; displayCooldown = true; } + return false; }); } @@ -31,8 +31,8 @@ public class DragSpawnTimer { private static final int SPAWN_DURATION = 100; - private static Dragon currentDragon = Dragon.NONE; - private static boolean hasDoneSplit = false; + static Dragon currentDragon = Dragon.NONE; + static boolean hasDoneSplit = false; private static int tick = 0; public static void init() { @@ -1,23 +1,26 @@ package blade.addon.features.dungeon.f7.dragons; import blade.addon.utils.dungeon.DungeonClass; +import net.minecraft.util.math.Vec3d; public enum Dragon { - PURPLE(0xffff55ff, 0, 4), - BLUE(0xff55ffff, 1, 3), - RED(0xffff5555, 2, 2), - GREEN(0xff55ff55, 3, 1), - ORANGE(0xffffaa00, 4, 0), - NONE(0xffffffff, 99, 99); + PURPLE(0xffff55ff, 0, 4, new Vec3d(56, 14, 125)), + BLUE(0xff55ffff, 1, 3, new Vec3d(84, 14, 94)), + RED(0xffff5555, 2, 2, new Vec3d (27, 14, 59)), + GREEN(0xff55ff55, 3, 1, new Vec3d(27, 14, 94)), + ORANGE(0xffffaa00, 4, 0, new Vec3d(84, 14, 94)), + NONE(0xffffffff, 99, 99, new Vec3d(0, 0, 0)); final int color; final int archPrio; final int bersPrio; + final Vec3d spawnPos; - Dragon(int color, int archPrio, int bersPrio) { + Dragon(int color, int archPrio, int bersPrio, Vec3d spawnPos) { this.color = color; this.archPrio = archPrio; this.bersPrio = bersPrio; + this.spawnPos = spawnPos; } //checks are from valley addons @@ -0,0 +1,24 @@ +package blade.addon.features.dungeon.f7.dragons; + +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.util.math.MatrixStack; + +public class DragonTracer { + + public static void init() { + RenderingEvents.LINE.register(DragonTracer::render); + } + + private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!Floor7.dragonTracer) return; + + Dragon dragon = DragSpawnTimer.currentDragon; + if (dragon == null || dragon == Dragon.NONE || !DragSpawnTimer.hasDoneSplit) return; + + RenderUtils.renderLineTo(context, matrixStack, consumer, dragon.spawnPos, dragon.color); + } +} @@ -8,7 +8,6 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; @@ -79,10 +78,11 @@ public class InvincibilityTimer { Events.ON_PET.register(name -> phoenixOn = name.equals("Phoenix")); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + Events.ON_GAME_MESSAGE.register(text -> { if (Location.inDungeon()) { - parseMessage(message); + parseMessage(text); } + return false; }); } @@ -2,17 +2,17 @@ package blade.addon.features.item; public enum ItemRarity { NONE(0x0), - COMMON(0x99dddddd), - UNCOMMON(0x8842ab42), - RARE(0x884c4cd0), - EPIC(0x88671067), - LEGENDARY(0x88cf8d0a), - MYTHIC(0x88ff55ff), - DIVINE(0x884fe4e4), - SPECIAL(0x88ff5555), - VERY_SPECIAL(0x88c44747), - ULTIMATE(0x88a10202), - ADMIN(0x88aa0000); + COMMON(0xffdddddd), + UNCOMMON(0xff42ab42), + RARE(0xff4c4cd0), + EPIC(0xff671067), + LEGENDARY(0xffcf8d0a), + MYTHIC(0xffff55ff), + DIVINE(0xff4fe4e4), + SPECIAL(0xffff5555), + VERY_SPECIAL(0xffc44747), + ULTIMATE(0xffa10202), + ADMIN(0xffaa0000); private final int color; @@ -1,17 +1,23 @@ package blade.addon.features.item; +import blade.addon.utils.Constants; import blade.addon.utils.config.values.Visual; import blade.addon.utils.rendering.DrawEvents; +import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; import java.util.List; public class ItemRarityHighlight { + private static final Identifier NORMAL_BACKGROUND = Identifier.of(Constants.NAMESPACE, "rarity-background"); + private static final Identifier CIRCLE_BACKGROUND = Identifier.of(Constants.NAMESPACE, "rarity-background-circle"); + public static void init() { DrawEvents.INVENTORY_SLOT_BEFORE.register(ItemRarityHighlight::draw); DrawEvents.HUD_SLOT_BEFORE.register(ItemRarityHighlight::draw); @@ -30,7 +36,11 @@ public class ItemRarityHighlight { if (!holder.blade_addons$hasItemRarity()) return; ItemRarity rarity = holder.blade_addons$getItemRarity(); - context.fill(x, y, x + 16, y + 16, rarity.getColor()); + if (Visual.circularRarityBackground) { + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, CIRCLE_BACKGROUND, x, y, 16, 16, rarity.getColor()); + } else { + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, NORMAL_BACKGROUND, x, y, 16, 16, rarity.getColor()); + } } public static ItemRarity getRarity(ItemStack item) { @@ -8,7 +8,6 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gl.RenderPipelines; @@ -43,20 +42,20 @@ public class SelectedPet { private static int tick = 0; public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + Events.ON_GAME_MESSAGE.register(message -> { String string = message.getString(); Matcher matcher = MANUAL_EQUIP_PET_PATTERN.matcher(string); if (matcher.find()) { if (matcher.group(1).equals("despawned")) { despawnPet(); - return; + return false; } String name = matcher.group(2).replace(" ✦", ""); Style style = getStyle(message, name); summonPet(name, Text.literal(name).setStyle(style), getLevel(string), false); - return; + return false; } String unformattedLine = string.replaceAll("§.", ""); @@ -72,6 +71,7 @@ public class SelectedPet { summonPet(name, Text.literal(textName), getLevel(unformattedLine), true); } + return false; }); Events.ON_PLAYER_ENTRY.register(receivedEntry -> { @@ -238,6 +238,7 @@ public class Config { dragon.add(new ConfigBool(Text.literal("Send sound on dragon spawn"), () -> Floor7.sendSoundOnDragSpawn, bool -> Floor7.sendSoundOnDragSpawn = bool)); dragon.add(new ConfigOptions<>(Text.literal("Healer prio"), DragSpawnTimer.Team.values(), () -> Floor7.healerTeam, team -> Floor7.healerTeam = team)); dragon.add(new ConfigBool(Text.literal("Render dragon health"), () -> Floor7.dragonHealth, bool -> Floor7.dragonHealth = bool)); + dragon.add(new ConfigBool(Text.literal("Render dragon spawn tracer"), () -> Floor7.dragonTracer, bool -> Floor7.dragonTracer = bool)); floor7.add(dragon); return floor7; @@ -386,6 +387,7 @@ public class Config { visual.add(new ConfigBool(Text.literal("Hide arrows stuck to entities"), () -> Visual.hideStuckArrows, bool -> Visual.hideStuckArrows = bool)); visual.add(new ConfigBool(Text.literal("Hide dead entities"), () -> Visual.hideDeadEntities, bool -> Visual.hideDeadEntities = bool)); visual.add(new ConfigBool(Text.literal("Item rarity background"), () -> Visual.itemRarityBackground, bool -> Visual.itemRarityBackground = bool)); + visual.add(new ConfigBool(Text.literal("Circular rarity background"), () -> Visual.circularRarityBackground, bool -> Visual.circularRarityBackground = bool)); visual.add(new ConfigBool(Text.literal("Hide potion effects overlay"), () -> Visual.hideStatusOverLay, bool -> Visual.hideStatusOverLay = bool)); visual.add(new ConfigBool(Text.literal("Disable glowing"), () -> Visual.disableGlowing, bool -> Visual.disableGlowing = bool)); visual.add(new ConfigBool(Text.literal("Draw item starCount"), () -> Visual.drawStarCount, bool -> Visual.drawStarCount = bool)); @@ -174,4 +174,7 @@ public class Floor7 { @ConfigValue public static boolean sectionPrevObjective = false; + + @ConfigValue + public static boolean dragonTracer = false; } @@ -52,4 +52,7 @@ public class Visual { @ConfigValue public static boolean stopPearlSwing = false; + @ConfigValue + public static boolean circularRarityBackground = false; + } @@ -3,6 +3,7 @@ package blade.addon.utils.rendering; import blade.addon.utils.Constants; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; @@ -15,6 +16,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; +import org.joml.Vector3f; public class RenderUtils { @@ -117,7 +119,24 @@ public class RenderUtils { renderText(context, matrices, text, pos.x, pos.y, pos.z, scale); } - public static String formatNumber(float num) { + public static void renderLineTo(WorldRenderContext context, MatrixStack matrices, VertexConsumer consumer, double x, double y, double z, int color) { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return; + + Vec3d playerPos = EntityUtil.getLerpedPos(player); + double eyeHeight = player.getStandingEyeHeight(); + Vector3f lookat = new Vector3f(0, 0, -1f).rotate(context.worldState().cameraRenderState.orientation); + + Vector3f startPos = playerPos.toVector3f().add(0f, (float)eyeHeight, 0f).add(lookat); + Vec3d endPos = new Vec3d(x, y, z).subtract(playerPos).subtract(lookat.x, lookat.y + eyeHeight, lookat.z); + VertexRendering.drawVector(matrices, consumer, startPos, endPos, color); + } + + public static void renderLineTo(WorldRenderContext context, MatrixStack matrices, VertexConsumer consumer, Vec3d pos, int color) { + renderLineTo(context, matrices, consumer, pos.x, pos.y, pos.z, color); + } + + public static String formatNumber(float num) { if (Floor7.capitalizeHealthNumbers) { if (num >= 1e9) return String.format("%.1fB", num / 1e9); if (num >= 1e6) return String.format("%.1fM", num / 1e6); @@ -15,6 +15,8 @@ public class RenderingEvents { public static RenderHandler FILLED_ENTITY = new RenderHandler(); public static RenderHandler OUTLINE_ENTITY = new RenderHandler(); public static RenderHandler NO_DEPTH_OUTLINE_ENTITY = new RenderHandler(); + public static RenderHandler LINE = new RenderHandler(); + public static void init() { WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::filled); @@ -22,6 +24,8 @@ public class RenderingEvents { WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityFilled); WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityOutline); WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityOutlineNoDepth); + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::debugLine); + } private static void filled(WorldRenderContext context) { @@ -100,4 +104,19 @@ public class RenderingEvents { matrices.pop(); } + private static void debugLine(WorldRenderContext context) { + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer consumer = consumers.getBuffer(RenderLayers.getOutline(4, true)); + + LINE.invoke(renderingEvent -> renderingEvent.render(context, matrices, consumer)); + matrices.pop(); + } + } |
- added press enter to set it as the inputed string - added stop swinging when shovel flattening (clicking on dirt with like aotv) - added stop swinging when throwing a pearl查看变更src/main/java/blade/addon/features/other/SearchBar.java | 14 ++++++++++---- src/main/java/blade/addon/features/other/SwingAnimation.java | 30 ++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/EnderPearlItemMixin.java | 24 ++++++++++++++++++++++++ src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 13 ++++++++++--- src/main/java/blade/addon/mixin/LivingEntityMixin.java | 23 +++++++++++++++++++++++ src/main/java/blade/addon/mixin/ShovelItemMixin.java | 23 +++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 2 ++ src/main/java/blade/addon/utils/config/values/Visual.java | 6 ++++++ src/main/resources/blade-addons.mixins.json | 3 +++ 9 files changed, 131 insertions(+), 7 deletions(-) @@ -50,7 +50,7 @@ public class SearchBar { searchBar.render(context, mouseX, mouseY, deltaTicks); if (!Double.isNaN(parsedValue)) { - String expression = " §e= §2"+ RenderUtils.formatNumber((float) parsedValue); + String expression = " §e= §2" + RenderUtils.formatNumber((float) parsedValue); TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; if (textRenderer == null) return; @@ -68,9 +68,15 @@ public class SearchBar { if (ctrlIsPressed && input.key() == GLFW.GLFW_KEY_F) { shouldDisplay = !shouldDisplay; return true; - } else if (shouldDisplay() && searchBar.isFocused() && input.key() != GLFW.GLFW_KEY_ESCAPE) { - searchBar.keyPressed(input); - return true; + } else if (shouldDisplay() && searchBar.isFocused()) { + if (input.key() == GLFW.GLFW_KEY_ENTER) { + if (!Double.isNaN(parsedValue)) { + searchBar.setText(RenderUtils.formatNumber((float) parsedValue)); + } + } else if (input.key() != GLFW.GLFW_KEY_ESCAPE) { + searchBar.keyPressed(input); + return true; + } } return false; } @@ -0,0 +1,30 @@ +package blade.addon.features.other; + +public class SwingAnimation { + + private static int ignoreCount = 0; + + /** + * tells consumeSwing to ignore next swing + */ + public static void ignoreNext(int count) { + ignoreCount = count; + } + + /** + * Consumes a swing and checks if it should ignore swing rendering + */ + public static void consumeSwing() { + if (ignoreCount > 0) { + ignoreCount--; + } + } + + /** + * Checks if it should ignore the swing + * @return true if it should ignore the swing animation, else false + */ + public static boolean shouldIgnore() { + return ignoreCount > 0; + } +} @@ -0,0 +1,24 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SwingAnimation; +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.data.EntityUtil; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.EnderPearlItem; +import net.minecraft.util.Hand; +import net.minecraft.world.World; +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.CallbackInfoReturnable; + +@Mixin(EnderPearlItem.class) +public class EnderPearlItemMixin { + + @Inject(method = "use", at=@At("HEAD")) + private void use(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<Boolean> cir) { + if (Visual.stopPearlSwing && EntityUtil.isClientPlayer(user)) { + SwingAnimation.ignoreNext(2); + } + } +} @@ -1,6 +1,7 @@ package blade.addon.mixin; import blade.addon.features.item.DropAnimation; +import blade.addon.features.other.SwingAnimation; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.item.HeldItemRenderer; @@ -54,9 +55,15 @@ public abstract class HeldItemRendererMixin { @Inject(method = "swingArm", at = @At("HEAD"), cancellable = true) private void stopSwing(float swingProgress, float equipProgress, MatrixStack matrices, int armX, Arm arm, CallbackInfo ci) { - if (!DropAnimation.shouldProceed()) return; - ItemStack prevDropped = DropAnimation.getPrevDroppedItem(); - if (prevDropped == null) return; + + //TODO: refactor this + if (!SwingAnimation.shouldIgnore()) { + if (!DropAnimation.shouldProceed()) return; + ItemStack prevDropped = DropAnimation.getPrevDroppedItem(); + if (prevDropped == null) return; + } + + int i = arm == Arm.RIGHT ? 1 : -1; matrices.translate((float) i * 0.56F, -0.52F, -0.72F); ci.cancel(); @@ -0,0 +1,23 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SwingAnimation; +import blade.addon.utils.data.EntityUtil; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.util.Hand; +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(LivingEntity.class) +public class LivingEntityMixin { + + + @Inject(method = "swingHand(Lnet/minecraft/util/Hand;Z)V", at = @At("TAIL")) + public void swingHand(Hand hand, boolean fromServerPlayer, CallbackInfo ci) { + if (EntityUtil.isClientPlayer((Entity) (Object) this)) { + SwingAnimation.consumeSwing(); + } + } +} @@ -0,0 +1,23 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SwingAnimation; +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.data.EntityUtil; +import net.minecraft.item.ItemUsageContext; +import net.minecraft.item.ShovelItem; +import net.minecraft.util.ActionResult; +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.CallbackInfoReturnable; + +@Mixin(ShovelItem.class) +public class ShovelItemMixin { + + @Inject(method = "useOnBlock", at= @At(value = "INVOKE", target = "Lnet/minecraft/world/World;playSound(Lnet/minecraft/entity/Entity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FF)V")) + public void useOnBlock(ItemUsageContext context, CallbackInfoReturnable<ActionResult> cir) { + if (Visual.stopShovelFlattening && EntityUtil.isClientPlayer(context.getPlayer())) { + SwingAnimation.ignoreNext(2); + } + } +} @@ -395,6 +395,8 @@ public class Config { visual.add(new ConfigBool(Text.literal("Old player head size"), () -> Visual.oldPlayerHead, bool -> Visual.oldPlayerHead = bool)); visual.add(new ConfigBool(Text.literal("Fix wither essence"), () -> Visual.fixWitherEssence, bool -> Visual.fixWitherEssence = bool)); visual.add(new ConfigBool(Text.literal("1.8.9 like fishing bobber"), () -> Visual.oldFishingRod, bool -> Visual.oldFishingRod = bool)); + visual.add(new ConfigBool(Text.literal("Stop shovel swing when flattening dirt"), () -> Visual.stopShovelFlattening, bool -> Visual.stopShovelFlattening = bool)); + visual.add(new ConfigBool(Text.literal("Stop swinging when throwing a pearl"), () -> Visual.stopPearlSwing, bool -> Visual.stopPearlSwing = bool)); return visual; } @@ -46,4 +46,10 @@ public class Visual { @ConfigValue public static boolean oldFishingRod = false; + @ConfigValue + public static boolean stopShovelFlattening = false; + + @ConfigValue + public static boolean stopPearlSwing = false; + } @@ -6,9 +6,12 @@ "ChunkMixin", "ClientConnectionMixin", "ClientPlayNetworkHandlerMixin", + "EnderPearlItemMixin", "EntityMixin", "ItemStackMixin", + "LivingEntityMixin", "PlayerInventoryMixin", + "ShovelItemMixin", "StuckArrowsFeatureRendererMixin" ], "injectors": { |
refactor: incomplete 1.21.11 implementation查看变更gradle.properties | 8 ++++---- gradlew | 0 src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 5 ++++- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 5 ++++- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 7 +++++-- src/main/java/blade/addon/mixin/HandledScreenMixin.java | 4 ++-- src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 2 +- src/main/java/blade/addon/mixin/StatusEffectsDisplayMixin.java | 11 ++++++++--- src/main/java/blade/addon/utils/Waypoint.java | 6 +++++- src/main/java/blade/addon/utils/rendering/RenderLayers.java | 37 ++++++++++++++----------------------- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 9 +++++++-- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 21 ++++++++++++++++----- 12 files changed, 70 insertions(+), 45 deletions(-) @@ -7,8 +7,8 @@ org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.10 -yarn_mappings=1.21.10+build.3 +minecraft_version=1.21.11 +yarn_mappings=1.21.11+build.4 loader_version=0.18.4 loom_version=1.15-SNAPSHOT @@ -18,8 +18,8 @@ maven_group=blade.addon archives_base_name=blade-addons # Dependencies -fabric_version=0.138.4+1.21.10 +fabric_version=0.141.3+1.21.11 # I love dependencies sometimes breaking practical_config=1.4.3 modmenu_version = 16.0.0-rc.2 -hypixel_api_version = 1.0.1 \ No newline at end of file +hypixel_api_version = 1.0.1 @@ -11,6 +11,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.DrawStyle; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; @@ -19,7 +20,9 @@ import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.ItemEntity; import net.minecraft.text.Text; import net.minecraft.util.math.Box; +import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.MathHelper; +import net.minecraft.world.debug.gizmo.GizmoDrawing; import java.util.HashSet; import java.util.List; @@ -71,7 +74,7 @@ public class ItemHighlight { EntityDimensions dimension = itemEntity.getDimensions(itemEntity.getPose()); Box box = dimension.getBoxAt(x, y, z).expand(0.1).offset(0, 0.05, 0); float[] color = RenderUtils.toFloats(getColor(itemEntity)); - VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); + GizmoDrawing.box(box, DrawStyle.filled(ColorHelper.fromFloats(color[3], color[0], color[1], color[2]))); }); } @@ -17,6 +17,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.DrawStyle; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; @@ -29,6 +30,8 @@ import net.minecraft.util.Formatting; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; +import net.minecraft.util.math.ColorHelper; +import net.minecraft.world.debug.gizmo.GizmoDrawing; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -263,7 +266,7 @@ public class RelicTimer { Box box = pickedupRelic.box; float[] color = RenderUtils.toFloats(pickedupRelic.color); - VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); + GizmoDrawing.box(box, DrawStyle.filled(ColorHelper.fromFloats(color[3], color[0], color[1], color[2]))); } public static boolean display() { @@ -10,10 +10,13 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.DrawStyle; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.Box; +import net.minecraft.util.math.ColorHelper; +import net.minecraft.world.debug.gizmo.GizmoDrawing; import java.util.ArrayList; @@ -103,9 +106,9 @@ public class PositionMessages { for (PositionMessage positionMessage : positionMessages) { Box box = positionMessage.getBox(); if (positionMessage.sent()) { - VertexRendering.drawBox(entry, consumer, box, 0, 1, 0, 1); + GizmoDrawing.box(box, DrawStyle.stroked(ColorHelper.fromFloats(1.0f, 0, 1, 0))); } else { - VertexRendering.drawBox(entry, consumer, box, 1, 0, 0, 1); + GizmoDrawing.box(box, DrawStyle.stroked(ColorHelper.fromFloats(1.0f, 1, 0, 0))); } } } @@ -41,7 +41,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen } @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) - public void drawBackground(DrawContext context, Slot slot, CallbackInfo ci) { + public void drawBackground(DrawContext context, Slot slot, int mouseX, int mouseY, CallbackInfo ci) { int x = slot.x; int y = slot.y; ItemStack stack = slot.getStack(); @@ -49,7 +49,7 @@ public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen } @Inject(method = "drawSlot", at = @At(value = "TAIL")) - public void drawStarCount(DrawContext context, Slot slot, CallbackInfo ci) { + public void drawStarCount(DrawContext context, Slot slot, int mouseX, int mouseY, CallbackInfo ci) { int x = slot.x; int y = slot.y; ItemStack stack = slot.getStack(); @@ -53,7 +53,7 @@ public abstract class HeldItemRendererMixin { } @Inject(method = "swingArm", at = @At("HEAD"), cancellable = true) - private void stopSwing(float swingProgress, float equipProgress, MatrixStack matrices, int armX, Arm arm, CallbackInfo ci) { + private void stopSwing(float swingProgress, MatrixStack matrices, int armX, Arm arm, CallbackInfo ci) { if (!DropAnimation.shouldProceed()) return; ItemStack prevDropped = DropAnimation.getPrevDroppedItem(); if (prevDropped == null) return; @@ -1,25 +1,30 @@ package blade.addon.mixin; import blade.addon.utils.config.values.Visual; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.StatusEffectsDisplay; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.text.Text; 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 java.util.Collection; + @Mixin(StatusEffectsDisplay.class) public class StatusEffectsDisplayMixin { @Inject(method = "drawStatusEffects", at=@At("HEAD"), cancellable = true) - public void drawEffects(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { + public void drawEffects(DrawContext context, Collection<StatusEffectInstance> effects, int x, int height, int mouseX, int mouseY, int width, CallbackInfo ci) { if (Visual.hideStatusOverLay) { ci.cancel(); } } - @Inject(method = "drawStatusEffectTooltip", at=@At("HEAD"), cancellable = true) - public void drawToolTip(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { + @Inject(method = "drawTexts", at=@At("HEAD"), cancellable = true) + public void drawToolTip(CallbackInfo ci) { if (Visual.hideStatusOverLay) { ci.cancel(); } @@ -1,8 +1,12 @@ package blade.addon.utils; +import net.minecraft.client.render.DrawStyle; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.ColorHelper; +import net.minecraft.world.debug.gizmo.GizmoDrawing; public class Waypoint { private final double x, y, z, dx, dy, dz; @@ -38,7 +42,7 @@ public class Waypoint { } public void Render(VertexConsumer consumer, MatrixStack matrixStack) { - VertexRendering.drawFilledBox(matrixStack, consumer, x, y, z, x + dx, y + dy, z + dz, r, g, b, a); + GizmoDrawing.box(new Box(x, y, z, x + dx, y + dy, z + dz), DrawStyle.filled(ColorHelper.fromFloats(a, r, g, b))); } @Override @@ -1,7 +1,8 @@ package blade.addon.utils.rendering; +import net.minecraft.client.render.LayeringTransform; import net.minecraft.client.render.RenderLayer; -import net.minecraft.client.render.RenderPhase; +import net.minecraft.client.render.RenderSetup; import java.util.HashMap; import java.util.OptionalDouble; @@ -11,20 +12,15 @@ public class RenderLayers { private static final HashMap<Integer, RenderLayer> OUTLINE_WIDTHS = new HashMap<>(); private static final HashMap<Integer, RenderLayer> OUTLINE_WIDTHS_NO_DEPTH = new HashMap<>(); - public static final RenderLayer.MultiPhase FILLED_LAYER = - RenderLayer.of("filled", RenderLayer.DEFAULT_BUFFER_SIZE, false, true, RenderPipelines.FILLED_PIPELINE, RenderLayer.MultiPhaseParameters.builder() - .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) - .build(false)); + public static final RenderLayer FILLED_LAYER = + RenderLayer.of("filled", RenderSetup.builder(RenderPipelines.FILLED_PIPELINE).layeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).build()); - public static final RenderLayer.MultiPhase FILLED_LAYER_NO_DEPTH = - RenderLayer.of("through_wall_filled", RenderLayer.DEFAULT_BUFFER_SIZE, false, true, RenderPipelines.FILLED_PIPELINE_NO_DEPTH, RenderLayer.MultiPhaseParameters.builder() - .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) - .build(false)); - public static final RenderLayer.MultiPhase FILLED_ENTITY_LAYER = - RenderLayer.of("filled-entity", RenderLayer.DEFAULT_BUFFER_SIZE, false, true, RenderPipelines.FILLED_ENTITY_PIPELINE, RenderLayer.MultiPhaseParameters.builder() - .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) - .build(false)); + public static final RenderLayer FILLED_LAYER_NO_DEPTH = + RenderLayer.of("through_wall_filled", RenderSetup.builder(RenderPipelines.FILLED_PIPELINE_NO_DEPTH).layeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).build()); + + public static final RenderLayer FILLED_ENTITY_LAYER = + RenderLayer.of("filled-entity", RenderSetup.builder(RenderPipelines.FILLED_ENTITY_PIPELINE).layeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).build()); public static RenderLayer getOutline(int width, boolean depthCheck) { if (depthCheck) { @@ -32,11 +28,8 @@ public class RenderLayers { return OUTLINE_WIDTHS.get(width); } - RenderLayer.MultiPhase outline_layer = - RenderLayer.of("outline-entity-" + width, RenderLayer.DEFAULT_BUFFER_SIZE, false, true, RenderPipelines.OUTLINE_ENTITY_PIPELINE, RenderLayer.MultiPhaseParameters.builder() - .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) - .lineWidth(new RenderPhase.LineWidth(OptionalDouble.of(width))) - .build(false)); + RenderLayer outline_layer = + RenderLayer.of("outline-entity-" + width, RenderSetup.builder(RenderPipelines.OUTLINE_ENTITY_PIPELINE).outlineMode(RenderSetup.OutlineMode.IS_OUTLINE).layeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).build()); OUTLINE_WIDTHS.put(width, outline_layer); return outline_layer; @@ -45,11 +38,9 @@ public class RenderLayers { return OUTLINE_WIDTHS_NO_DEPTH.get(width); } - RenderLayer.MultiPhase outline_layer = - RenderLayer.of("outline-entity-" + width, RenderLayer.DEFAULT_BUFFER_SIZE, false, true, RenderPipelines.OUTLINE_ENTITY_PIPELINE_NO_DEPTH, RenderLayer.MultiPhaseParameters.builder() - .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) - .lineWidth(new RenderPhase.LineWidth(OptionalDouble.of(width))) - .build(false)); + RenderLayer outline_layer = + RenderLayer.of("outline-entity-" + width, RenderSetup.builder(RenderPipelines.OUTLINE_ENTITY_PIPELINE).outlineMode(RenderSetup.OutlineMode.IS_OUTLINE).layeringTransform(LayeringTransform.VIEW_OFFSET_Z_LAYERING).build()); + OUTLINE_WIDTHS_NO_DEPTH.put(width, outline_layer); return outline_layer; @@ -9,12 +9,15 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.DrawStyle; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; import net.minecraft.util.math.Box; +import net.minecraft.util.math.ColorHelper; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.debug.gizmo.GizmoDrawing; public class RenderUtils { @@ -87,12 +90,14 @@ public class RenderUtils { public static void renderFilled(MatrixStack matrixStack, VertexConsumer consumer, Box box, float[] rgba) { if (rgba[3] == 0) return; - VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + GizmoDrawing.box(box, DrawStyle.filled(ColorHelper.fromFloats(rgba[3], rgba[0], rgba[1], rgba[2]))); // Could be filledAndStroked + //VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); } public static void renderOutline(MatrixStack matrixStack, VertexConsumer consumer, Box box, float[] rgba) { if (rgba[3] == 0) return; - VertexRendering.drawBox(matrixStack.peek(), consumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); + GizmoDrawing.box(box, DrawStyle.stroked(ColorHelper.fromFloats(rgba[3], rgba[0], rgba[1], rgba[2]))); // Could be filledAndStroked + //VertexRendering.drawBox(matrixStack.peek(), consumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); } @@ -5,6 +5,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.state.WorldRenderState; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.Vec3d; @@ -25,7 +26,9 @@ public class RenderingEvents { } private static void filled(WorldRenderContext context) { - Vec3d camera = context.worldState().cameraRenderState.pos; + WorldRenderState worldState = context.worldState(); + if (worldState == null) return; + Vec3d camera = worldState.cameraRenderState.pos; MatrixStack matrices = context.matrices(); if (matrices == null) return; matrices.push(); @@ -40,7 +43,9 @@ public class RenderingEvents { } private static void filledNoDepth(WorldRenderContext context) { - Vec3d camera = context.worldState().cameraRenderState.pos; + WorldRenderState worldState = context.worldState(); + if (worldState == null) return; + Vec3d camera = worldState.cameraRenderState.pos; MatrixStack matrices = context.matrices(); if (matrices == null) return; matrices.push(); @@ -55,7 +60,9 @@ public class RenderingEvents { } private static void entityFilled(WorldRenderContext context) { - Vec3d camera = context.worldState().cameraRenderState.pos; + WorldRenderState worldState = context.worldState(); + if (worldState == null) return; + Vec3d camera = worldState.cameraRenderState.pos; MatrixStack matrices = context.matrices(); if (matrices == null) return; matrices.push(); @@ -71,7 +78,9 @@ public class RenderingEvents { private static void entityOutline(WorldRenderContext context) { - Vec3d camera = context.worldState().cameraRenderState.pos; + WorldRenderState worldState = context.worldState(); + if (worldState == null) return; + Vec3d camera = worldState.cameraRenderState.pos; MatrixStack matrices = context.matrices(); if (matrices == null) return; matrices.push(); @@ -86,7 +95,9 @@ public class RenderingEvents { } private static void entityOutlineNoDepth(WorldRenderContext context) { - Vec3d camera = context.worldState().cameraRenderState.pos; + WorldRenderState worldState = context.worldState(); + if (worldState == null) return; + Vec3d camera = worldState.cameraRenderState.pos; MatrixStack matrices = context.matrices(); if (matrices == null) return; matrices.push(); |
- increased the max char limit from 100 -> 200 in filter - added math parser to the searchbar, works p much the same as neus unless ive missed smth查看变更src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 2 +- src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/dragons/DragonHealth.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 2 +- src/main/java/blade/addon/features/filter/FilterEntry.java | 2 +- src/main/java/blade/addon/features/other/PracticeSS.java | 2 +- src/main/java/blade/addon/features/other/SearchBar.java | 20 +++++- src/main/java/blade/addon/mixin/BossBarHudMixin.java | 2 +- src/main/java/blade/addon/utils/Constants.java | 16 +++-- src/main/java/blade/addon/utils/MathParser.java | 306 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 2 +- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 22 +++--- 12 files changed, 354 insertions(+), 26 deletions(-) @@ -96,7 +96,7 @@ public class ItemHighlight { } else if (item.age > 11){ return Constants.GREEN; } else { - return Constants.ORANGE; + return Constants.GOLD; } } @@ -46,7 +46,7 @@ public class SecretSpawnTimer { int x = component.getScaledX(); int y = component.getScaledY(); - int color = tick > 10 ? Constants.GREEN : tick > 5 ? Constants.ORANGE : Constants.RED; + int color = tick > 10 ? Constants.GREEN : tick > 5 ? Constants.GOLD : Constants.RED; RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(tick + ""), x, y, component.getWidth(), color); @@ -78,7 +78,7 @@ public class DragonHealth { if (health == 0) return; Vec3d pos = EntityUtil.getLerpedPos(dragon); - RenderUtils.renderText(context, matrixStack, Text.literal(RenderUtils.formatHealth(health)).withColor(getColor(health)), pos, 5); + RenderUtils.renderText(context, matrixStack, Text.literal(RenderUtils.formatNumber(health)).withColor(getColor(health)), pos, 5); }); @@ -37,7 +37,7 @@ public class GoldorTickTimer { if (Floor7.inDeathTicks && !Floor7.makeGoldorTickUp) mod = 3.0 - mod; if (Floor7.inDeathTicks) num = mod; - int color = (mod < 1 ? Constants.GREEN : mod < 2 ? Constants.ORANGE : Constants.RED); + int color = (mod < 1 ? Constants.GREEN : mod < 2 ? Constants.GOLD : Constants.RED); RenderUtils.drawTimer(component, context, num, color); } @@ -34,7 +34,7 @@ public class FilterEntry extends TextFieldWidget { public FilterEntry(Supplier<String> supplier, Consumer<String> consumer, int index, FilterList parent) { super(MinecraftClient.getInstance().textRenderer, Constants.WIDGET_WIDTH, HEIGHT, Text.empty()); - this.setMaxLength(100); + this.setMaxLength(200); this.setText(supplier.get()); this.setChangedListener(consumer); this.index = index; @@ -304,7 +304,7 @@ public class PracticeSS { private static int getColor(int index) { if (index == 1 && ticksSinceLuckyButton > 0) return ExtraOptions.luckyButtonColor; if (index == currentIndex) return Constants.GREEN; - if (index == currentIndex + 1) return Constants.ORANGE; + if (index == currentIndex + 1) return Constants.GOLD; return Constants.RED; } @@ -1,8 +1,10 @@ package blade.addon.features.other; +import blade.addon.utils.MathParser; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.data.ItemUtil; import blade.addon.utils.rendering.DrawEvents; +import blade.addon.utils.rendering.RenderUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.Click; @@ -23,10 +25,11 @@ public class SearchBar { private static TextFieldWidget searchBar; private static boolean shouldDisplay = false; private static String searchTerm = ""; + private static double parsedValue = Double.NaN; public static void init() { DrawEvents.INVENTORY_SLOT_AFTER.register((context, item, x, y) -> { - if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar) { + if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar && Double.isNaN(parsedValue)) { if (!matches(item)) { context.fill(x, y, x + 16, y + 16, 0xaa111111); } @@ -45,6 +48,16 @@ public class SearchBar { public static void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { if (!exists() || !shouldDisplay() || !ExtraOptions.toggleableSearchBar) return; searchBar.render(context, mouseX, mouseY, deltaTicks); + + if (!Double.isNaN(parsedValue)) { + String expression = " §e= §2"+ RenderUtils.formatNumber((float) parsedValue); + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + if (textRenderer == null) return; + + int textX = searchBar.getX() + textRenderer.getWidth(searchTerm) + 4; + int textY = searchBar.getY() + (searchBar.getHeight() - 8) / 2; + context.drawText(textRenderer, expression, textX, textY, 0xffffffff, true); + } } public static boolean keyPressed(KeyInput input) { @@ -87,7 +100,10 @@ public class SearchBar { if (window == null || textRenderer == null) return false; searchBar = new TextFieldWidget(textRenderer, (window.getScaledWidth() - SEARCH_WIDTH) / 2, SEARCH_Y, SEARCH_WIDTH, SEARCH_HEIGHT, Text.literal("")); - searchBar.setChangedListener(string -> searchTerm = string.toLowerCase()); + searchBar.setChangedListener(string -> { + searchTerm = string.toLowerCase(); + parsedValue = MathParser.parseExpression(searchTerm); + }); return true; } @@ -45,7 +45,7 @@ public class BossBarHudMixin { } float currHealth = health * bossBar.getPercent(); - return Text.literal("§c" + name + " §a" + RenderUtils.formatHealth(currHealth) + "§7/§a" + RenderUtils.formatHealth(health)); + return Text.literal("§c" + name + " §a" + RenderUtils.formatNumber(currHealth) + "§7/§a" + RenderUtils.formatNumber(health)); } catch (Exception e) { Debug.LOGGER.error("Failed to modify bossbar name!", e); return bossBar.getName(); @@ -9,13 +9,21 @@ public class Constants { public static final double TICK_DURATION = 0.05; public static final int TEXT_HEIGHT = 10; + public static final int BLACK = 0xff000000; + public static final int DARK_BLUE = 0xff0000aa; + public static final int DARK_GREEN = 0xff00aa00; + public static final int DARK_AQUA = 0xff00aaaa; + public static final int DARK_RED = 0xffaa0000; + public static final int DARK_PURPLE = 0xffaa00aa; + public static final int GOLD = 0xffffaa00; + public static final int GRAY = 0xffaaaaaa; + public static final int DARK_GRAY = 0xff555555; + public static final int BLUE = 0xff5555ff; public static final int GREEN = 0xff55ff55; - public static final int ORANGE = 0xffffaa00; + public static final int AQUA = 0xff55ffff; public static final int RED = 0xffff5555; - public static final int YELLOW = 0xffffff55; - public static final int GOLD = 0xffffaa00; public static final int LIGHT_PURPLE = 0xffff55ff; - public static final int DARK_PURPLE = 0xffaa00aa; + public static final int YELLOW = 0xffffff55; public static final int FAIL = 0; public static final int SUCCESS = 1; @@ -0,0 +1,306 @@ +package blade.addon.utils; + +import java.util.ArrayList; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * This is purely made for the searchbar. + * The parser is based on Shunting Yard and Reverse Polish Notation. + * Yes this is commented more than other files, but this was more fun, + * so I actually felt like documenting it. + */ +public class MathParser { + + private static final Pattern NUMBER_PATTERN = Pattern.compile("^(?<num>-?\\d+)(?<decimal>\\.\\d+)?(?<unit>[bBmMkK])?"); + private static final Pattern TOKEN_PATTERN = Pattern.compile("[()+\\-*/^]"); + + /** + * Parses an expression and returns the value. + * @param string The expression to parse + * @return The value if it's a valid expression, otherwise NaN + */ + public static double parseExpression(String string) { + if (string == null) return Double.NaN; + + ArrayList<String> tokens; + try { + tokens = toTokens(string); + } catch (IllegalArgumentException e) { + return Double.NaN; + } + + if (tokens.isEmpty()) return Double.NaN; + + if (tokens.size() == 1) { + try { + //incase it's just a number + return tokenToNum(tokens.getFirst()); + } catch (NumberFormatException ignored) { + return Double.NaN; + } + } + + ArrayList<String> rpnTokens = toRPN(tokens); + + if (rpnTokens == null) { + return Double.NaN; + } + try { + return parseRPN(rpnTokens); + } catch (IllegalArgumentException e) { + return Double.NaN; + } + } + + /** + * Converts a String to a number. + * Supports orders of magnitudes like b, m and k. + * It also supports negative and decimal numbers. + * If it can't convert the number, + * {@code NumberFormatException} will be thrown. + * + * @param token The token to convert to a number + * @return The converted number + */ + private static double tokenToNum(String token) { + Matcher matcher = NUMBER_PATTERN.matcher(token); + if (!matcher.find()) { + throw new NumberFormatException(); + } + + String num = matcher.group("num"); + String decimal = matcher.group("decimal"); + String unit = matcher.group("unit"); + + double value; + + if (decimal != null) { + value = Double.parseDouble(num + decimal); + } else { + value = Double.parseDouble(num); + } + + + if (unit != null) { + switch (unit) { + case "b", "B": + value *= 1_000_000_000; + break; + case "m", "M": + value *= 1000_000; + break; + case "k", "K": + value *= 1000; + break; + } + } + + return value; + } + + + /** + * Parses an RPN token, Will throw an {@code IllegalArgumentException} when handling an invalid token. + * @param stack the stack to keep track of previously handled tokens + * @param token The token to parse + */ + private static void handleTokenRPN(Stack<Double> stack, String token) { + try { + double value = tokenToNum(token); + stack.push(value); + return; + } catch (NumberFormatException ignored) { + } + + if (stack.size() < 2) { + if (stack.size() == 1) { + if (token.equals("-")) { + //edge case to make for example -(2+3) negative + stack.push(stack.pop() * -1); + return; + } + } + + throw new IllegalArgumentException("Invalid token"); + } + + + double right = stack.pop(); + double left = stack.pop(); + + switch (token) { + case "+": + stack.push(left + right); + break; + case "-": + stack.push(left - right); + break; + case "*": + stack.push(left * right); + break; + case "/": + stack.push(left / right); + break; + case "^": + stack.push(Math.pow(left, right)); + break; + default: + throw new IllegalArgumentException("Invalid operator"); + } + } + + /** + * Parses an expression of tokens in RPN. + * Reference: <a href="https://inspirnathan.com/posts/150-reverse-polish-notation-evaluator-in-javascript/">reverse-polish-notation-evaluator-in-javascript</a> + * @param tokens The tokens to parse + * @return The parsed value, {@code Double.NaN} if its invalid + */ + private static double parseRPN(ArrayList<String> tokens) { + Stack<Double> stack = new Stack<>(); + + for (String token : tokens) { + handleTokenRPN(stack, token); + } + + if (stack.isEmpty()) return Double.NaN; + return stack.pop(); + } + + private static int getPrecedence(String token) { + return switch (token) { + case "^" -> 4; + case "*", "/" -> 3; + case "+", "-" -> 2; + default -> -1; + }; + } + + private static String getAssociative(String token) { + return switch (token) { + case "^" -> "right"; + case "*", "/", "+", "-" -> "left"; + default -> ""; + }; + } + + private static boolean isANumber(String token) { + Matcher matcher = NUMBER_PATTERN.matcher(token); + return matcher.find(); + } + + private static boolean addToken(ArrayList<String> output, Stack<String> stack, String token) { + if (isANumber(token)) { + output.add(token); + return true; + } else if (getPrecedence(token) != -1) { + if (stack.isEmpty()) { + stack.push(token); + return true; + } + + String top = stack.peek(); + + while (!top.equals("(") && (getPrecedence(top) > getPrecedence(token) + || (getPrecedence(top) == getPrecedence(token) && getAssociative(token).equals("left"))) + ) { + output.add(stack.pop()); + if (stack.isEmpty()) break; + top = stack.peek(); + } + stack.push(token); + return true; + + } else if (token.equals("(")) { + stack.push(token); + return true; + } else if (token.equals(")")) { + String top = stack.peek(); + while (!top.equals("(")) { + if (stack.isEmpty()) return false; + output.add(stack.pop()); + if (stack.isEmpty()) return false; + top = stack.peek(); + } + + if (stack.isEmpty() || !stack.peek().equals("(")) return false; + stack.pop(); + return true; + } else { + return false; + } + } + + /** + * Converts a list of tokens to a new in RPN + * Refrence: <a href="https://inspirnathan.com/posts/151-shunting-yard-algorithm-in-javascript/">151-shunting-yard-algorithm-in-javascript</a> + * @param tokens The tokens to convert + * @return The list of tokens in RPN + */ + private static ArrayList<String> toRPN(ArrayList<String> tokens) { + ArrayList<String> output = new ArrayList<>(); + Stack<String> stack = new Stack<>(); + + for (String token : tokens) { + if (!addToken(output, stack, token)) { + return null; + } + } + + while (!stack.isEmpty()) { + String token = stack.pop(); + if (token.equals("(")) return null; + output.add(token); + } + + return output; + } + + /** + * Split an expression string to an ArrayList of tokens. + * Throws an {@code IllegalArgumentException} when an invalid token is read. + * + * @param string The string to split into token + * @return The list of tokens + */ + private static ArrayList<String> toTokens(String string) { + ArrayList<String> output = new ArrayList<>(); + String copiedString = string.replaceAll(" ", ""); + + //to handle binary subtraction not getting confused + //with unary subtraction + boolean wasPrevNum = false; + + while (!copiedString.isEmpty()) { + Matcher matcher = NUMBER_PATTERN.matcher(copiedString); + if (!wasPrevNum && matcher.find()) { + String token = matcher.group(); + int index = copiedString.indexOf(token); + if (index == 0) { + copiedString = copiedString.substring(token.length()); + output.add(token); + wasPrevNum = true; + continue; + } + } + + matcher = TOKEN_PATTERN.matcher(copiedString); + if (matcher.find()) { + String token = matcher.group(); + int index = copiedString.indexOf(token); + if (index == 0) { + copiedString = copiedString.substring(token.length()); + output.add(token); + wasPrevNum = false; + continue; + } + } + + throw new IllegalArgumentException("String: " + string + " has invalid token, ended at: " + copiedString); + } + + return output; + } + +} @@ -273,7 +273,7 @@ public class Config { highlight.add(new ConfigDouble(Text.literal("Extra Wither Width"), () -> MobHighlight.witherExtraWidth, num -> MobHighlight.witherExtraWidth = num, 0.1, 0, 1.5)); highlight.add(new ConfigInt(Text.literal("Outline Width"), () -> MobHighlight.outlineWidth, num -> MobHighlight.outlineWidth = num, 1, 1, 10)); highlight.add(new ConfigOptions<>(Text.literal("Highlight mode"), MobHighlight.HighlightType.values(), () -> MobHighlight.currentHighlight, type -> MobHighlight.currentHighlight = type)); - highlight.add(new ConfigBool(Text.literal("Hide none stared nametags"), () -> MobHighlight.hideNoneStaredNameTags, bool -> MobHighlight.hideNoneStaredNameTags = bool)); + highlight.add(new ConfigBool(Text.literal("Hide none starred nametags"), () -> MobHighlight.hideNoneStaredNameTags, bool -> MobHighlight.hideNoneStaredNameTags = bool)); highlight.add(new ConfigColor(Text.literal("Star mob filled color"), () -> MobHighlight.starFilledColor, color -> MobHighlight.starFilledColor = color, "star-filled", true)); highlight.add(new ConfigColor(Text.literal("Star mob outline color"), () -> MobHighlight.starOutlineColor, color -> MobHighlight.starOutlineColor = color, "star-outline", true)); @@ -29,7 +29,7 @@ public class RenderUtils { } public static int getStatusColor(int minGreen, int minOrange, int value) { - return value >= minGreen ? Constants.GREEN : value >= minOrange ? Constants.ORANGE : Constants.RED; + return value >= minGreen ? Constants.GREEN : value >= minOrange ? Constants.GOLD : Constants.RED; } public static void drawText(DrawContext context, HUDComponent component, Text text, int color) { @@ -117,19 +117,17 @@ public class RenderUtils { renderText(context, matrices, text, pos.x, pos.y, pos.z, scale); } - - public static String formatHealth(float health) { + public static String formatNumber(float num) { if (Floor7.capitalizeHealthNumbers) { - if (health >= 1e9) return String.format("%.1fB", health / 1e9); - if (health >= 1e6) return String.format("%.1fM", health / 1e6); - if (health >= 1e3) return String.format("%.1fK", health / 1e3); - return health + ""; + if (num >= 1e9) return String.format("%.1fB", num / 1e9); + if (num >= 1e6) return String.format("%.1fM", num / 1e6); + if (num >= 1e3) return String.format("%.1fK", num / 1e3); + return num + ""; } else { - if (health >= 1e9) return String.format("%.1fb", health / 1e9); - if (health >= 1e6) return String.format("%.1fm", health / 1e6); - if (health >= 1e3) return String.format("%.1fk", health / 1e3); - return health + ""; + if (num >= 1e9) return String.format("%.1fb", num / 1e9); + if (num >= 1e6) return String.format("%.1fm", num / 1e6); + if (num >= 1e3) return String.format("%.1fk", num / 1e3); + return num + ""; } } - } |
| - added a quiz progress toggle - added a toggle each to ignore color codes for chat filters and notifications - added current Section display - added changing colors with current section progress - added prev objective finished in section - fixed invalid regexes not being caught in chat filters
- hopefully made end of run splits not get sent in the middle of class xp 查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/dungeon/QuizTimer.java | 23 ++++++++++++++++++++++- src/main/java/blade/addon/features/dungeon/f7/terms/CurrentSection.java | 33 +++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/terms/SectionProgress.java | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/main/java/blade/addon/features/filter/Filters.java | 15 ++++++++++++++- src/main/java/blade/addon/features/notifications/Notifications.java | 6 ++++++ src/main/java/blade/addon/utils/config/Config.java | 24 ++++++++++++++++++++---- src/main/java/blade/addon/utils/config/components/Components.java | 6 +++++- src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 6 ++++++ src/main/java/blade/addon/utils/config/values/Floor7.java | 9 +++++++++ src/main/java/blade/addon/utils/data/TextUtil.java | 5 +++++ src/main/java/blade/addon/utils/dungeon/Phase.java | 6 ++++-- 13 files changed, 192 insertions(+), 11 deletions(-) @@ -28,6 +28,7 @@ import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; import blade.addon.features.dungeon.f7.storm.DistanceToLedge; import blade.addon.features.dungeon.f7.storm.PillarExplode; import blade.addon.features.dungeon.f7.storm.StormTickTimer; +import blade.addon.features.dungeon.f7.terms.CurrentSection; import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; @@ -158,5 +159,6 @@ public class Bladeaddons implements ModInitializer { SectionCompletion.init(); MaxorTickTimer.init(); BloodNotifier.init(); + CurrentSection.init(); } } \ No newline at end of file @@ -1,11 +1,16 @@ package blade.addon.features.dungeon; +import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; public class QuizTimer { @@ -13,6 +18,7 @@ public class QuizTimer { private static final int QUESTION_DURATION = 100; private static int tick = 0; + private static int stage = 0; public static void init() { @@ -22,10 +28,13 @@ public class QuizTimer { String string = text.getString(); if (string.equals("[STATUE] Oruo the Omniscient: I am Oruo the Omniscient. I have lived many lives. I have learned all there is to know.")) { tick = START_DURATION; + stage = 1; } else if (string.equals("[STATUE] Oruo the Omniscient: 2 questions left... Then you will have proven your worth to me!")) { tick = QUESTION_DURATION; + stage = 2; } else if (string.equals("[STATUE] Oruo the Omniscient: One more question!")) { tick = QUESTION_DURATION; + stage = 3; } return false; @@ -38,6 +47,7 @@ public class QuizTimer { Events.ON_LOCATION_CHANGE.register(newLocation -> { tick = 0; + stage = 0; return false; }); } @@ -47,7 +57,18 @@ public class QuizTimer { } public static void render(HUDComponent component, DrawContext context) { - RenderUtils.drawPrefixedTimer(component, context, "Quiz", tick); + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + if (textRenderer == null) return; + + if (Dungeons.quizProgress) { + Text drawnText = Text.literal("Quiz " + "(").withColor(ExtraOptions.timerPrefixColor) + .append(Text.literal(stage + "/3").withColor(0xffffffff) + .append(Text.literal("): ").withColor(ExtraOptions.timerPrefixColor)) + .append(Text.literal(Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION) + "s").withColor(0xffffffff))); + context.drawText(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); + } else { + RenderUtils.drawPrefixedTimer(component, context, "Quiz", tick); + } } @@ -0,0 +1,33 @@ +package blade.addon.features.dungeon.f7.terms; + +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; + +public class CurrentSection { + + private static int section = 1; + + public static void init() { + Events.ON_SECTION_CHANGE.register(() -> { + section++; + return false; + }); + Events.ON_LOCATION_CHANGE.register(newLocation -> { + section = 1; + return false; + }); + } + + public static boolean display() { + return Floor7.showCurrentSection && Phase.inTerminals(); + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawPrefixedText(component, context, "Section", " " + section); + } + +} @@ -1,6 +1,7 @@ package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.TextUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; import blade.addon.utils.events.Events; @@ -13,18 +14,48 @@ public class SectionProgress { private static int completed = 0; private static int sectionTotal = 7; + private static String prevObjective = ""; + + private static String completedFormat = ""; + private static String objectiveFormat = ""; public static void init() { + updateObjectiveFormat(); + updateProgressFormat(); + + Events.ON_GAME_MESSAGE.register((message) -> { + if (!Phase.inTerminals() || !Floor7.sectionPrevObjective) return false; + + String string = message.getString(); + if (string.equals("The gate has been destroyed!")) { + prevObjective = "Gate Destroyed"; + updateObjectiveFormat(); + } + + else if (string.equals("The gate will open in 5 seconds!")) { + prevObjective = "Break Gate"; + updateObjectiveFormat(); + } + + return false; + }); + Events.ON_TERMINAL.register((formattedName, action, objective, current, total) -> { completed = current; sectionTotal = total; + prevObjective = TextUtil.capitaliseFirst(objective); + updateObjectiveFormat(); + updateProgressFormat(); return false; }); Events.ON_SECTION_CHANGE.register(() -> { if (completed == sectionTotal) completed = 0; sectionTotal = getTotal(); + prevObjective = ""; + updateObjectiveFormat(); + updateProgressFormat(); return false; }); @@ -36,8 +67,33 @@ public class SectionProgress { } + private static void updateObjectiveFormat() { + objectiveFormat = switch (prevObjective) { + case "Lever", "Gate Destroyed" -> "§c"; + case "Device" -> "§d"; + case "Terminal" -> "§b"; + case "Break Gate" -> "§5§l"; + default -> ""; + }; + } + + private static void updateProgressFormat() { + if (completed >= sectionTotal) completedFormat = "§6§l"; + else if (sectionTotal - completed == 1 || (completed == 7 && sectionTotal == 8)) completedFormat = "§a"; + else if (completed >= 3) completedFormat = "§e"; + else completedFormat = "§c"; + } + private static int getTotal() { - return Section.getSection() != 2? 7: 8; + return Section.getSection() != 2 ? 7 : 8; + } + + private static Text getProgressText() { + if (Floor7.sectionColorProgress) { + return Text.literal("§f(" + completedFormat + completed + "§f/§a" + sectionTotal + "§f)"); + } else { + return Text.literal("§a(§c" + completed + "§a/" + sectionTotal + ")"); + } } public static boolean display() { @@ -45,7 +101,12 @@ public class SectionProgress { } public static void render(HUDComponent component, DrawContext context) { - RenderUtils.drawCenteredText(context, component, Text.literal("§a(§c" + completed + "§a/" + sectionTotal + ")")); + if (Floor7.sectionPrevObjective) { + RenderUtils.drawCenteredText(context, component, Text.literal(objectiveFormat + prevObjective + " ").append(getProgressText())); + } else { + RenderUtils.drawCenteredText(context, component, getProgressText()); + } + } } @@ -1,12 +1,16 @@ package blade.addon.features.filter; import blade.addon.utils.config.FolderUtility; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.debug.Debug; import config.practical.manager.ConfigManager; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.minecraft.text.Text; import java.util.ArrayList; import java.util.List; +import java.util.regex.PatternSyntaxException; public class Filters { @@ -21,8 +25,17 @@ public class Filters { ClientReceiveMessageEvents.ALLOW_GAME.register((message, overlay) -> { if (overlay) return true; String string = message.getString(); + + if (ExtraOptions.ignoreColorCodesFilter) { + string = string.replaceAll("§.", ""); + } + for (String filter : filters) { - if (string.matches(filter)) return false; + try { + if (string.matches(filter)) return false; + } catch (PatternSyntaxException e) { + Debug.sendDebugMessage(Text.literal("Invalid regex: " + filter)); + } } return true; }); @@ -2,6 +2,7 @@ package blade.addon.features.notifications; import blade.addon.utils.Misc; import blade.addon.utils.config.FolderUtility; +import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -40,6 +41,11 @@ public class Notifications { load(); Events.ON_GAME_MESSAGE.register(text -> { String message = text.getString(); + + if (ExtraOptions.ignoreColorCodesNotification) { + message = message.replaceAll("§.", ""); + } + if (Debug.sendNotiDebug) { Misc.addChatMessage(Text.literal(message.replaceAll("§", "&"))); } @@ -59,8 +59,17 @@ public class Config { private static ConfigCategory general() { ConfigCategory general = new ConfigCategory("General"); general.add(new ConfigString(Text.literal("Message prefix"), () -> ExtraOptions.textPrefix, str -> ExtraOptions.textPrefix = str)); - general.add(new ConfigButton(Text.literal("Edit Notifications"), () -> MinecraftClient.getInstance().setScreen(new NotificationList()))); - general.add(new ConfigButton(Text.literal("Edit Chat filters"), () -> MinecraftClient.getInstance().setScreen(new FilterList()))); + + ConfigSection notifications = new ConfigSection(Text.literal("Chat Notifications")); + notifications.add(new ConfigButton(Text.literal("Edit Notifications"), () -> MinecraftClient.getInstance().setScreen(new NotificationList()))); + notifications.add(new ConfigBool(Text.literal("Ignore color codes"), () -> ExtraOptions.ignoreColorCodesNotification, bool -> ExtraOptions.ignoreColorCodesNotification = bool)); + general.add(notifications); + + + ConfigSection chatFilter = new ConfigSection(Text.literal("Chat filter")); + chatFilter.add(new ConfigButton(Text.literal("Edit"), () -> MinecraftClient.getInstance().setScreen(new FilterList()))); + chatFilter.add(new ConfigBool(Text.literal("Ignore color codes"), () -> ExtraOptions.ignoreColorCodesFilter, bool -> ExtraOptions.ignoreColorCodesFilter = bool)); + general.add(chatFilter); return general; } @@ -132,6 +141,7 @@ public class Config { dungeons.add(new ConfigBool(Text.literal("Highlight teammates"), () -> Dungeons.highlightTeammates, bool -> Dungeons.highlightTeammates = bool)); dungeons.add(new ConfigBool(Text.literal("Render class names"), () -> Dungeons.renderClassName, bool -> Dungeons.renderClassName = bool)); dungeons.add(new ConfigBool(Text.literal("Time until quiz question"), () -> Dungeons.quizTimer, bool -> Dungeons.quizTimer = bool)); + dungeons.add(new ConfigBool(Text.literal("append quiz progress"), () -> Dungeons.quizProgress, bool -> Dungeons.quizProgress = bool)); dungeons.add(new ConfigBool(Text.literal("Draw boss health numbers"), () -> Dungeons.bossHealthNumbers, bool -> Dungeons.bossHealthNumbers = bool)); dungeons.add(new ConfigBool(Text.literal("Blood notifier on first 4 spawned"), () -> Dungeons.alertBloodSpawns, bool -> Dungeons.alertBloodSpawns = bool)); dungeons.add(new ConfigBool(Text.literal("Blood notifier on all classes"), () -> Dungeons.alertBloodForAllClasses, bool -> Dungeons.alertBloodForAllClasses = bool)); @@ -184,12 +194,18 @@ public class Config { goldor.add(new ConfigBool(Text.literal("SS completion notification"), () -> Floor7.notifySSCompletion, bool -> Floor7.notifySSCompletion = bool)); goldor.add(new ConfigBool(Text.literal("Melody warning notification"), () -> Floor7.notifiyMelody, bool -> Floor7.notifiyMelody = bool)); goldor.add(new ConfigBool(Text.literal("Send terminal time stamps"), () -> Floor7.terminalTimeStamps, bool -> Floor7.terminalTimeStamps = bool)); - goldor.add(new ConfigBool(Text.literal("Display section progress"), () -> Floor7.showSectionProgress, bool -> Floor7.showSectionProgress = bool)); goldor.add(new ConfigBool(Text.literal("Section completion notification"), () -> Floor7.sectionCompletionNotification, bool -> Floor7.sectionCompletionNotification = bool)); goldor.add(new ConfigSound(Text.literal("Section complete sound"), Floor7.sectionChangeSound, 2, 2, true)); - + goldor.add(new ConfigBool(Text.literal("Current section display"), () -> Floor7.showCurrentSection, bool -> Floor7.showCurrentSection = bool)); floor7.add(goldor); + ConfigSection sectionProgress = new ConfigSection(Text.literal("Section progress")); + sectionProgress.add(new ConfigBool(Text.literal("Display section progress"), () -> Floor7.showSectionProgress, bool -> Floor7.showSectionProgress = bool)); + sectionProgress.add(new ConfigBool(Text.literal("Change color with progress"), () -> Floor7.sectionColorProgress, bool -> Floor7.sectionColorProgress = bool)); + sectionProgress.add(new ConfigBool(Text.literal("Include prev objective"), () -> Floor7.sectionPrevObjective, bool -> Floor7.sectionPrevObjective = bool)); + floor7.add(sectionProgress); + + ConfigSection titles = new ConfigSection(Text.literal("Terminal titles")); titles.add(new ConfigBool(Text.literal("Disable titles on pre4"), () -> Floor7.disableTitlesAtPre4, bool -> Floor7.disableTitlesAtPre4 = bool)); titles.add(new ConfigBool(Text.literal("Disable titles on ss"), () -> Floor7.disableTitlesAtSS, bool -> Floor7.disableTitlesAtSS = bool)); @@ -18,6 +18,7 @@ import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.dungeon.f7.maxor.MaxorStun; +import blade.addon.features.dungeon.f7.terms.CurrentSection; import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; import blade.addon.features.dungeon.f7.terms.MelodyWarning; @@ -142,7 +143,7 @@ public class Components { public static HUDComponent sectionProgressDisplay = new HUDComponent(0, 0, 30, 10, 1, "Section progress", SectionProgress::display, SectionProgress::render, () -> Floor7.showSectionProgress); @ConfigValue - public static HUDComponent quizTimerDisplay = new HUDComponent(0, 0, 60, 10, 1, "Quiz timer", QuizTimer::display, QuizTimer::render, () -> Dungeons.quizTimer); + public static HUDComponent quizTimerDisplay = new HUDComponent(0, 0, 80, 10, 1, "Quiz timer", QuizTimer::display, QuizTimer::render, () -> Dungeons.quizTimer); @ConfigValue public static HUDComponent maxorStunDisplay = new HUDComponent(0, 0, 70, 10, 1, "Maxor stun display", MaxorStun::display, MaxorStun::render, () -> Floor7.maxorStunDuration); @@ -161,4 +162,7 @@ public class Components { @ConfigValue public static HUDComponent bloodNotificationDisplay = new HUDComponent(0, 0, NOTIFICATION_WIDTH, 10, 1, "blood notification", BloodNotifier::display, BloodNotifier::render, () -> Dungeons.alertBloodSpawns && !Dungeons.combineScreenNotifications); + + @ConfigValue + public static HUDComponent currentSectionDisplay = new HUDComponent(0, 0, 50, 10, 1, "Current section", CurrentSection::display, CurrentSection::render, () -> Floor7.showCurrentSection); } @@ -145,4 +145,7 @@ public class Dungeons { @ConfigValue public static boolean alertBloodForAllClasses = false; + + @ConfigValue + public static boolean quizProgress = false; } @@ -129,4 +129,10 @@ public class ExtraOptions { @ConfigValue public static boolean oldTubaSound = false; + + @ConfigValue + public static boolean ignoreColorCodesFilter = false; + + @ConfigValue + public static boolean ignoreColorCodesNotification = false; } @@ -165,4 +165,13 @@ public class Floor7 { @ConfigValue public static boolean enableMaxorTickTimer = false; + + @ConfigValue + public static boolean showCurrentSection = false; + + @ConfigValue + public static boolean sectionColorProgress = false; + + @ConfigValue + public static boolean sectionPrevObjective = false; } @@ -121,4 +121,9 @@ public class TextUtil { return Constants.DECIMAL_FORMAT.format(tick * Constants.TICK_DURATION); } + public static String capitaliseFirst(String message) { + String strippedMessage = message.strip(); + if (strippedMessage.length() < 2) return message; + return strippedMessage.substring(0, 1).toUpperCase() + strippedMessage.substring(1).toLowerCase(); + } } @@ -148,7 +148,11 @@ public class Phase { private static void endRun() { runOver = true; currentPhase = currentSplits.size(); + Scheduler.scheduleTask(Phase::printSplits, 2); + Events.ON_RUN_END.invoke(RunEndEvent::onRunEnd); + } + private static void printSplits() { Misc.addChatMessage(Text.literal("§aSplits: ")); for (Split split : currentSplits) { split.end(); @@ -159,8 +163,6 @@ public class Phase { Text timeLost = Text.literal("§aApproximately §e" + Constants.DECIMAL_FORMAT.format(time) + "s §alost to lag."); Misc.addChatMessage(timeLost); } - - Events.ON_RUN_END.invoke(RunEndEvent::onRunEnd); } public static int getPhase() { |
| - fixed warp cooldown reseting when it shouldn't - added maxor tick timer (for vortie spring boots or smth)
- added blood room first 4 mob spawn notifier 查看变更src/main/java/blade/addon/Bladeaddons.java | 16 ++++++++++------ src/main/java/blade/addon/features/dungeon/BloodNotifier.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 2 ++ src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorTickTimer.java | 35 +++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 2 -- src/main/java/blade/addon/utils/config/Config.java | 5 ++++- src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 5 +++++ src/main/java/blade/addon/utils/config/components/Components.java | 8 ++++++++ src/main/java/blade/addon/utils/config/values/Dungeons.java | 6 ++++++ src/main/java/blade/addon/utils/config/values/Floor7.java | 3 +++ 10 files changed, 133 insertions(+), 9 deletions(-) @@ -1,6 +1,7 @@ package blade.addon; import blade.addon.features.dungeon.AutoRequeue; +import blade.addon.features.dungeon.BloodNotifier; import blade.addon.features.dungeon.ChestCounter; import blade.addon.features.dungeon.ExplosiveShot; import blade.addon.features.dungeon.HidePlayers; @@ -12,20 +13,21 @@ import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.BossWaypoints; -import blade.addon.features.dungeon.f7.invincibility.MaskHighlight; -import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; -import blade.addon.features.dungeon.f7.storm.DistanceToLedge; -import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; -import blade.addon.features.dungeon.f7.storm.PillarExplode; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; -import blade.addon.features.dungeon.f7.storm.StormTickTimer; +import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; import blade.addon.features.dungeon.f7.dragons.DragonHealth; import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; +import blade.addon.features.dungeon.f7.invincibility.MaskHighlight; import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.dungeon.f7.location.PositionMessages; +import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; import blade.addon.features.dungeon.f7.maxor.MaxorStun; +import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; +import blade.addon.features.dungeon.f7.storm.DistanceToLedge; +import blade.addon.features.dungeon.f7.storm.PillarExplode; +import blade.addon.features.dungeon.f7.storm.StormTickTimer; import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; @@ -154,5 +156,7 @@ public class Bladeaddons implements ModInitializer { SearchBar.init(); TubaSound.init(); SectionCompletion.init(); + MaxorTickTimer.init(); + BloodNotifier.init(); } } \ No newline at end of file @@ -0,0 +1,60 @@ +package blade.addon.features.dungeon; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; + +public class BloodNotifier { + + private static boolean detected = false; + private static long prevTime = 0; + + public static void init() { + + Events.ON_GAME_MESSAGE.register(message -> { + if (detected || !Location.inDungeon()) return false; + + + if (message.getString().equals("[BOSS] The Watcher: Let's see how you can handle this.")) { + detected = true; + prevTime = System.currentTimeMillis(); + + if (correctClass()) { + Misc.sendSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0); + } + } + + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + reset(); + return false; + }); + } + + private static void reset() { + detected = false; + } + + private static boolean correctClass() { + return Dungeons.alertBloodForAllClasses || DungeonClass.isClass(DungeonClass.MAGE); + } + + public static boolean display() { + return Dungeons.alertBloodSpawns && System.currentTimeMillis() - prevTime < 2000 && correctClass(); + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, Text.literal("First four mobs spawned!"), Constants.RED); + } + +} @@ -21,6 +21,8 @@ public class WarpCooldown { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { if (!Dungeons.enableWarpCooldown) return; + if ((endTime - System.currentTimeMillis()) > 0) return; + Matcher matcher = PATTERN.matcher(message.getString()); if (matcher.find()) { endTime = System.currentTimeMillis() + WARP_COOLDOWN_MS; @@ -0,0 +1,35 @@ +package blade.addon.features.dungeon.f7.maxor; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; + +public class MaxorTickTimer { + + private static int tick = 0; + + public static void init() { + Events.ON_SERVER_TICK.register(() -> { + if (Location.inDungeon() && Phase.inP1()) tick++; + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + tick = 0; + return false; + }); + } + + public static boolean display() { + return Floor7.enableMaxorTickTimer && Location.inDungeon() && Phase.inP1(); + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawTimer(component, context, tick, 0xffffffff); + } + +} @@ -37,8 +37,6 @@ public class GoldorTickTimer { if (Floor7.inDeathTicks && !Floor7.makeGoldorTickUp) mod = 3.0 - mod; if (Floor7.inDeathTicks) num = mod; - System.out.println(num); - int color = (mod < 1 ? Constants.GREEN : mod < 2 ? Constants.ORANGE : Constants.RED); RenderUtils.drawTimer(component, context, num, color); @@ -133,6 +133,8 @@ public class Config { dungeons.add(new ConfigBool(Text.literal("Render class names"), () -> Dungeons.renderClassName, bool -> Dungeons.renderClassName = bool)); dungeons.add(new ConfigBool(Text.literal("Time until quiz question"), () -> Dungeons.quizTimer, bool -> Dungeons.quizTimer = bool)); dungeons.add(new ConfigBool(Text.literal("Draw boss health numbers"), () -> Dungeons.bossHealthNumbers, bool -> Dungeons.bossHealthNumbers = bool)); + dungeons.add(new ConfigBool(Text.literal("Blood notifier on first 4 spawned"), () -> Dungeons.alertBloodSpawns, bool -> Dungeons.alertBloodSpawns = bool)); + dungeons.add(new ConfigBool(Text.literal("Blood notifier on all classes"), () -> Dungeons.alertBloodForAllClasses, bool -> Dungeons.alertBloodForAllClasses = bool)); return dungeons; } @@ -151,6 +153,7 @@ public class Config { floor7.add(waypoints); ConfigSection maxor = new ConfigSection(Text.literal("Maxor")); + maxor.add(new ConfigBool(Text.literal("Maxor tick timer"), () -> Floor7.enableMaxorTickTimer, bool -> Floor7.enableMaxorTickTimer = bool)); maxor.add(new ConfigBool(Text.literal("Crystal Spawn Time"), () -> Floor7.enableCrystalSpawnTime, bool -> Floor7.enableCrystalSpawnTime = bool)); maxor.add(new ConfigBool(Text.literal("Crystal place reminder"), () -> Floor7.crystalPlaceReminder, bool -> Floor7.crystalPlaceReminder = bool)); maxor.add(new ConfigBool(Text.literal("Display reminder instantly"), () -> Floor7.instantlyDisplayCrystalReminder, bool -> Floor7.instantlyDisplayCrystalReminder = bool)); @@ -158,7 +161,7 @@ public class Config { floor7.add(maxor); ConfigSection storm = new ConfigSection(Text.literal("Storm")); - storm.add(new ConfigBool(Text.literal("Storm Tick timer"), () -> Floor7.enableStormTickTimer, bool -> Floor7.enableStormTickTimer = bool)); + storm.add(new ConfigBool(Text.literal("Storm tick timer"), () -> Floor7.enableStormTickTimer, bool -> Floor7.enableStormTickTimer = bool)); storm.add(new ConfigColor(Text.literal("Timer color"), () -> Floor7.stormTickTimerColor, color -> Floor7.stormTickTimerColor = color, "storm-tick-timer-color", false)); storm.add(new ConfigBool(Text.literal("Tick down from 5"), () -> Floor7.tickDownStormTickTimer, bool -> Floor7.tickDownStormTickTimer = bool)); storm.add(new ConfigBool(Text.literal("First Death time"), () -> Floor7.enableStormDeathTime, bool -> Floor7.enableStormDeathTime = bool)); @@ -1,5 +1,6 @@ package blade.addon.utils.config.components; +import blade.addon.features.dungeon.BloodNotifier; import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; @@ -41,6 +42,8 @@ public class CombinedScreenNotifications { return true; } else if (SectionCompletion.display()) { return true; + } else if (BloodNotifier.display()) { + return true; } return false; } @@ -66,6 +69,8 @@ public class CombinedScreenNotifications { ArrowSwapper.renderNotification(component, context); } else if (SectionCompletion.display()) { SectionCompletion.render(component, context); + }else if (BloodNotifier.display()) { + BloodNotifier.render(component, context); }else { RenderUtils.drawCenteredText(context, component, Text.literal("Some notification")); } @@ -1,5 +1,6 @@ package blade.addon.utils.config.components; +import blade.addon.features.dungeon.BloodNotifier; import blade.addon.features.dungeon.ChestCounter; import blade.addon.features.dungeon.QuizTimer; import blade.addon.features.dungeon.RunStartValidator; @@ -7,6 +8,7 @@ import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; +import blade.addon.features.dungeon.f7.maxor.MaxorTickTimer; import blade.addon.features.dungeon.f7.storm.DistanceToLedge; import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; import blade.addon.features.dungeon.f7.storm.PillarExplode; @@ -153,4 +155,10 @@ public class Components { @ConfigValue public static HUDComponent sectionCompletionDisplay = new HUDComponent(0, 0, NOTIFICATION_WIDTH, 10, 1, "Section completion", SectionCompletion::display, SectionCompletion::render, () -> Floor7.sectionCompletionNotification && !Dungeons.combineScreenNotifications); + + @ConfigValue + public static HUDComponent maxorTickTimer = new HUDComponent(0, 0, TICK_TIMER_WIDTH, 10, 1, "Maxor Tick Timer", MaxorTickTimer::display, MaxorTickTimer::render, () -> Floor7.enableMaxorTickTimer); + + @ConfigValue + public static HUDComponent bloodNotificationDisplay = new HUDComponent(0, 0, NOTIFICATION_WIDTH, 10, 1, "blood notification", BloodNotifier::display, BloodNotifier::render, () -> Dungeons.alertBloodSpawns && !Dungeons.combineScreenNotifications); } @@ -139,4 +139,10 @@ public class Dungeons { @ConfigValue public static boolean removeMaskPart = true; + + @ConfigValue + public static boolean alertBloodSpawns = false; + + @ConfigValue + public static boolean alertBloodForAllClasses = false; } @@ -162,4 +162,7 @@ public class Floor7 { @ConfigValue public static SoundData sectionChangeSound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0, 1); + + @ConfigValue + public static boolean enableMaxorTickTimer = false; } |
- fixed revive title not being shown after dying on pre4 - possibly improved at location notifier (needs testing)查看变更src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 13 +++++++++---- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 7 +++++-- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 5 +++-- src/main/java/blade/addon/features/dungeon/f7/terms/DeviceNotifier.java | 14 ++++++++++++-- src/main/java/blade/addon/mixin/InGameHudMixin.java | 4 ++-- src/main/java/blade/addon/utils/events/CustomEvents.java | 3 ++- 6 files changed, 33 insertions(+), 13 deletions(-) @@ -28,13 +28,12 @@ public class LocationNotifier { public static void init() { Events.ON_PARTY_MESSAGE.register((username, message) -> { if (!Floor7.displayLocationNotification || !Location.inDungeon()) return false; - Matcher matcher = PATTERN.matcher(message); + Matcher matcher = PATTERN.matcher(format(message)); if (!matcher.find()) return false; String action = matcher.group(1); - - if (Floor7.dontNotifiyForYourself && EntityUtil.isClientPlayer(username)) return false; - String location =message.substring(action.length()) .replaceAll("§.", ""); + String location = message.substring(message.indexOf(action) + action.length()).replaceAll("§.", ""); if (PositionMessages.hasBeenSent(location)) return false; + if (Floor7.dontNotifiyForYourself && EntityUtil.isClientPlayer(username)) return false; startNotification(username, " is " + action + location + "!"); return false; @@ -43,6 +42,12 @@ public class LocationNotifier { ClientTickEvents.END_CLIENT_TICK.register(client -> ticks = Math.max(ticks - 1, 0)); } + private static String format(String message) { + String strippedMessage = message.strip(); + if (strippedMessage.length() < 2) return message; + return strippedMessage.substring(0, 1).toUpperCase() + strippedMessage.substring(1).toLowerCase(); + } + public static void startNotification(String username, String message) { int color = Constants.GOLD; if (Dungeons.useClassColors) { @@ -13,6 +13,7 @@ public class PositionMessage { private final String[] checks; private final Box box; private boolean sent; + private boolean personallySent; private final int[] sections; public PositionMessage(String message, String[] checks, Box box, int[] sections) { @@ -20,6 +21,7 @@ public class PositionMessage { this.checks = checks; this.box = box; this.sent = true; + this.personallySent = true; this.sections = sections; PositionMessages.positionMessages.add(this); } @@ -36,10 +38,10 @@ public class PositionMessage { } public void tick(ClientPlayerEntity player) { - if (sent || !inAValidSection() || !inRange(player.getEntityPos())) return; - sent = true; + if (sent || personallySent || !inAValidSection() || !inRange(player.getEntityPos())) return; if (Floor7.enablePositionalMessages) { Misc.executeCommand("pc " + message); + personallySent = true; } } @@ -63,6 +65,7 @@ public class PositionMessage { public void setSent(boolean sent) { this.sent = sent; + this.personallySent = sent; } public boolean sent() { @@ -34,7 +34,7 @@ public class PositionMessages { public static void init() { ClientTickEvents.END_CLIENT_TICK.register(PositionMessages::tick); - RenderingEvents.FILLED_BLOCK.register(PositionMessages::render); + RenderingEvents.OUTLINE_ENTITY.register(PositionMessages::render); Events.ON_LOCATION_CHANGE.register(newLocation -> { disableAll(); return false; @@ -81,8 +81,9 @@ public class PositionMessages { } public static boolean hasBeenSent(String message) { + String lowered = message.toLowerCase(); for (PositionMessage positionMessage : positionMessages) { - if (positionMessage.hasBeenSent(message)) { + if (positionMessage.hasBeenSent(lowered)) { return true; } } @@ -56,8 +56,18 @@ public class DeviceNotifier { return (player.getX() >= 63 && player.getX() <= 64 && player.getY() == 127 && player.getZ() >= 35 && player.getZ() <= 36); } - public static boolean disableTitles() { - return ((Floor7.disableTitlesAtPre4 && at4thDev()) || (Floor7.disableTitlesAtSS && atSS())) && Phase.inTerminals(); + public static boolean disableTitles(Text title) { + if (!(((Floor7.disableTitlesAtPre4 && at4thDev()) || (Floor7.disableTitlesAtSS && atSS())) && Phase.inTerminals())) + return false; + + String string = title.getString(); + + if (string.equals("§eYou became a ghost!") || string.equals("§7Hopefully your teammates will be able to revive you!") || string.equals("§e§lBEING REVIVED")) { + return false; + } + + return (!string.matches("§aYou will be revived in \\ds")); + } public static boolean display() { @@ -62,13 +62,13 @@ public class InGameHudMixin implements GameHud { @Inject(method = "setTitle", at = @At("HEAD"), cancellable = true, order = 2000) public void setTitle(Text title, CallbackInfo ci) { if (TitleHider.shouldHideTitle(title)) ci.cancel(); - else if (DeviceNotifier.disableTitles()) ci.cancel(); + else if (DeviceNotifier.disableTitles(title)) ci.cancel(); } @Inject(method = "setSubtitle", at = @At("HEAD"), cancellable = true, order = 2000) public void setSubtitle(Text subtitle, CallbackInfo ci) { if (TitleHider.shouldHideTitle(subtitle)) ci.cancel(); - else if (DeviceNotifier.disableTitles()) ci.cancel(); + else if (DeviceNotifier.disableTitles(subtitle)) ci.cancel(); } @Inject(method = "renderHeldItemTooltip", at=@At("HEAD")) @@ -18,6 +18,7 @@ public class CustomEvents { //party event ClientReceiveMessageEvents.GAME.register((message, overlay) -> { String string = message.getString(); + Matcher matcher = PARTY_PATTERN.matcher(string); if (!matcher.find()) return; @@ -29,7 +30,7 @@ public class CustomEvents { String tempUsername = string.substring(PARTY_MSG_OFFSET, index).replaceAll("§.", ""); if (index + 2 >= string.length()) return; - String sentMessage = string.substring(index + 2); + String sentMessage = string.substring(index + 2).strip(); index = tempUsername.indexOf("]") + 2; if (index > -1 && index < tempUsername.length()) { |
| - made searchbar also search the lore of an item - fixed hide terminal titles hiding titles like rev title
- added dev command to test strings 查看变更src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 23 ++++++----------------- src/main/java/blade/addon/features/other/SearchBar.java | 14 +++++++++++--- src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 8 -------- src/main/java/blade/addon/mixin/InGameHudMixin.java | 6 +++--- src/main/java/blade/addon/utils/data/ItemUtil.java | 17 +++++++++++++++++ src/main/java/blade/addon/utils/debug/Debug.java | 7 +++++++ src/main/java/blade/addon/utils/dungeon/Section.java | 11 +---------- src/main/java/blade/addon/utils/interfaces/GameHud.java | 2 +- 8 files changed, 46 insertions(+), 42 deletions(-) @@ -1,12 +1,9 @@ package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Location; -import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; -import blade.addon.utils.dungeon.Section; -import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; import net.minecraft.text.Text; import java.util.regex.Matcher; @@ -16,26 +13,18 @@ public class TitleHider { private static final Pattern TERMINALS_DONE_PATTERN = Pattern.compile("^(\\w+) (activated|completed) a (terminal|device|lever)! \\((\\d)/(\\d)\\)$"); - public static void processSubtitle(SubtitleS2CPacket packet) { - if (!shouldHideTitle()) return; - if (Section.inSection(1) && DeviceNotifier.at4thDev()) return; - String string = packet.text().getString().replaceAll("§.", ""); + public static boolean shouldHideTitle(Text title) { + if (!(Floor7.hideTerminalTitles && Phase.inP3() && Location.inDungeon())) return false; + String titleString = title.getString().replaceAll("§.", ""); - - Matcher matcher = TERMINALS_DONE_PATTERN.matcher(string); + Matcher matcher = TERMINALS_DONE_PATTERN.matcher(titleString); if (matcher.find()) { String name = matcher.group(1); - if (EntityUtil.isClientPlayer(name)) { - Misc.forceTitle(Text.empty(), packet.text()); - } - //end of section msg is handled by the Section class currently + return !EntityUtil.isClientPlayer(name); } else { - Misc.forceTitle(Text.empty(), packet.text()); + return false; } - } - public static boolean shouldHideTitle() { - return Floor7.hideTerminalTitles && Phase.inP3() && Location.inDungeon(); } } @@ -1,6 +1,7 @@ package blade.addon.features.other; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.ItemUtil; import blade.addon.utils.rendering.DrawEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; @@ -10,6 +11,7 @@ import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.input.CharInput; import net.minecraft.client.input.KeyInput; import net.minecraft.client.util.Window; +import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; @@ -25,8 +27,7 @@ public class SearchBar { public static void init() { DrawEvents.INVENTORY_SLOT_AFTER.register((context, item, x, y) -> { if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar) { - String name = item.getName().getString().toLowerCase(); - if (!name.contains(searchTerm.toLowerCase()) || name.equals("air")) { + if (!matches(item)) { context.fill(x, y, x + 16, y + 16, 0xaa111111); } @@ -34,6 +35,13 @@ public class SearchBar { }); } + private static boolean matches(ItemStack item) { + String name = item.getName().getString().toLowerCase(); + if (name.equals("air")) return false; + + return (name.contains(searchTerm) || ItemUtil.containsIgnoreCaseLore(item, searchTerm)); + } + public static void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { if (!exists() || !shouldDisplay() || !ExtraOptions.toggleableSearchBar) return; searchBar.render(context, mouseX, mouseY, deltaTicks); @@ -79,7 +87,7 @@ public class SearchBar { if (window == null || textRenderer == null) return false; searchBar = new TextFieldWidget(textRenderer, (window.getScaledWidth() - SEARCH_WIDTH) / 2, SEARCH_Y, SEARCH_WIDTH, SEARCH_HEIGHT, Text.literal("")); - searchBar.setChangedListener(string -> searchTerm = string); + searchBar.setChangedListener(string -> searchTerm = string.toLowerCase()); return true; } @@ -1,6 +1,5 @@ package blade.addon.mixin; -import blade.addon.features.dungeon.f7.terms.TitleHider; import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.debug.Debug; @@ -22,7 +21,6 @@ import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; -import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; import net.minecraft.network.packet.s2c.play.TeamS2CPacket; import net.minecraft.scoreboard.Team; import net.minecraft.sound.SoundEvent; @@ -99,12 +97,6 @@ public class ClientPlayNetworkHandlerMixin { } } - @Inject(method = "onSubtitle", at = @At("HEAD")) - private void onTitle(SubtitleS2CPacket packet, CallbackInfo ci) { - TitleHider.processSubtitle(packet); - } - - @Inject(method = "onEntitySpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;playSpawnSound(Lnet/minecraft/entity/Entity;)V")) private void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo ci, @Local Entity entity) { Events.ON_ENTITY_SPAWNED.invoke(entityTrackEvent -> entityTrackEvent.onEntity(entity, world)); @@ -60,14 +60,14 @@ public class InGameHudMixin implements GameHud { } @Inject(method = "setTitle", at = @At("HEAD"), cancellable = true, order = 2000) - public void renderStatusEffectsOverLay(Text title, CallbackInfo ci) { - if (TitleHider.shouldHideTitle()) ci.cancel(); + public void setTitle(Text title, CallbackInfo ci) { + if (TitleHider.shouldHideTitle(title)) ci.cancel(); else if (DeviceNotifier.disableTitles()) ci.cancel(); } @Inject(method = "setSubtitle", at = @At("HEAD"), cancellable = true, order = 2000) public void setSubtitle(Text subtitle, CallbackInfo ci) { - if (TitleHider.shouldHideTitle()) ci.cancel(); + if (TitleHider.shouldHideTitle(subtitle)) ci.cancel(); else if (DeviceNotifier.disableTitles()) ci.cancel(); } @@ -60,6 +60,23 @@ public class ItemUtil { return false; } + public static boolean containsIgnoreCaseLore(ItemStack item, String contain) { + if (item ==null) return false; + LoreComponent lore = item.get(DataComponentTypes.LORE); + if (lore == null) return false; + + List<Text> lines = lore.lines(); + if (lines.isEmpty()) return false; + + for (Text line : lines.reversed()) { + String string = line.getString(); + if (string.toLowerCase().contains(contain.toLowerCase())) { + return true; + } + } + return false; + } + public static boolean containsNBT(ItemStack item, String contain) { NbtComponent nbt = item.get(DataComponentTypes.CUSTOM_DATA); if (nbt == null) { @@ -8,6 +8,7 @@ import blade.addon.utils.Misc; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; +import blade.addon.utils.events.Events; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.StringArgumentType; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; @@ -71,6 +72,12 @@ public class Debug { return Constants.SUCCESS; })) + .then(ClientCommandManager.literal("testString").then(ClientCommandManager.argument("message", StringArgumentType.string()).executes(context -> { + String message = StringArgumentType.getString(context, "message"); + Events.ON_GAME_MESSAGE.invoke(gameMessageEvent -> gameMessageEvent.onGameMessage(Text.literal(message))); + return Constants.SUCCESS; + }))) + .then(ClientCommandManager.literal("relic") .then(ClientCommandManager.literal("set") .then(ClientCommandManager.argument("name", StringArgumentType.string()) @@ -1,11 +1,10 @@ package blade.addon.utils.dungeon; -import blade.addon.features.dungeon.f7.terms.TitleHider; import blade.addon.utils.Constants; -import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import blade.addon.utils.events.interfaces.SectionEvent; import config.practical.hud.HUDComponent; @@ -14,7 +13,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.List; import java.util.regex.Matcher; @@ -75,9 +73,6 @@ public class Section { currentSection = 1; splits[0].start(); } else if (Phase.inGoldorTunnel()) { - if (TitleHider.shouldHideTitle()) { - Misc.forceTitle(Text.empty(), Text.literal("The Core entrance is opening!").formatted(Formatting.GREEN)); - } if (Debug.termInfo) { Misc.addChatMessage(Text.literal("Terminals ended")); } @@ -193,10 +188,6 @@ public class Section { if (string.equals("The gate has been destroyed!")) { gateBlownUp = true; - if (TitleHider.shouldHideTitle()) { - Misc.forceTitle(Text.empty(), message); - } - if (completed == total) { incrementSection(); } @@ -2,6 +2,6 @@ package blade.addon.utils.interfaces; import net.minecraft.text.Text; -public interface GameHud { +public interface GameHud { void blade_addons$forceTitle(Text title, Text subtitle); } |
- added section completion screen notification and sound查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/dungeon/f7/terms/SectionCompletion.java | 32 ++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 3 +++ src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 5 +++++ src/main/java/blade/addon/utils/config/components/Components.java | 4 ++++ src/main/java/blade/addon/utils/config/values/Floor7.java | 6 ++++++ 6 files changed, 52 insertions(+) @@ -30,6 +30,7 @@ import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; import blade.addon.features.dungeon.f7.terms.MelodyWarning; +import blade.addon.features.dungeon.f7.terms.SectionCompletion; import blade.addon.features.dungeon.f7.terms.SectionProgress; import blade.addon.features.dungeon.f7.terms.TermStartTimer; import blade.addon.features.filter.Filters; @@ -152,5 +153,6 @@ public class Bladeaddons implements ModInitializer { SelectedPetHighlight.init(); SearchBar.init(); TubaSound.init(); + SectionCompletion.init(); } } \ No newline at end of file @@ -0,0 +1,32 @@ +package blade.addon.features.dungeon.f7.terms; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +public class SectionCompletion { + + private static long prevTime = 0; + + public static void init() { + Events.ON_SECTION_CHANGE.register(() -> { + Misc.sendSound(Floor7.sectionChangeSound); + prevTime = System.currentTimeMillis(); + return false; + }); + } + + public static boolean display() { + return System.currentTimeMillis() - prevTime < 1000 && Floor7.sectionCompletionNotification; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, Text.literal("Section completed!").formatted(Formatting.GREEN)); + } + +} @@ -182,6 +182,9 @@ public class Config { goldor.add(new ConfigBool(Text.literal("Melody warning notification"), () -> Floor7.notifiyMelody, bool -> Floor7.notifiyMelody = bool)); goldor.add(new ConfigBool(Text.literal("Send terminal time stamps"), () -> Floor7.terminalTimeStamps, bool -> Floor7.terminalTimeStamps = bool)); goldor.add(new ConfigBool(Text.literal("Display section progress"), () -> Floor7.showSectionProgress, bool -> Floor7.showSectionProgress = bool)); + goldor.add(new ConfigBool(Text.literal("Section completion notification"), () -> Floor7.sectionCompletionNotification, bool -> Floor7.sectionCompletionNotification = bool)); + goldor.add(new ConfigSound(Text.literal("Section complete sound"), Floor7.sectionChangeSound, 2, 2, true)); + floor7.add(goldor); ConfigSection titles = new ConfigSection(Text.literal("Terminal titles")); @@ -6,6 +6,7 @@ import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; import blade.addon.features.dungeon.f7.terms.MelodyWarning; import blade.addon.features.dungeon.f7.storm.PillarExplode; import blade.addon.features.dungeon.f7.terms.DeviceNotifier; +import blade.addon.features.dungeon.f7.terms.SectionCompletion; import blade.addon.features.notifications.Notifications; import blade.addon.features.other.ArrowSwapper; import blade.addon.features.other.SelectedPet; @@ -38,6 +39,8 @@ public class CombinedScreenNotifications { return true; } else if (ArrowSwapper.displayNotification()) { return true; + } else if (SectionCompletion.display()) { + return true; } return false; } @@ -61,6 +64,8 @@ public class CombinedScreenNotifications { SelectedPet.renderNotification(component, context); } else if (ArrowSwapper.displayNotification()) { ArrowSwapper.renderNotification(component, context); + } else if (SectionCompletion.display()) { + SectionCompletion.render(component, context); }else { RenderUtils.drawCenteredText(context, component, Text.literal("Some notification")); } @@ -20,6 +20,7 @@ import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; import blade.addon.features.dungeon.f7.terms.MelodyWarning; import blade.addon.features.dungeon.f7.terms.DeviceNotifier; +import blade.addon.features.dungeon.f7.terms.SectionCompletion; import blade.addon.features.dungeon.f7.terms.SectionProgress; import blade.addon.features.dungeon.f7.terms.TermStartTimer; import blade.addon.features.item.HeldItemToolTip; @@ -149,4 +150,7 @@ public class Components { @ConfigValue public static HUDComponent arrowSwapDisplay = new HUDComponent(0, 0, 100, 10, 1, "Selected arrow title", ArrowSwapper::displayNotification, ArrowSwapper::renderNotification, () -> ExtraOptions.arrowSwapNotification && !Dungeons.combineScreenNotifications); + + @ConfigValue + public static HUDComponent sectionCompletionDisplay = new HUDComponent(0, 0, NOTIFICATION_WIDTH, 10, 1, "Section completion", SectionCompletion::display, SectionCompletion::render, () -> Floor7.sectionCompletionNotification && !Dungeons.combineScreenNotifications); } @@ -156,4 +156,10 @@ public class Floor7 { @ConfigValue public static boolean capitalizeHealthNumbers = true; + + @ConfigValue + public static boolean sectionCompletionNotification = false; + + @ConfigValue + public static SoundData sectionChangeSound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0, 1); } |
| - made it so searchbar ignores capitalization - added hide none stared nametags
- added old tuba sound 查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/highlight/MobHighlight.java | 24 +++++++++++++++++++++++- src/main/java/blade/addon/features/other/SearchBar.java | 5 +++-- src/main/java/blade/addon/features/sound/TubaSound.java | 32 ++++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/EntityRenderManagerMixin.java | 7 +++++++ src/main/java/blade/addon/utils/config/Config.java | 3 +++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 +++ 7 files changed, 73 insertions(+), 3 deletions(-) @@ -55,6 +55,7 @@ import blade.addon.features.other.SearchBar; import blade.addon.features.other.SelectedPet; import blade.addon.features.other.StunWaypoint; import blade.addon.features.sound.BonzoSound; +import blade.addon.features.sound.TubaSound; import blade.addon.utils.Commands; import blade.addon.utils.Keybinds; import blade.addon.utils.Location; @@ -150,5 +151,6 @@ public class Bladeaddons implements ModInitializer { ProtectItem.init(); SelectedPetHighlight.init(); SearchBar.init(); + TubaSound.init(); } } \ No newline at end of file @@ -55,6 +55,7 @@ public class MobHighlight { private static final int LEATHER_BOOTS_ID = Item.getRawId(Items.LEATHER_BOOTS); private static final ConcurrentHashMap<Integer, Entity> foundEntities = new ConcurrentHashMap<>(); + public static final ConcurrentLinkedQueue<ArmorStandEntity> nonStaredTags = new ConcurrentLinkedQueue<>(); public static final ConcurrentLinkedQueue<DataHolder> savedEntities = new ConcurrentLinkedQueue<>(); public static boolean dontRenderHighlight = false; @@ -76,6 +77,9 @@ public class MobHighlight { @ConfigValue public static int outlineWidth = 4; + @ConfigValue + public static boolean hideNoneStaredNameTags = false; + @ConfigValue public static int starFilledColor = 0xff00ff00; @ConfigValue @@ -141,6 +145,8 @@ public class MobHighlight { Events.ON_LOCATION_CHANGE.register(newLocation -> { savedEntities.clear(); + foundEntities.clear(); + nonStaredTags.clear(); return false; }); @@ -155,6 +161,9 @@ public class MobHighlight { int id = entity.getId(); savedEntities.removeIf(dataHolder -> dataHolder.entity == entity); foundEntities.remove(id); + if (entity instanceof ArmorStandEntity) { + nonStaredTags.remove(entity); + } }); RenderingEvents.FILLED_ENTITY.register(MobHighlight::renderFilled); @@ -163,7 +172,12 @@ public class MobHighlight { private static void testArmorStand(ArmorStandEntity armorStand) { MobType type = getType(armorStand); - if (type == null) return; + if (type == null) { + if (isGeneralStaredMob(armorStand)) { + nonStaredTags.add(armorStand); + } + return; + } int idOffset = getIdOffset(armorStand); if (idOffset < 0) return; @@ -210,6 +224,14 @@ public class MobHighlight { return false; } + public static boolean isGeneralStaredMob(ArmorStandEntity armorStand) { + Text text = armorStand.getCustomName(); + if (text == null) return false; + String name = text.getString(); + return name.contains("Lurker") || name.contains("Dreadlord") || name.contains("Souleater") || name.contains("Zombie") || name.contains("Skeleton") || name.contains("Skeletor") + || name.contains("Sniper") || name.contains("Spider") || name.contains("Fel") || isTankMob(name) || isMiniBoss(name); + } + public static boolean isTankMob(String name) { return name.contains("Zombie Commander") || name.contains("Zombie Lord") || name.contains("Skeleton Lord") || name.contains("Withermancer") || name.contains("Super Archer"); } @@ -25,10 +25,11 @@ public class SearchBar { public static void init() { DrawEvents.INVENTORY_SLOT_AFTER.register((context, item, x, y) -> { if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar) { - String name = item.getName().getString(); - if (!name.contains(searchTerm) || name.equals("Air")) { + String name = item.getName().getString().toLowerCase(); + if (!name.contains(searchTerm.toLowerCase()) || name.equals("air")) { context.fill(x, y, x + 16, y + 16, 0xaa111111); } + } }); } @@ -0,0 +1,32 @@ +package blade.addon.features.sound; + +import blade.addon.utils.Constants; +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.ItemUtil; +import blade.addon.utils.events.Events; +import net.minecraft.entity.passive.WolfSoundVariants; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Identifier; + +public class TubaSound { + + private static final SoundEvent SOUND = SoundEvents.WOLF_SOUNDS.get(WolfSoundVariants.Type.CLASSIC).deathSound().value(); + private static final SoundEvent TUBA_SOUND = SoundEvent.of(Identifier.of(Constants.NAMESPACE, "wolf-howl")); + + + public static void init() { + Events.ON_SOUND.register((soundEvent, volume, pitch) -> { + if (volume != 0.5 || soundEvent != SOUND) return false; + if (!ItemUtil.isHolding("Tuba")) return false; + + if (ExtraOptions.oldTubaSound) { + Misc.sendSound(TUBA_SOUND, volume, pitch); + return true; + } + return false; + }); + } + +} @@ -12,6 +12,7 @@ import net.minecraft.client.render.Frustum; import net.minecraft.client.render.entity.EntityRenderManager; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.passive.SheepEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.FishingBobberEntity; @@ -64,5 +65,11 @@ public class EntityRenderManagerMixin { } } + if (entity instanceof ArmorStandEntity armorStand && MobHighlight.hideNoneStaredNameTags) { + if (MobHighlight.nonStaredTags.contains(armorStand)) { + cir.setReturnValue(false); + } + } + } } @@ -251,6 +251,8 @@ public class Config { highlight.add(new ConfigDouble(Text.literal("Extra Wither Width"), () -> MobHighlight.witherExtraWidth, num -> MobHighlight.witherExtraWidth = num, 0.1, 0, 1.5)); highlight.add(new ConfigInt(Text.literal("Outline Width"), () -> MobHighlight.outlineWidth, num -> MobHighlight.outlineWidth = num, 1, 1, 10)); highlight.add(new ConfigOptions<>(Text.literal("Highlight mode"), MobHighlight.HighlightType.values(), () -> MobHighlight.currentHighlight, type -> MobHighlight.currentHighlight = type)); + highlight.add(new ConfigBool(Text.literal("Hide none stared nametags"), () -> MobHighlight.hideNoneStaredNameTags, bool -> MobHighlight.hideNoneStaredNameTags = bool)); + highlight.add(new ConfigColor(Text.literal("Star mob filled color"), () -> MobHighlight.starFilledColor, color -> MobHighlight.starFilledColor = color, "star-filled", true)); highlight.add(new ConfigColor(Text.literal("Star mob outline color"), () -> MobHighlight.starOutlineColor, color -> MobHighlight.starOutlineColor = color, "star-outline", true)); highlight.add(new ConfigColor(Text.literal("Tank mob filled color"), () -> MobHighlight.tankFilledColor, color -> MobHighlight.tankFilledColor = color, "tank-filled", true)); @@ -301,6 +303,7 @@ public class Config { sound.add(new ConfigBool(Text.literal("Disable \"on cooldown\" sound"), () -> ExtraOptions.disableAbilityCooldownSound, bool -> ExtraOptions.disableAbilityCooldownSound = bool)); sound.add(new ConfigBool(Text.literal("Disable bonzo sound"), () -> ExtraOptions.disableBonzoSound, bool -> ExtraOptions.disableBonzoSound = bool)); sound.add(new ConfigBool(Text.literal("Old bonzo sound"), () -> ExtraOptions.oldBonzoSound, bool -> ExtraOptions.oldBonzoSound = bool)); + sound.add(new ConfigBool(Text.literal("Old tuba sound"), () -> ExtraOptions.oldTubaSound, bool -> ExtraOptions.oldTubaSound = bool)); extra.add(sound); ConfigSection rag = new ConfigSection(Text.literal("Ragnarock")); @@ -126,4 +126,7 @@ public class ExtraOptions { @ConfigValue public static boolean copyChatFeedback = false; + + @ConfigValue + public static boolean oldTubaSound = false; } |
| - fixed leaporder not working thanks to hypixel randomly adding color codes - added a toggle to remove the "mask" part from the text for the invincibility display 查看变更src/main/java/blade/addon/features/dungeon/LeapOrder.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 13 +++++++++---- src/main/java/blade/addon/utils/config/Config.java | 1 + src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ 4 files changed, 14 insertions(+), 5 deletions(-) @@ -40,7 +40,7 @@ public class LeapOrder { Scoreboard scoreboard = world.getScoreboard(); for (Team team : scoreboard.getTeams()) { - String teamStr = team.getPrefix().getString() + team.getSuffix().getString(); + String teamStr = (team.getPrefix().getString() + team.getSuffix().getString()).replaceAll("§.", ""); Matcher matcher = PATTERN.matcher(teamStr); if (matcher.find()) { DungeonClass dungeonClass = getClass(matcher.group(1)); @@ -140,7 +140,7 @@ public class InvincibilityTimer { if (ticks > 0) { return Text.literal("§c" + string).append(formatTimer(ticks)); } else { - String color = isOn ? "§e" : "§a"; + String color = isOn ? "§e" : "§a"; return Text.literal(color + string); } } @@ -154,7 +154,7 @@ public class InvincibilityTimer { } private static void drawSprite(DrawContext context, Identifier identifier, int x, int y, boolean isOn, int ticks, Text timerText) { - int color = (ticks > 0? Constants.RED: isOn? Constants.YELLOW: Constants.GREEN); + int color = (ticks > 0 ? Constants.RED : isOn ? Constants.YELLOW : Constants.GREEN); context.fill(x, y, x + SPRITE_SIZE, y + SPRITE_SIZE, color); context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, identifier, x, y, SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); if (ticks > 0) { @@ -200,8 +200,13 @@ public class InvincibilityTimer { drawSprite(context, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, spiritMaskOn, spiritMaskTicks, formatTimer(spiritMaskTicks)); drawSprite(context, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); } else { - context.drawText(MinecraftClient.getInstance().textRenderer, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); - context.drawText(MinecraftClient.getInstance().textRenderer, getText(spiritMaskTicks, spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); + if (Dungeons.removeMaskPart) { + context.drawText(MinecraftClient.getInstance().textRenderer, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo "), x, y, 0xffffffff, true); + context.drawText(MinecraftClient.getInstance().textRenderer, getText(spiritMaskTicks, spiritMaskOn, "Spirit "), x, y + TEXT_HEIGHT, 0xffffffff, true); + } else { + context.drawText(MinecraftClient.getInstance().textRenderer, getText(bonzoMaskTicks, bonzoMaskOn, "Bonzo's Mask "), x, y, 0xffffffff, true); + context.drawText(MinecraftClient.getInstance().textRenderer, getText(spiritMaskTicks, spiritMaskOn, "Spirit Mask "), x, y + TEXT_HEIGHT, 0xffffffff, true); + } context.drawText(MinecraftClient.getInstance().textRenderer, getText(phoenixTicks, phoenixOn, "Phoenix "), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); } } @@ -80,6 +80,7 @@ public class Config { invincibility.add(new ConfigBool(Text.literal("Show title on proc"), () -> Dungeons.showProcTitle, bool -> Dungeons.showProcTitle = bool)); invincibility.add(new ConfigBool(Text.literal("Invincibility duration"), () -> Dungeons.InvincibilityDuration, bool -> Dungeons.InvincibilityDuration = bool)); invincibility.add(new ConfigBool(Text.literal("Duration changing color"), () -> Dungeons.useStatusColorForInvincibility, bool -> Dungeons.useStatusColorForInvincibility = bool)); + invincibility.add(new ConfigBool(Text.literal("Remove \"Mask\" in the text"), () -> Dungeons.removeMaskPart, bool -> Dungeons.removeMaskPart = bool)); dungeons.add(invincibility); ConfigSection classColors = new ConfigSection(Text.literal("Class Colors")); @@ -136,4 +136,7 @@ public class Dungeons { @ConfigValue public static boolean bossHealthNumbers = false; + + @ConfigValue + public static boolean removeMaskPart = true; } |
- added a toggle to temporarily disable protectitems - bumped version查看变更gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -13,7 +13,7 @@ loader_version=0.18.4 loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=2.3.4 +mod_version=2.3.5 maven_group=blade.addon archives_base_name=blade-addons |
- added a toggle to temporarily disable protectitems - bumped version查看变更src/main/java/blade/addon/features/item/ProtectItem.java | 4 +++- src/main/java/blade/addon/utils/config/Config.java | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) @@ -36,6 +36,8 @@ public class ProtectItem { @ConfigValue public static HashSet<String> protectedItems = new HashSet<>(); + public static boolean stopProtectItem = false; + public static void init() { DrawEvents.INVENTORY_SLOT_BEFORE.register(ProtectItem::draw); DrawEvents.HUD_SLOT_BEFORE.register(ProtectItem::draw); @@ -69,7 +71,7 @@ public class ProtectItem { } public static boolean protect(ItemStack stack) { - + if (stopProtectItem) return false; String uuid = ItemUtil.getUuid(stack); //TODO: add smth for non uuid items @@ -6,6 +6,7 @@ import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.filter.FilterList; import blade.addon.features.highlight.MobHighlight; +import blade.addon.features.item.ProtectItem; import blade.addon.features.other.DianaNotifier; import blade.addon.features.notifications.NotificationList; import blade.addon.utils.config.components.Components; @@ -291,6 +292,7 @@ public class Config { extra.add(new ConfigBool(Text.literal("Display selected arrow"), () -> ExtraOptions.displayCurrentArrow, bool -> ExtraOptions.displayCurrentArrow = bool)); extra.add(new ConfigBool(Text.literal("Title on arrow swap"), () -> ExtraOptions.arrowSwapNotification, bool -> ExtraOptions.arrowSwapNotification = bool)); extra.add(new ConfigBool(Text.literal("Toggleable searchbar (ctrl + f)"), () -> ExtraOptions.toggleableSearchBar, bool -> ExtraOptions.toggleableSearchBar = bool)); + extra.add(new ConfigBool(Text.literal("Disable protect item (resets on launch)"), () -> ProtectItem.stopProtectItem, bool -> ProtectItem.stopProtectItem = bool)); //extra.add(new ConfigBool(Text.literal("Kuudra stun waypoint"), () -> ExtraOptions.stunWaypoint, bool -> ExtraOptions.stunWaypoint = bool)); |
fixed selected pet highlight in menu not being toggleable查看变更src/main/java/blade/addon/features/item/SelectedPetHighlight.java | 2 ++ 1 file changed, 2 insertions(+) @@ -17,6 +17,8 @@ public class SelectedPetHighlight { } private static void draw(DrawContext context, ItemStack stack, int x, int y) { + if (!ExtraOptions.highlightSelectedPet) return; + PetHolder holder = (PetHolder) (Object) stack; assert holder != null; |
- added an option to capitalize health displays like dragon health and boss bar health - added an option to send a message in chat when you copy a chat message - added new icon查看变更src/main/java/blade/addon/mixin/ChatScreenMixin.java | 5 +++++ src/main/java/blade/addon/utils/config/Config.java | 2 ++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 +++ src/main/java/blade/addon/utils/config/values/Floor7.java | 2 ++ src/main/java/blade/addon/utils/rendering/RenderUtils.java | 13 ++++++++++--- src/main/resources/assets/blade-addons/icon.png | Bin 0 -> 2285 bytes 6 files changed, 22 insertions(+), 3 deletions(-) @@ -1,5 +1,6 @@ package blade.addon.mixin; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.data.TextUtil; import net.minecraft.client.MinecraftClient; @@ -58,6 +59,10 @@ public class ChatScreenMixin extends Screen { } mc.keyboard.setClipboard(string); + + if (ExtraOptions.copyChatFeedback) { + Misc.addChatMessage(Text.literal("Copied chat message")); + } } @Unique @@ -138,6 +138,7 @@ public class Config { ConfigCategory floor7 = new ConfigCategory("Floor 7"); floor7.add(new ConfigBool(Text.literal("Combine tick timers"), () -> Floor7.combineTickTimers, bool -> Floor7.combineTickTimers = bool)); floor7.add(new ConfigBool(Text.literal("Enable player leap count"), () -> Floor7.leapNotifications, bool -> Floor7.leapNotifications = bool)); + floor7.add(new ConfigBool(Text.literal("Capitalize health numbers"), () -> Floor7.capitalizeHealthNumbers, bool -> Floor7.capitalizeHealthNumbers = bool)); ConfigSection waypoints = new ConfigSection(Text.literal("Waypoints")); waypoints.add(new ConfigBool(Text.literal("Enable boss waypoints"), () -> Floor7.enableBossWaypoints, bool -> Floor7.enableBossWaypoints = bool)); @@ -311,6 +312,7 @@ public class Config { copyChat.add(new ConfigBool(Text.literal("remove color codes"), () -> ExtraOptions.removeColorCodes, bool -> ExtraOptions.removeColorCodes = bool)); copyChat.add(new ConfigBool(Text.literal("replace format char with &"), () -> ExtraOptions.replaceColorChars, bool -> ExtraOptions.replaceColorChars = bool)); copyChat.add(new ConfigBool(Text.literal("copy line only"), () -> ExtraOptions.copyLineOnly, bool -> ExtraOptions.copyLineOnly = bool)); + copyChat.add(new ConfigBool(Text.literal("Send feedback msg in chat on copied msg"), () -> ExtraOptions.copyChatFeedback, bool -> ExtraOptions.copyChatFeedback = bool)); extra.add(copyChat); ConfigSection pets = new ConfigSection(Text.literal("Pets")); @@ -123,4 +123,7 @@ public class ExtraOptions { @ConfigValue public static boolean toggleableSearchBar = true; + + @ConfigValue + public static boolean copyChatFeedback = false; } @@ -154,4 +154,6 @@ public class Floor7 { @ConfigValue public static boolean makeGoldorTickUp = true; + @ConfigValue + public static boolean capitalizeHealthNumbers = true; } @@ -2,6 +2,7 @@ package blade.addon.utils.rendering; import blade.addon.utils.Constants; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Floor7; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; @@ -68,7 +69,7 @@ public class RenderUtils { RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); } - public static void drawPrefixedTimer(HUDComponent component, DrawContext context, String prefix, int num) { + public static void drawPrefixedTimer(HUDComponent component, DrawContext context, String prefix, int num) { drawPrefixedText(component, context, prefix, Constants.DECIMAL_FORMAT.format(num * Constants.TICK_DURATION) + "s"); } @@ -117,12 +118,18 @@ public class RenderUtils { } - - public static String formatHealth(float health) { + public static String formatHealth(float health) { + if (Floor7.capitalizeHealthNumbers) { if (health >= 1e9) return String.format("%.1fB", health / 1e9); if (health >= 1e6) return String.format("%.1fM", health / 1e6); if (health >= 1e3) return String.format("%.1fK", health / 1e3); return health + ""; + } else { + if (health >= 1e9) return String.format("%.1fb", health / 1e9); + if (health >= 1e6) return String.format("%.1fm", health / 1e6); + if (health >= 1e3) return String.format("%.1fk", health / 1e3); + return health + ""; } + } } |
| Merge pull request #3 from Ryflyy/capitalize-boss-bar capitalize formatting of boss bar letters 查看变更src/main/java/blade/addon/utils/rendering/RenderUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) |
| - added and renamed goldor countdown toggle - added f1-7 and m1-7 commands like "/f7" - added selectable color for selected pet highlight - added toggleable pet level for hud display - added 1.8.9 like fishing bobber (its still a good bit off) - added an openable searchbar with ctrl + f - hopefully fixed copy chat copying format in the wrong order making them not directly compatible with chat Notifications
- fixed terminal timestamps breaking term splits
- fixed healer getting sent purple prio sometimes
- fix class not getting detected
- fixed selected pet highlight not working for some people 查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 14 ++++++++++ src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 78 ++++++++++++++++++++++++++++--------------------------- src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 17 ++++++------ src/main/java/blade/addon/features/dungeon/f7/dragons/Dragon.java | 11 +++++++- src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskHighlight.java | 10 ++++++- src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 8 ++++-- src/main/java/blade/addon/features/filter/FilterList.java | 20 ++++++++++++-- src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 13 +++++++--- src/main/java/blade/addon/features/item/ProtectItem.java | 12 +++++++-- src/main/java/blade/addon/features/item/SelectedPetHighlight.java | 14 +++++++--- src/main/java/blade/addon/features/item/StarCountHighlight.java | 12 ++++++++- src/main/java/blade/addon/features/notifications/Notifications.java | 6 +++++ src/main/java/blade/addon/features/other/SearchBar.java | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/SelectedPet.java | 39 ++++++++++++++++++++++------ src/main/java/blade/addon/features/other/StunWaypoint.java | 62 ++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/ClientConnectionMixin.java | 12 ++++----- src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 22 ++++++++++++++++ src/main/java/blade/addon/mixin/EntityRenderManagerMixin.java | 15 +++++++++++ src/main/java/blade/addon/mixin/HandledScreenMixin.java | 62 +++++++++++++++++++------------------------- src/main/java/blade/addon/mixin/InGameHudMixin.java | 17 +++--------- src/main/java/blade/addon/mixin/InventoryScreenMixin.java | 2 ++ src/main/java/blade/addon/mixin/KeyboardMixin.java | 26 +++++++++++++++++++ src/main/java/blade/addon/mixin/MinecraftClientMixin.java | 4 +-- src/main/java/blade/addon/utils/Commands.java | 12 +++++++++ src/main/java/blade/addon/utils/Location.java | 103 +++++++++++++++++++++++++++++++++++++++++++++++-------------------------- src/main/java/blade/addon/utils/config/Config.java | 10 +++++-- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 12 +++++++++ src/main/java/blade/addon/utils/config/values/Floor7.java | 3 +++ src/main/java/blade/addon/utils/config/values/Visual.java | 3 +++ src/main/java/blade/addon/utils/data/TextUtil.java | 51 ++++++++++++++++++------------------ src/main/java/blade/addon/utils/debug/Debug.java | 47 +++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 31 ++++++++++++++++++---- src/main/java/blade/addon/utils/dungeon/Section.java | 7 ++--- src/main/java/blade/addon/utils/events/Events.java | 3 ++- src/main/java/blade/addon/utils/events/interfaces/BlockInteractionEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/ParticleEvent.java | 4 +-- src/main/java/blade/addon/utils/rendering/DrawEvents.java | 10 +++++++ src/main/java/blade/addon/utils/rendering/DrawHandler.java | 22 ++++++++++++++++ src/main/java/blade/addon/utils/rendering/drawevents/SlotEvent.java | 10 +++++++ src/main/resources/assets/blade-addons/Blade-addons-picture.png | Bin 128048 -> 0 bytes src/main/resources/assets/blade-addons/icon.png | Bin 3510 -> 0 bytes src/main/resources/blade-addons.mixins.json | 1 + src/main/resources/fabric.mod.json | 2 +- 44 files changed, 698 insertions(+), 207 deletions(-) @@ -13,7 +13,7 @@ loader_version=0.18.4 loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=2.3.3 +mod_version=2.3.4 maven_group=blade.addon archives_base_name=blade-addons @@ -12,6 +12,7 @@ import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.BossWaypoints; +import blade.addon.features.dungeon.f7.invincibility.MaskHighlight; import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; import blade.addon.features.dungeon.f7.storm.DistanceToLedge; import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; @@ -39,6 +40,10 @@ import blade.addon.features.highlight.SheepHighlight; import blade.addon.features.highlight.TeammateHighlight; import blade.addon.features.highlight.WitherHighlight; import blade.addon.features.item.DropAnimation; +import blade.addon.features.item.ItemRarityHighlight; +import blade.addon.features.item.ProtectItem; +import blade.addon.features.item.SelectedPetHighlight; +import blade.addon.features.item.StarCountHighlight; import blade.addon.features.notifications.Notifications; import blade.addon.features.other.ArrowSwapper; import blade.addon.features.other.CompactHoppity; @@ -46,7 +51,9 @@ import blade.addon.features.other.DianaNotifier; import blade.addon.features.other.KickedTimer; import blade.addon.features.other.PracticeSS; import blade.addon.features.other.RagDisplay; +import blade.addon.features.other.SearchBar; import blade.addon.features.other.SelectedPet; +import blade.addon.features.other.StunWaypoint; import blade.addon.features.sound.BonzoSound; import blade.addon.utils.Commands; import blade.addon.utils.Keybinds; @@ -136,5 +143,12 @@ public class Bladeaddons implements ModInitializer { DragonHealth.init(); MaxorStun.init(); ArrowSwapper.init(); + StarCountHighlight.init(); + MaskHighlight.init(); + StunWaypoint.init(); + ItemRarityHighlight.init(); + ProtectItem.init(); + SelectedPetHighlight.init(); + SearchBar.init(); } } \ No newline at end of file @@ -26,6 +26,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; @@ -154,54 +155,55 @@ public class RelicTimer { }); - Events.ON_BLOCK_INTERACTION.register((result, itemStack) -> { - if ((!Location.inDungeon() || !Phase.inP5())) return false; + Events.ON_BLOCK_INTERACTION.register(RelicTimer::blockInteraction); + RenderingEvents.FILLED_BLOCK.register(RelicTimer::worldRender); - if (pickedupRelic == null) return false; + } - BlockPos pos = result.getBlockPos(); + private static boolean blockInteraction(BlockHitResult result, ItemStack itemStack) { + if ((!Location.inDungeon() || !Phase.inP5())) return false; - if (!isARelicPos(pos)) return false; + if (pickedupRelic == null) return false; - //skyblock menu check is there incase the item doesnt get updated - if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu")) { - if (Floor7.blockIncorrectRelicPlace) { - Debug.sendDebugMessage(Text.literal("Item: " + itemStack.getName())); - Misc.addChatMessage(Text.literal("Blocked a weird click")); - return true; - } else { - return false; - } - } + BlockPos pos = result.getBlockPos(); - if (clickedRelic(pickedupRelic, pos)) { - if (Floor7.enableRelicPlaceTime) { - MutableText text = Text.literal("The ").formatted(Formatting.GREEN) - .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) - .append(" relic was placed in ").formatted(Formatting.GREEN); - - switch (pickedupRelic) { - case RED -> PersonalBests.redRelicTime.testNewTime(text, phaseStartTime); - case ORANGE -> PersonalBests.orangeRelicTime.testNewTime(text, phaseStartTime); - case BLUE -> PersonalBests.blueRelicTime.testNewTime(text, phaseStartTime); - case GREEN -> PersonalBests.greenRelicTime.testNewTime(text, phaseStartTime); - case PURPLE -> PersonalBests.purpleRelicTime.testNewTime(text, phaseStartTime); - } + if (!isARelicPos(pos)) return false; - } - pickedupRelic = null; + //skyblock menu check is there incase the item doesnt get updated + if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu")) { + if (Floor7.blockIncorrectRelicPlace) { + Debug.sendDebugMessage(Text.literal("Name: " + itemStack.getName() + " Item: " + itemStack)); + Misc.addChatMessage(Text.literal("Blocked a weird click")); + return true; } else { - if (Floor7.blockIncorrectRelicPlace) { - Debug.sendDebugMessage(Text.literal("Relic: " + pickedupRelic)); - Misc.addChatMessage(Text.literal("incorrect click!")); - return true; - } + return false; } - return false; - }); + } - RenderingEvents.FILLED_BLOCK.register(RelicTimer::worldRender); + if (clickedRelic(pickedupRelic, pos)) { + if (Floor7.enableRelicPlaceTime) { + MutableText text = Text.literal("The ").formatted(Formatting.GREEN) + .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) + .append(" relic was placed in ").formatted(Formatting.GREEN); + + switch (pickedupRelic) { + case RED -> PersonalBests.redRelicTime.testNewTime(text, phaseStartTime); + case ORANGE -> PersonalBests.orangeRelicTime.testNewTime(text, phaseStartTime); + case BLUE -> PersonalBests.blueRelicTime.testNewTime(text, phaseStartTime); + case GREEN -> PersonalBests.greenRelicTime.testNewTime(text, phaseStartTime); + case PURPLE -> PersonalBests.purpleRelicTime.testNewTime(text, phaseStartTime); + } + } + pickedupRelic = null; + } else { + if (Floor7.blockIncorrectRelicPlace) { + Debug.sendDebugMessage(Text.literal("Relic: " + pickedupRelic)); + Misc.addChatMessage(Text.literal("incorrect click!")); + return true; + } + } + return false; } private static boolean isARelicPos(BlockPos pos) { @@ -2,6 +2,7 @@ package blade.addon.features.dungeon.f7.dragons; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; @@ -9,6 +10,7 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; import net.minecraft.particle.ParticleTypes; import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; public class DragSpawnTimer { @@ -34,13 +36,10 @@ public class DragSpawnTimer { private static int tick = 0; public static void init() { - Events.ON_PACKET.register(packet -> { - if (packet instanceof ParticleS2CPacket particle) { - if (!validParticle(particle)) return false; - Dragon dragon = Dragon.getDragon(particle.getX(), particle.getY(), particle.getZ()); - testDragon(dragon); - } - + Events.ON_PARTICLE.register(packet -> { + if (!validParticle(packet)) return false; + Dragon dragon = Dragon.getDragon(packet.getX(), packet.getY(), packet.getZ()); + testDragon(dragon); return false; }); @@ -63,6 +62,7 @@ public class DragSpawnTimer { if (dragon == Dragon.NONE) return; if (currentDragon == Dragon.NONE) { + Debug.sendDebugMessage(Text.literal("Drag: " + currentDragon.name())); currentDragon = dragon; tick = SPAWN_DURATION; @@ -70,7 +70,8 @@ public class DragSpawnTimer { Misc.sendSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0.75f, 1); } - } else if (currentDragon != dragon && !hasDoneSplit) { + } else if (currentDragon != dragon && !hasDoneSplit) { + Debug.sendDebugMessage(Text.literal("comparing: " + currentDragon.name() + " and " + dragon.name())); currentDragon = Dragon.getPrio(dragon, currentDragon); hasDoneSplit = true; } @@ -2,7 +2,7 @@ package blade.addon.features.dungeon.f7.dragons; import blade.addon.utils.dungeon.DungeonClass; -public enum Dragon { +public enum Dragon { PURPLE(0xffff55ff, 0, 4), BLUE(0xff55ffff, 1, 3), RED(0xffff5555, 2, 2), @@ -43,7 +43,16 @@ public enum Dragon { } public static Dragon getPrio(Dragon dragon1, Dragon dragon2) { + if (DungeonClass.isArchTeam()) { + if (DungeonClass.isClass(DungeonClass.HEALER)) { + if (dragon1 == Dragon.PURPLE) { + return dragon2; + } else if (dragon2 == Dragon.PURPLE) { + return dragon1; + } + } + if (dragon1.archPrio < dragon2.archPrio) { return dragon1; } else { @@ -1,6 +1,8 @@ package blade.addon.features.dungeon.f7.invincibility; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.data.ItemUtil; +import blade.addon.utils.rendering.DrawEvents; import net.minecraft.client.gui.DrawContext; import net.minecraft.item.ItemStack; @@ -8,7 +10,13 @@ public class MaskHighlight { private static final int COLOR = 0xbb666666; - public static void draw(DrawContext context, ItemStack stack, int x, int y) { + public static void init() { + DrawEvents.INVENTORY_SLOT_AFTER.register(MaskHighlight::draw); + } + + private static void draw(DrawContext context, ItemStack stack, int x, int y) { + if (!Dungeons.maskHighlight) return; + MaskHolder holder = (MaskHolder) (Object) stack; assert holder != null; @@ -28,15 +28,19 @@ public class GoldorTickTimer { } public static boolean display() { - return Floor7.enableGoldorTickTimer && Location.inDungeon() && Phase.inTerminals(); + return Floor7.enableGoldorTickTimer && Location.inDungeon() && Phase.inTerminals(); } public static void render(HUDComponent component, DrawContext context) { double num = tick * Constants.TICK_DURATION; double mod = num % 3; - int color = (mod < 1? Constants.GREEN: mod < 2? Constants.ORANGE: Constants.RED); + if (Floor7.inDeathTicks && !Floor7.makeGoldorTickUp) mod = 3.0 - mod; if (Floor7.inDeathTicks) num = mod; + System.out.println(num); + + int color = (mod < 1 ? Constants.GREEN : mod < 2 ? Constants.ORANGE : Constants.RED); + RenderUtils.drawTimer(component, context, num, color); } } @@ -9,6 +9,7 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.Window; import net.minecraft.text.Text; +import net.minecraft.util.Pair; import org.joml.Matrix3x2fStack; public class FilterList extends Screen { @@ -18,6 +19,10 @@ public class FilterList extends Screen { private static final int TITLE_Y_OFFSET = 20; private static final int BUTTON_HEIGHT = 30; + private static final int BUTTON_WIDTH = 100; + + private static final Text INFO_TEXT = Text.literal("To add a filter, input a regex which would match the word fully. I'd highly recommend using regex101.com to create them."); + private final Screen parent; private final ConfigScroll scroll; @@ -30,8 +35,9 @@ public class FilterList extends Screen { parent = client.currentScreen; Window window = client.getWindow(); - addFilter = ButtonWidget.builder(Text.literal("Add Filter"), this::addFilter).position((window.getScaledWidth() - Constants.WIDGET_WIDTH) / 2, TITLE_Y_OFFSET + 16).width(100).build(); - scroll = new ConfigScroll(0, BUTTON_HEIGHT + TITLE_Y_OFFSET + 16, window.getScaledWidth(), window.getScaledHeight() - BUTTON_HEIGHT, Constants.WIDGET_WIDTH); + Pair<Integer, Integer> pos = getButtonPos(); + addFilter = ButtonWidget.builder(Text.literal("Add Filter"), this::addFilter).position(pos.getLeft(), pos.getRight()).width(BUTTON_WIDTH).build(); + scroll = new ConfigScroll(0, BUTTON_HEIGHT + TITLE_Y_OFFSET + 16, window.getScaledWidth(), window.getScaledHeight() - BUTTON_HEIGHT, Constants.WIDGET_WIDTH); } @Override @@ -45,6 +51,9 @@ public class FilterList extends Screen { stack.scale(TITLE_SCALAR, TITLE_SCALAR); context.drawText(this.textRenderer, this.title, 0, 0, TITLE_COLOR, true); stack.popMatrix(); + + Pair<Integer, Integer> pos = getButtonPos(); + context.drawWrappedText(this.textRenderer, INFO_TEXT, pos.getLeft() + BUTTON_WIDTH + 5, pos.getRight(), 245, 0xffffffff, true); } @Override @@ -55,6 +64,13 @@ public class FilterList extends Screen { updateList(); } + private Pair<Integer, Integer> getButtonPos() { + MinecraftClient client = MinecraftClient.getInstance(); + Window window = client.getWindow(); + return new Pair<>((window.getScaledWidth() - Constants.WIDGET_WIDTH) / 2, TITLE_Y_OFFSET + 16); + } + + private void updateList() { scroll.children().clear(); @@ -1,5 +1,7 @@ package blade.addon.features.item; +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.rendering.DrawEvents; import net.minecraft.client.gui.DrawContext; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; @@ -10,7 +12,13 @@ import java.util.List; public class ItemRarityHighlight { - public static void draw(DrawContext context, ItemStack stack, int x, int y) { + public static void init() { + DrawEvents.INVENTORY_SLOT_BEFORE.register(ItemRarityHighlight::draw); + DrawEvents.HUD_SLOT_BEFORE.register(ItemRarityHighlight::draw); + } + + private static void draw(DrawContext context, ItemStack stack, int x, int y) { + if (!Visual.itemRarityBackground) return; ItemRarityHolder holder = (ItemRarityHolder) (Object) stack; assert holder != null; @@ -38,8 +46,7 @@ public class ItemRarityHighlight { for (String testString: rarityStrings) { try { - ItemRarity rarity = ItemRarity.valueOf(testString); - return rarity; + return ItemRarity.valueOf(testString); } catch (IllegalArgumentException ignored) { } @@ -1,12 +1,14 @@ package blade.addon.features.item; import blade.addon.utils.Constants; +import blade.addon.utils.config.values.Visual; import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.FolderUtility; import blade.addon.utils.data.ItemUtil; import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.rendering.DrawEvents; import config.practical.manager.ConfigManager; import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; @@ -34,6 +36,11 @@ public class ProtectItem { @ConfigValue public static HashSet<String> protectedItems = new HashSet<>(); + public static void init() { + DrawEvents.INVENTORY_SLOT_BEFORE.register(ProtectItem::draw); + DrawEvents.HUD_SLOT_BEFORE.register(ProtectItem::draw); + } + public static void protectSelected() { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player == null) { @@ -73,7 +80,8 @@ public class ProtectItem { return protectedItems.contains(uuid); } - public static void draw(DrawContext context, ItemStack stack, int x, int y) { + private static void draw(DrawContext context, ItemStack stack, int x, int y) { + if (!Visual.highlightProtectedItem) return; ProtectedItemHolder holder = (ProtectedItemHolder) (Object) stack; assert holder != null; @@ -131,6 +139,6 @@ public class ProtectItem { } public static boolean isInADungeon() { - return Location.inDungeon() && Phase.runStarted() && !Phase.runOver() && Location.hasRecivedLocation(); + return Location.inDungeon() && Phase.runStarted() && !Phase.runOver() && Location.hasReceivedLocation(); } } @@ -1,5 +1,7 @@ package blade.addon.features.item; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.rendering.DrawEvents; import net.minecraft.client.gui.DrawContext; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; @@ -10,7 +12,11 @@ import java.util.List; public class SelectedPetHighlight { - public static void draw(DrawContext context, ItemStack stack, int x, int y) { + public static void init() { + DrawEvents.INVENTORY_SLOT_BEFORE.register(SelectedPetHighlight::draw); + } + + private static void draw(DrawContext context, ItemStack stack, int x, int y) { PetHolder holder = (PetHolder) (Object) stack; assert holder != null; @@ -20,17 +26,17 @@ public class SelectedPetHighlight { if (!holder.blade_addons$isSelected()) return; - context.fill(x, y, x + 16, y + 16, 0xffff0000); + context.fill(x, y, x + 16, y + 16, ExtraOptions.petHighlightColor); } public static boolean isSelected(ItemStack item) { LoreComponent lore = item.get(DataComponentTypes.LORE); - if (lore == null) return false; + if (lore == null) return false; List<Text> lines = lore.lines(); if (lines.isEmpty()) return false; - for(Text text: lines) { + for (Text text : lines) { if (text == null) continue; if (text.getString().equals("Click to despawn!")) return true; } @@ -1,5 +1,7 @@ package blade.addon.features.item; +import blade.addon.utils.config.values.Visual; +import blade.addon.utils.rendering.DrawEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -10,7 +12,15 @@ import net.minecraft.nbt.NbtCompound; public class StarCountHighlight { - public static void draw(DrawContext context, ItemStack stack, int x, int y) { + public static void init() { + DrawEvents.INVENTORY_SLOT_AFTER.register(StarCountHighlight::draw); + DrawEvents.HUD_SLOT_AFTER.register(StarCountHighlight::draw); + } + + private static void draw(DrawContext context, ItemStack stack, int x, int y) { + + if (!Visual.drawStarCount) return; + StarCountHolder holder = (StarCountHolder) (Object) stack; assert holder != null; @@ -1,6 +1,8 @@ package blade.addon.features.notifications; +import blade.addon.utils.Misc; import blade.addon.utils.config.FolderUtility; +import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import com.google.gson.Gson; @@ -38,6 +40,10 @@ public class Notifications { load(); Events.ON_GAME_MESSAGE.register(text -> { String message = text.getString(); + if (Debug.sendNotiDebug) { + Misc.addChatMessage(Text.literal(message.replaceAll("§", "&"))); + } + for (Notification notification : notifications) { notification.testMessage(message); } @@ -0,0 +1,94 @@ +package blade.addon.features.other; + +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.rendering.DrawEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.Click; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.input.CharInput; +import net.minecraft.client.input.KeyInput; +import net.minecraft.client.util.Window; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; + +public class SearchBar { + + private static final int SEARCH_Y = 20; + private static final int SEARCH_WIDTH = 150; + private static final int SEARCH_HEIGHT = 20; + private static TextFieldWidget searchBar; + private static boolean shouldDisplay = false; + private static String searchTerm = ""; + + public static void init() { + DrawEvents.INVENTORY_SLOT_AFTER.register((context, item, x, y) -> { + if (shouldDisplay() && !searchTerm.isEmpty() && ExtraOptions.toggleableSearchBar) { + String name = item.getName().getString(); + if (!name.contains(searchTerm) || name.equals("Air")) { + context.fill(x, y, x + 16, y + 16, 0xaa111111); + } + } + }); + } + + public static void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + if (!exists() || !shouldDisplay() || !ExtraOptions.toggleableSearchBar) return; + searchBar.render(context, mouseX, mouseY, deltaTicks); + } + + public static boolean keyPressed(KeyInput input) { + if (!exists() || !ExtraOptions.toggleableSearchBar) return false; + + boolean ctrlIsPressed = (input.modifiers() & GLFW.GLFW_MOD_CONTROL) != 0; + + if (ctrlIsPressed && input.key() == GLFW.GLFW_KEY_F) { + shouldDisplay = !shouldDisplay; + return true; + } else if (shouldDisplay() && searchBar.isFocused() && input.key() != GLFW.GLFW_KEY_ESCAPE) { + searchBar.keyPressed(input); + return true; + } + return false; + } + + public static void CharTyped(CharInput input) { + if (!exists() || !searchBar.isFocused() || !shouldDisplay() || !ExtraOptions.toggleableSearchBar) return; + searchBar.charTyped(input); + } + + public static void onMouseClick(Click click) { + if (!exists() || !shouldDisplay() || !ExtraOptions.toggleableSearchBar) return; + searchBar.setFocused(inBounds(click.x(), click.y())); + } + + + public static boolean shouldDisplay() { + return shouldDisplay; + } + + private static boolean exists() { + if (searchBar != null) return true; + + MinecraftClient mc = MinecraftClient.getInstance(); + TextRenderer textRenderer = mc.textRenderer; + Window window = mc.getWindow(); + + if (window == null || textRenderer == null) return false; + + searchBar = new TextFieldWidget(textRenderer, (window.getScaledWidth() - SEARCH_WIDTH) / 2, SEARCH_Y, SEARCH_WIDTH, SEARCH_HEIGHT, Text.literal("")); + searchBar.setChangedListener(string -> searchTerm = string); + return true; + } + + private static boolean inBounds(double x, double y) { + int sx = searchBar.getX(); + int sy = searchBar.getY(); + int sw = searchBar.getWidth(); + int sh = searchBar.getHeight(); + + return x >= sx && x <= sx + sw && y >= sy && y <= sy + sh; + } + +} @@ -13,6 +13,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.MutableText; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -28,13 +29,15 @@ public class SelectedPet { private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (?:\\[[^\\]]+\\] )?(.+)"); private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (?:\\[Lvl \\d+] )?(?:\\[[^\\]]+\\] )?(.+)!$"); private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl \\d+] (?:\\[[^\\]]+\\] )?(.+)! VIEW RULE$"); + private static final Pattern LEVEL_REGEX = Pattern.compile("\\[Lvl (\\d+)]"); private static final int TOTAL_TICKS = 20; - private static final Text NO_PET = Text.literal("§cNo pet"); + private static final MutableText NO_PET = Text.literal("§cNo pet"); private static final String identifierPrefix = "pets/"; - private static Text currentPetText = NO_PET; + private static MutableText currentPetText = NO_PET; + private static int currentPetLevel = -1; private static String currentPetString = ""; private static Identifier spriteId = null; private static int tick = 0; @@ -52,11 +55,12 @@ public class SelectedPet { String name = matcher.group(2).replace(" ✦", ""); Style style = getStyle(message, name); - summonPet(name, Text.literal(name).setStyle(style), false); + summonPet(name, Text.literal(name).setStyle(style), getLevel(string), false); return; } - matcher = RULE_EQUIP_PET_PATTERN.matcher(string.replaceAll("§.", "")); + String unformattedLine = string.replaceAll("§.", ""); + matcher = RULE_EQUIP_PET_PATTERN.matcher(unformattedLine); if (matcher.find()) { String name = matcher.group(1).replace(" ✦", ""); @@ -66,7 +70,7 @@ public class SelectedPet { textName = string.substring(index - COLOR_OFFSET, index) + textName; } - summonPet(name, Text.literal(textName), true); + summonPet(name, Text.literal(textName), getLevel(unformattedLine), true); } }); @@ -85,7 +89,7 @@ public class SelectedPet { if (matcher.find()) { String petName = matcher.group(1).replace(" ✦", ""); Style style = getStyle(text, petName); - summonPet(petName, Text.literal(petName).setStyle(style), false); + summonPet(petName, Text.literal(petName).setStyle(style), getLevel(string), false); } return false; @@ -100,12 +104,14 @@ public class SelectedPet { private static void despawnPet() { Events.ON_PET.invoke(petEvent -> petEvent.onPet("")); currentPetText = NO_PET; + currentPetLevel = -1; currentPetString = ""; spriteId = null; } - private static void summonPet(String stringName, Text textName, boolean sendSound) { + private static void summonPet(String stringName, MutableText textName, int level, boolean sendSound) { + currentPetLevel = level; if (stringName.equals(currentPetString)) { return; } @@ -135,6 +141,15 @@ public class SelectedPet { return style; } + private static int getLevel(String line) { + Matcher matcher = LEVEL_REGEX.matcher(line); + if (matcher.find()) { + return Integer.parseInt(matcher.group(1)); + } + + return -1; + } + private static void updateSprite(String petName) { if (petName == null) { spriteId = null; @@ -162,7 +177,15 @@ public class SelectedPet { TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; - context.drawText(textRenderer, currentPetText, x + (ExtraOptions.includePetSprite ? 18 : 0), y + component.getHeight() - textRenderer.fontHeight, 0xffffffff, true); + int textX = x + (ExtraOptions.includePetSprite ? 18 : 0); + int textY = y + component.getHeight() - textRenderer.fontHeight; + + if (ExtraOptions.displayPetLevel && currentPetText != NO_PET) { + context.drawText(textRenderer, Text.literal("§7[Lvl " + (currentPetLevel != -1 ? currentPetLevel : "???") + "]"), textX, textY, 0xffffffff, true); + textY -= textRenderer.fontHeight; + } + + context.drawText(textRenderer, currentPetText, textX, textY, 0xffffffff, true); } public static boolean displayNotification() { @@ -0,0 +1,62 @@ +package blade.addon.features.other; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +public class StunWaypoint { + + private static final Box BLOCK = new Box(-168, 27, -169, -167, 28, -168); + + private static boolean inBelly = false; + private static boolean inP3 = false; + + public static void init() { + + Events.ON_GAME_MESSAGE.register(text -> { + if (!Location.in(Location.KUUDRA) || !ExtraOptions.stunWaypoint) return false; + String string = text.getString(); + + if (string.equals("[NPC] Elle: Phew! The Ballista is finally ready! It should be strong enough to tank Kuudra's blows now!")) { + inP3 = true; + return false; + } + + if (string.equals("[NPC] Elle: POW! SURELY THAT'S IT! I don't think he has any more in him!")) { + reset(); + return false; + } + + return false; + }); + + Events.ON_PACKET.register(packet -> { + if (!Location.in(Location.KUUDRA) || !ExtraOptions.stunWaypoint) return false; + + if (packet instanceof PlayerPositionLookS2CPacket posPacket) { + Vec3d pos = posPacket.change().position(); + if (pos.x == -161 && pos.y == 49 && pos.z == -186) { + inBelly = true; + } + + } + return false; + }); + + RenderingEvents.NO_DEPTH_OUTLINE_ENTITY.register((context, matrixStack, consumer) -> { + if (!inP3 || !inBelly || !Location.in(Location.KUUDRA) || !ExtraOptions.stunWaypoint) return; + RenderUtils.renderOutline(matrixStack, consumer, BLOCK, new float[]{0, 1, 1, 1}); + }); + } + + + private static void reset() { + inBelly = false; + inP3 = false; + } +} @@ -8,6 +8,7 @@ import net.minecraft.network.ClientConnection; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.s2c.common.CommonPingS2CPacket; import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientConnection.class) public class ClientConnectionMixin { - @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), order = 0, cancellable = true) + @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;handlePacket(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;)V"), order = 0, cancellable = true) private void channelRead0(ChannelHandlerContext channelHandlerContext, Packet<?> packet, CallbackInfo ci) { if (packet instanceof CommonPingS2CPacket common) { //admins send these packets too for inventory changes @@ -25,14 +26,13 @@ public class ClientConnectionMixin { Events.ON_SERVER_TICK.invoke(ServerTickEvent::onServerTick); } - if (packet instanceof GameMessageS2CPacket message) { - if (Events.ON_GAME_MESSAGE.invoke(gameMessageEvent -> gameMessageEvent.onGameMessage(message.content()))) { - ci.cancel(); - return; + if (packet instanceof GameMessageS2CPacket(Text content, boolean overlay) && !overlay) { + if (Events.ON_GAME_MESSAGE.invoke(gameMessageEvent -> gameMessageEvent.onGameMessage(content))) { + ci.cancel(); } } - Events.ON_PACKET.invoke(packetEvent -> packetEvent.onPacket(packet)); + Events.ON_PACKET.invoke(packetEvent -> packetEvent.onPacket(packet)); } @Inject(method = "sendImmediately", at = @At("HEAD")) @@ -6,13 +6,19 @@ import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; @@ -104,4 +110,20 @@ public class ClientPlayNetworkHandlerMixin { Events.ON_ENTITY_SPAWNED.invoke(entityTrackEvent -> entityTrackEvent.onEntity(entity, world)); } + @Inject(method = "onParticle", at = @At("HEAD")) + private void onParticle(ParticleS2CPacket packet, CallbackInfo ci) { + Events.ON_PARTICLE.invoke(particleEvent -> particleEvent.onParticle(packet)); + } + + @WrapOperation(method = "onBundle", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/Packet;apply(Lnet/minecraft/network/listener/PacketListener;)V")) + private void apply(Packet<?> packet, PacketListener listener, Operation<Void> original) { + if (packet instanceof GameMessageS2CPacket(Text content, boolean overlay) && !overlay) { + if (Events.ON_GAME_MESSAGE.invoke(gameMessageEvent -> gameMessageEvent.onGameMessage(content))) { + return; + } + } + + Events.ON_PACKET.invoke(packetEvent -> packetEvent.onPacket(packet)); + original.call(packet, listener); + } } \ No newline at end of file @@ -14,6 +14,8 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.passive.SheepEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.projectile.FishingBobberEntity; +import net.minecraft.util.math.Vec3d; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -49,5 +51,18 @@ public class EntityRenderManagerMixin { if (entity instanceof SheepEntity) { if (Location.inDungeon() && MobHighlight.hideSheep) cir.setReturnValue(false); } + + if (Visual.oldFishingRod && entity instanceof FishingBobberEntity bobber) { + ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; + if (clientPlayer == null || bobber.getOwner() != clientPlayer) return; + + //Pretty much just hides the bobber if it's too close + //its def not exact, but it's good enough for now + Vec3d pos = bobber.getInterpolator().getLerpedPos(); + if (clientPlayer.getEntityPos().distanceTo(pos) < 2 && bobber.age < 6 && pos.y > clientPlayer.getY() + 1.2 && clientPlayer.getPitch() > -60) { + cir.setReturnValue(false); + } + } + } } @@ -1,16 +1,13 @@ package blade.addon.mixin; -import blade.addon.features.dungeon.f7.invincibility.MaskHighlight; -import blade.addon.features.item.ItemRarityHighlight; import blade.addon.features.item.ProtectItem; -import blade.addon.features.item.SelectedPetHighlight; -import blade.addon.features.item.StarCountHighlight; -import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.config.values.Visual; +import blade.addon.features.other.SearchBar; +import blade.addon.utils.rendering.DrawEvents; +import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.input.KeyInput; import net.minecraft.item.ItemStack; import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.slot.Slot; @@ -23,9 +20,10 @@ import org.spongepowered.asm.mixin.Unique; 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; @Mixin(HandledScreen.class) -public class HandledScreenMixin<T extends ScreenHandler> { +public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen { @Shadow @Final @@ -33,32 +31,21 @@ public class HandledScreenMixin<T extends ScreenHandler> { @Unique private static final int INVALID_SLOT_ID = -999; + protected HandledScreenMixin(Text title) { + super(title); + } + + @Inject(method = "render", at=@At("TAIL")) + private static void render(DrawContext context, int mouseX, int mouseY, float deltaTicks, CallbackInfo ci) { + SearchBar.render(context, mouseX, mouseY, deltaTicks); + } + @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) public void drawBackground(DrawContext context, Slot slot, CallbackInfo ci) { - int x = slot.x; int y = slot.y; ItemStack stack = slot.getStack(); - - if (ExtraOptions.highlightSelectedPet) { - HandledScreen screen = (HandledScreen) (Object) this; - if (screen instanceof GenericContainerScreen containerScreen) { - Text title = containerScreen.getTitle(); - if (title == null) return; - if (title.getString().equals("Pets")) { - SelectedPetHighlight.draw(context, stack, x, y); - } - - } - } - - if (Visual.highlightProtectedItem) { - ProtectItem.draw(context, stack, x, y); - } - - if (Visual.itemRarityBackground) { - ItemRarityHighlight.draw(context, stack, x, y); - } + DrawEvents.INVENTORY_SLOT_BEFORE.invoke(event -> event.draw(context, stack, x, y)); } @Inject(method = "drawSlot", at = @At(value = "TAIL")) @@ -66,14 +53,17 @@ public class HandledScreenMixin<T extends ScreenHandler> { int x = slot.x; int y = slot.y; ItemStack stack = slot.getStack(); + DrawEvents.INVENTORY_SLOT_AFTER.invoke(event -> event.draw(context, stack, x, y)); + } - if (Dungeons.maskHighlight) { - MaskHighlight.draw(context, stack, x, y); - } + @Inject(method = "keyPressed", at=@At("HEAD"), cancellable = true) + private void keyPressed(KeyInput input, CallbackInfoReturnable<Boolean> cir) { + if (SearchBar.keyPressed(input)) cir.setReturnValue(false); + } - if (Visual.drawStarCount) { - StarCountHighlight.draw(context, stack, x, y); - } + @Inject(method = "mouseClicked", at=@At("HEAD")) + private void onMouseClick(Click click, boolean doubled, CallbackInfoReturnable<Boolean> cir) { + SearchBar.onMouseClick(click); } @Inject(method ="onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;onMouseClick(Lnet/minecraft/screen/slot/Slot;Lnet/minecraft/screen/slot/SlotActionType;)V"), cancellable = true) @@ -3,12 +3,10 @@ package blade.addon.mixin; import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.features.dungeon.f7.terms.TitleHider; import blade.addon.features.item.HeldItemToolTip; -import blade.addon.features.item.ItemRarityHighlight; -import blade.addon.features.item.ProtectItem; -import blade.addon.features.item.StarCountHighlight; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.config.values.Visual; import blade.addon.utils.interfaces.GameHud; +import blade.addon.utils.rendering.DrawEvents; import com.llamalad7.mixinextras.sugar.Local; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; @@ -46,21 +44,12 @@ public class InGameHudMixin implements GameHud { @Inject(method = "renderHotbarItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;III)V"), order = 2000) public void drawBackground(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { - if (Visual.itemRarityBackground) { - ItemRarityHighlight.draw(context, stack, x, y); - } - - if (Visual.highlightProtectedItem) { - ProtectItem.draw(context, stack, x, y); - } - + DrawEvents.HUD_SLOT_BEFORE.invoke(slotEvent -> slotEvent.draw(context, stack, x, y)); } @Inject(method = "renderHotbarItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;III)V", shift = At.Shift.AFTER), order = 2000) public void drawStar(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { - if (Visual.drawStarCount) { - StarCountHighlight.draw(context, stack, x, y); - } + DrawEvents.HUD_SLOT_AFTER.invoke(slotEvent -> slotEvent.draw(context, stack, x, y)); } @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD"), cancellable = true, order = 2000) @@ -1,6 +1,7 @@ package blade.addon.mixin; import blade.addon.features.other.InventoryButton; +import blade.addon.features.other.SearchBar; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.InventoryScreen; @@ -31,6 +32,7 @@ public abstract class InventoryScreenMixin extends RecipeBookScreen<PlayerScreen stack.translate(x, y); InventoryButton.renderAll(context, mouseX, mouseY, deltaTicks); stack.popMatrix(); + SearchBar.render(context, mouseX, mouseY, deltaTicks); } @Override @@ -0,0 +1,26 @@ +package blade.addon.mixin; + +import blade.addon.features.other.SearchBar; +import blade.addon.utils.config.values.ExtraOptions; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.Keyboard; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.input.CharInput; +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(Keyboard.class) +public class KeyboardMixin { + + @Inject(method = "onChar", at= @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;charTyped(Lnet/minecraft/client/input/CharInput;)Z")) + private void onChar(long window, CharInput input, CallbackInfo ci, @Local Screen screen) { + if (ExtraOptions.toggleableSearchBar && screen instanceof HandledScreen<?>) { + SearchBar.CharTyped(input); + } + } + + +} @@ -25,10 +25,10 @@ public class MinecraftClientMixin { public HitResult crosshairTarget; @Inject(method = "doItemUse", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/item/ItemStack;getCount()I"), cancellable = true) - private void testInteraction(CallbackInfo ci, @Local ItemStack itemStack) { + private void testInteractionBlock(CallbackInfo ci, @Local ItemStack itemStack) { BlockHitResult blockHitResult = (BlockHitResult) this.crosshairTarget; if (blockHitResult == null) return; - if (Events.ON_BLOCK_INTERACTION.invoke(blockInteractionEvent -> blockInteractionEvent.iteract(blockHitResult, itemStack))) { + if (Events.ON_BLOCK_INTERACTION.invoke(blockInteractionEvent -> blockInteractionEvent.interact(blockHitResult, itemStack))) { ci.cancel(); } } @@ -199,6 +199,18 @@ public class Commands { Misc.executeCommand("warp dungeon_hub"); return Constants.SUCCESS; })); + + for (int i = 1; i <= 7; i++) { + int finalI = i; + dispatcher.register(ClientCommandManager.literal("f" + i).executes(context -> { + Misc.executeCommand("joindungeon catacombs " + finalI); + return Constants.SUCCESS; + })); + dispatcher.register(ClientCommandManager.literal("m" + i).executes(context -> { + Misc.executeCommand("joindungeon master_catacombs " + finalI); + return Constants.SUCCESS; + })); + } } } } @@ -8,53 +8,51 @@ import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacke import net.minecraft.text.Text; public enum Location { - NONE, - DUNGEON, - DUNGEON_HUB, - PRIVATE_ISLAND, - HUB, - GALATEA, - THE_PARK, - THE_FARMING_ISLANDS, - GOLD_MINE, - DEEP_CAVERNS, - DWARVEN_MINES, - CRYSTAL_HOLLOWS, - SPIDERS_DEN, - THE_END, - CRIMSON_ISLE, - GARDEN, - THE_RIFT, - BACKWATER_BAYOU, - UNKNOWN, - JERRYS_WORKSHOP, - MINESHAFT, - DARK_AUCTION, - KUUDRA; - - private static Location currentLocation = Location.NONE; + UNKNOWN("Unknown"), + DUNGEON("Dungeon"), + DUNGEON_HUB("Dungeon Hub"), + PRIVATE_ISLAND("Private Island"), + HUB("Hub"), + GALATEA("Galatea"), + THE_PARK("The Park"), + THE_FARMING_ISLANDS("The Farming Islands"), + GOLD_MINE("Gold Mine"), + DEEP_CAVERNS("Deep Caverns"), + DWARVEN_MINES("Dwarven Mines"), + CRYSTAL_HOLLOWS("Crystal Hollows"), + SPIDERS_DEN("Spider's Den"), + THE_END("The End"), + CRIMSON_ISLE("Crimson Isle"), + GARDEN("Garden"), + THE_RIFT("The Rift"), + BACKWATER_BAYOU("Backwater Bayou"), + JERRYS_WORKSHOP("Jerry's Workshop"), + MINESHAFT("Mineshaft"), + DARK_AUCTION("Dark Auction"), + KUUDRA("Kuudra"),; + + final String name; + + Location(String name) { + this.name = name; + } + + + private static Location currentLocation = Location.UNKNOWN; private static boolean inSkyblock = false; private static boolean detectedNewLocation = false; + private static long lastChanged = System.currentTimeMillis(); public static void init() { HypixelModAPI instance = HypixelModAPI.getInstance(); - instance.createHandler(ClientboundLocationPacket.class, packet -> packet.getMap().ifPresent(map -> { - + instance.createHandler(ClientboundLocationPacket.class, packet -> packet.getMap().ifPresent(locationName -> { if (packet.getServerType().isPresent()) { ServerType serverType = packet.getServerType().get(); inSkyblock = serverType.getName().equals("SkyBlock"); } - try { - currentLocation = Location.valueOf(map.toUpperCase().replace(" ", "_").replaceAll("'", "")); - } catch (IllegalArgumentException ignored) { - currentLocation = Location.NONE; - } - detectedNewLocation = true; - Debug.sendDebugMessage(Text.literal("Location: " + currentLocation)); - - Events.ON_LOCATION_CHANGE.invoke(locationChangeEvent -> locationChangeEvent.onLocationChange(currentLocation)); + changeLocation(getLocation(locationName)); })); instance.subscribeToEventPacket(ClientboundLocationPacket.class); @@ -65,6 +63,28 @@ public enum Location { }); } + public static Location getLocation(String locationName) { + Location location; + + try { + location = Location.valueOf(locationName.toUpperCase().replace(" ", "_").replaceAll("'", "")); + } catch (IllegalArgumentException ignored) { + location = Location.UNKNOWN; + } + + return location; + } + + public static void changeLocation(Location location) { + currentLocation = location; + detectedNewLocation = true; + lastChanged = System.currentTimeMillis(); + Debug.sendDebugMessage(Text.literal("Location: " + currentLocation)); + + Events.ON_LOCATION_CHANGE.invoke(locationChangeEvent -> locationChangeEvent.onLocationChange(currentLocation)); + + } + public static boolean in(Location location) { if (!inSkyblock) return false; return currentLocation == location; @@ -75,11 +95,20 @@ public enum Location { return currentLocation == Location.DUNGEON; } + public static Location getCurrentLocation() { + return currentLocation; + } + public static boolean inSkyblock() { return inSkyblock; } - public static boolean hasRecivedLocation() { + public static boolean hasReceivedLocation() { return detectedNewLocation; } + + @Override + public String toString() { + return "Location: " + name + " Last changed: " + (System.currentTimeMillis() - lastChanged) / 1000.0 + "s"; + } } \ No newline at end of file @@ -169,7 +169,8 @@ public class Config { ConfigSection goldor = new ConfigSection(Text.literal("Goldor")); goldor.add(new ConfigBool(Text.literal("Goldor tick timer"), () -> Floor7.enableGoldorTickTimer, bool -> Floor7.enableGoldorTickTimer = bool)); goldor.add(new ConfigBool(Text.literal("Term start time"), () -> Floor7.enableTermStartTimer, bool -> Floor7.enableTermStartTimer = bool)); - goldor.add(new ConfigBool(Text.literal("Make goldor timer tick down"), () -> Floor7.inDeathTicks, bool -> Floor7.inDeathTicks = bool)); + goldor.add(new ConfigBool(Text.literal("in 3s increments"), () -> Floor7.inDeathTicks, bool -> Floor7.inDeathTicks = bool)); + goldor.add(new ConfigBool(Text.literal("Tick up (instead of down from 3s)"), () -> Floor7.makeGoldorTickUp, bool -> Floor7.makeGoldorTickUp = bool)); goldor.add(new ConfigBool(Text.literal("Positional messages"), () -> Floor7.enablePositionalMessages, bool -> Floor7.enablePositionalMessages = bool)); goldor.add(new ConfigBool(Text.literal("Terminal splits"), () -> Section.enableTerminalSplits, bool -> Section.enableTerminalSplits = bool)); goldor.add(new ConfigOptions<>(Text.literal("Display when"), Section.DisplayTerminalSplitsWhen.values(), () -> Section.displayTerminalSplitsWhen, when -> Section.displayTerminalSplitsWhen = when)); @@ -202,7 +203,7 @@ public class Config { relic.add(new ConfigBool(Text.literal("Use valleys progress bar"), () -> Floor7.useValleyBar, bool -> Floor7.useValleyBar = bool)); relic.add(new ConfigInt(Text.literal("Relic start timer ticks"), () -> Floor7.relicSpawnTicks, num -> Floor7.relicSpawnTicks = num, 1, 30, 50)); relic.add(new ConfigBool(Text.literal("Enable relic placed time"), () -> Floor7.enableRelicPlaceTime …… diff 过长已截断 …… |
capitalize formatting of boss bar letters查看变更src/main/java/blade/addon/utils/rendering/RenderUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -119,9 +119,9 @@ public class RenderUtils { public static String formatHealth(float health) { - if (health >= 1e9) return String.format("%.1fb", health / 1e9); - if (health >= 1e6) return String.format("%.1fm", health / 1e6); - if (health >= 1e3) return String.format("%.1fk", health / 1e3); + if (health >= 1e9) return String.format("%.1fB", health / 1e9); + if (health >= 1e6) return String.format("%.1fM", health / 1e6); + if (health >= 1e3) return String.format("%.1fK", health / 1e3); return health + ""; } |
| - added chat filters - added dragon health - added maxor stun duration - added arrow swapper display and title - added f7 boss health numbers in the boss bar, credits to slice for the initial code - hopefully fixed splits getting sent in between the xp message
- fixed term time stamps sending 0:0s for the final completion of each section
- hopefully fixed dragon spawn timer
- hopefully fixed stuff breaking thanks to hypixels random changes 查看变更gradle.properties | 4 +-
src/main/java/blade/addon/Bladeaddons.java | 21 ++++++---
src/main/java/blade/addon/features/dungeon/ChestCounter.java | 2 +-
src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 6 +--
src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 7 +--
src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/DragSpawnTimer.java | 157 --------------------------------------------------------------------
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 31 +++++++++-----
src/main/java/blade/addon/features/dungeon/f7/dragons/DragSpawnTimer.java | 104 +++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/dragons/Dragon.java | 61 +++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/dragons/DragonHealth.java | 87 ++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 16 +++++--
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 20 ++++-----
src/main/java/blade/addon/features/dungeon/f7/{ => maxor}/CrystalSpawn.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/maxor/MaxorStun.java | 59 ++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/{ => storm}/DistanceToLedge.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/{ => storm}/PillarExplode.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/{ => storm}/StormTickTimer.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 2 +-
src/main/java/blade/addon/features/filter/FilterEntry.java | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/filter/FilterList.java | 93 ++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/filter/Filters.java | 31 ++++++++++++++
src/main/java/blade/addon/features/highlight/Highlight.java | 4 --
src/main/java/blade/addon/features/highlight/MimicHighlight.java | 4 +-
src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 2 +-
src/main/java/blade/addon/features/notifications/NotificationEntry.java | 2 +-
src/main/java/blade/addon/features/notifications/Notifications.java | 14 ++++--
src/main/java/blade/addon/features/other/ArrowSwapper.java | 95 +++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/other/PracticeSS.java | 11 ++---
src/main/java/blade/addon/features/other/RagDisplay.java | 2 +-
src/main/java/blade/addon/mixin/BossBarHudMixin.java | 56 ++++++++++++++++++++++++
src/main/java/blade/addon/mixin/ClientConnectionMixin.java | 12 +-----
src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 9 ++--
src/main/java/blade/addon/mixin/ItemStackMixin.java | 16 -------
src/main/java/blade/addon/utils/Constants.java | 14 +++---
src/main/java/blade/addon/utils/Keybinds.java | 6 +--
src/main/java/blade/addon/utils/Location.java | 22 +++++++++-
src/main/java/blade/addon/utils/config/Config.java | 40 +++++++++++-------
src/main/java/blade/addon/utils/config/FolderUtility.java | 1 +
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 11 +++--
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 4 +-
src/main/java/blade/addon/utils/config/components/Components.java | 21 ++++++---
src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 ++
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 6 +++
src/main/java/blade/addon/utils/config/values/Floor7.java | 8 +++-
src/main/java/blade/addon/utils/data/EntityUtil.java | 6 +++
src/main/java/blade/addon/utils/data/ItemUtil.java | 13 +++++-
src/main/java/blade/addon/utils/data/TextUtil.java | 5 +++
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 2 +-
src/main/java/blade/addon/utils/dungeon/Phase.java | 4 +-
src/main/java/blade/addon/utils/dungeon/Section.java | 17 ++++----
src/main/java/blade/addon/utils/events/Events.java | 7 ++-
src/main/java/blade/addon/utils/events/interfaces/PacketEvent.java | 8 ++++
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 25 ++++++++++-
src/main/resources/blade-addons.mixins.json | 1 +
57 files changed, 1007 insertions(+), 317 deletions(-)@@ -10,10 +10,10 @@ org.gradle.configuration-cache=false minecraft_version=1.21.10 yarn_mappings=1.21.10+build.3 loader_version=0.18.4 -loom_version=1.14-SNAPSHOT +loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=2.3.2 +mod_version=2.3.3 maven_group=blade.addon archives_base_name=blade-addons @@ -12,23 +12,26 @@ import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.BossWaypoints; -import blade.addon.features.dungeon.f7.CrystalSpawn; -import blade.addon.features.dungeon.f7.DistanceToLedge; -import blade.addon.features.dungeon.f7.DragSpawnTimer; -import blade.addon.features.dungeon.f7.PillarExplode; +import blade.addon.features.dungeon.f7.maxor.CrystalSpawn; +import blade.addon.features.dungeon.f7.storm.DistanceToLedge; +import blade.addon.features.dungeon.f7.dragons.DragSpawnTimer; +import blade.addon.features.dungeon.f7.storm.PillarExplode; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; -import blade.addon.features.dungeon.f7.StormTickTimer; +import blade.addon.features.dungeon.f7.storm.StormTickTimer; +import blade.addon.features.dungeon.f7.dragons.DragonHealth; import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.dungeon.f7.location.PositionMessages; +import blade.addon.features.dungeon.f7.maxor.MaxorStun; +import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; import blade.addon.features.dungeon.f7.terms.MelodyWarning; -import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.features.dungeon.f7.terms.SectionProgress; import blade.addon.features.dungeon.f7.terms.TermStartTimer; +import blade.addon.features.filter.Filters; import blade.addon.features.highlight.BatHighlight; import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; @@ -37,6 +40,7 @@ import blade.addon.features.highlight.TeammateHighlight; import blade.addon.features.highlight.WitherHighlight; import blade.addon.features.item.DropAnimation; import blade.addon.features.notifications.Notifications; +import blade.addon.features.other.ArrowSwapper; import blade.addon.features.other.CompactHoppity; import blade.addon.features.other.DianaNotifier; import blade.addon.features.other.KickedTimer; @@ -61,7 +65,6 @@ import blade.addon.utils.dungeon.Section; import blade.addon.utils.events.CustomEvents; import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; public class Bladeaddons implements ModInitializer { @Override @@ -129,5 +132,9 @@ public class Bladeaddons implements ModInitializer { SectionProgress.init(); BonzoSound.init(); QuizTimer.init(); + Filters.init(); + DragonHealth.init(); + MaxorStun.init(); + ArrowSwapper.init(); } } \ No newline at end of file @@ -74,7 +74,7 @@ public class ChestCounter { if (hasUpdatedData) { RenderUtils.drawPrefixedText(component, context, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); } else { - context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, Constants.RED_COLOR, true); + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, Constants.RED, true); } } @@ -92,11 +92,11 @@ public class ItemHighlight { if (distance > 20) { return 0; } else if (distance > 3.5) { - return Constants.RED_COLOR; + return Constants.RED; } else if (item.age > 11){ - return Constants.GREEN_COLOR; + return Constants.GREEN; } else { - return Constants.ORANGE_COLOR; + return Constants.ORANGE; } } @@ -4,6 +4,7 @@ import blade.addon.utils.Location; import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; @@ -42,7 +43,7 @@ public class KeyNotifier { public static void init() { ClientTickEvents.END_WORLD_TICK.register((world) -> { - if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return; + if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier || Phase.inBoss()) return; for (Entity entity : world.getEntities()) { if (entity instanceof ArmorStandEntity armorStand && !foundKeys.contains(entity)) { @@ -106,11 +107,11 @@ public class KeyNotifier { } private static boolean isValidClass() { - return Dungeons.displayKeyForAllClasses || DungeonClass.isClass(DungeonClass.ARCHER) || DungeonClass.isClass(DungeonClass.MAGE); + return (Dungeons.displayKeyForAllClasses || DungeonClass.isClass(DungeonClass.ARCHER) || DungeonClass.isClass(DungeonClass.MAGE) && Dungeons.enableKeyNotifier); } public static boolean display() { - return Location.inDungeon() && hasKey && isValidClass(); + return Location.inDungeon() && hasKey && isValidClass() && !Phase.inBoss(); } public static void render(HUDComponent component, DrawContext context) { @@ -46,7 +46,7 @@ public class SecretSpawnTimer { int x = component.getScaledX(); int y = component.getScaledY(); - int color = tick > 10 ? Constants.GREEN_COLOR : tick > 5 ? Constants.ORANGE_COLOR : Constants.RED_COLOR; + int color = tick > 10 ? Constants.GREEN : tick > 5 ? Constants.ORANGE : Constants.RED; RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(tick + ""), x, y, component.getWidth(), color); @@ -1,157 +0,0 @@ -package blade.addon.features.dungeon.f7; - -import blade.addon.utils.Scheduler; -import blade.addon.utils.config.values.Floor7; -import blade.addon.utils.dungeon.DungeonClass; -import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import config.practical.hud.HUDComponent; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.sound.SoundEvents; - -public class DragSpawnTimer { - - enum Dragon { - PURPLE(0xffff55ff, 0, 4), - BLUE(0xff55ffff, 1, 3), - RED(0xffff5555, 2, 2), - GREEN(0xff55ff55, 3, 1), - ORANGE(0xffffaa00, 4, 0), - NONE(0xffffffff, 99, 99); - - final int color; - final int archPrio; - final int bersPrio; - - Dragon(int color, int archPrio, int bersPrio) { - this.color = color; - this.archPrio = archPrio; - this.bersPrio = bersPrio; - } - } - - public enum Team { - ARCHER_TEAM("Archer team"), BERS_TEAM("Bers team"); - - private final String label; - - Team(String label) { - this.label = label; - } - - @Override - public String toString() { - return label; - } - } - - private static final int SPAWN_DURATION = 100; - private static final int DUPE_DELAY = 130; - - private static Dragon currentDragon = Dragon.NONE; - private static Dragon prevDragon = Dragon.NONE; - private static boolean hasDoneSplit = false; - private static int tick = 0; - private static int dupeTick = 0; - - public static void init() { - Events.ON_PARTICLE.register((x, y, z, effect) -> { - if (effect.getType() != ParticleTypes.ENCHANT) return false; - Dragon detectedDragon = getDragon(x, y, z); - - if (detectedDragon == Dragon.NONE) return false; - - //the dupe check is to stop purple from just breaking it when it spawns - if (currentDragon == Dragon.NONE) { - if ((prevDragon == detectedDragon && dupeTick > 0)) return false; - currentDragon = detectedDragon; - prevDragon = currentDragon; - dupeTick = DUPE_DELAY; - tick = SPAWN_DURATION; - if (Floor7.sendSoundOnDragSpawn) { - Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0.75f, 1); - } - } else if (detectedDragon != currentDragon && !hasDoneSplit) { - currentDragon = getPrio(detectedDragon, currentDragon); - prevDragon = currentDragon; - dupeTick = DUPE_DELAY * 2; - hasDoneSplit = true; - } - - return false; - }); - - Events.ON_SERVER_TICK.register(() -> { - tick = Math.max(tick - 1, 0); - dupeTick = Math.max(dupeTick - 1, 0); - if (dupeTick == 0 && prevDragon != Dragon.NONE) { - prevDragon = Dragon.NONE; - } - - if (tick == 0 && currentDragon != Dragon.NONE) { - currentDragon = Dragon.NONE; - } - return false; - }); - - Events.ON_LOCATION_CHANGE.register(newLocation -> { - reset(); - return false; - }); - } - - private static void reset() { - hasDoneSplit = false; - currentDragon = Dragon.NONE; - prevDragon = Dragon.NONE; - tick = 0; - } - - //checks are from valley addons - private static Dragon getDragon(double x, double y, double z) { - if (y >= 14 && y <= 19) { - if (x >= 27 && x <= 32) { - if (z == 59) { - return Dragon.RED; - } else if (z == 94) { - return Dragon.GREEN; - } - } else if (x >= 79 && x <= 85) { - if (z == 94) { - return Dragon.BLUE; - } else if (z == 56) { - return Dragon.ORANGE; - } - } else if (x == 56) { - return Dragon.PURPLE; - } - } - return Dragon.NONE; - } - - private static Dragon getPrio(Dragon dragon1, Dragon dragon2) { - if (DungeonClass.isArchTeam()) { - if (dragon1.archPrio < dragon2.archPrio) { - return dragon1; - } else { - return dragon2; - } - } else if (DungeonClass.isBersTeam()) { - if (dragon1.bersPrio < dragon2.bersPrio) { - return dragon1; - } else { - return dragon2; - } - } - return Dragon.NONE; - } - - public static boolean display() { - return Floor7.dragSpawnTimers && currentDragon != Dragon.NONE; - } - - public static void render(HUDComponent component, DrawContext context) { - RenderUtils.drawTimer(component, context, tick, currentDragon.color); - } -} @@ -1,11 +1,11 @@ package blade.addon.features.dungeon.f7; -import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.data.ItemUtil; +import blade.addon.utils.data.TextUtil; import blade.addon.utils.debug.Debug; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; @@ -21,8 +21,8 @@ import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; -import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.decoration.ArmorStandEntity; +import net.minecraft.item.ItemStack; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -44,7 +44,7 @@ public class RelicTimer { final Box box; final int color; final String name; - long placedTime = 0; + int placedTick = 0; Relic(Box box, int color, String name) { this.box = box; @@ -63,6 +63,7 @@ public class RelicTimer { private static Relic pickedupRelic = null; private static int tick = Floor7.relicSpawnTicks; + private static int placeTick = 0; private static boolean sentRelicTimes = false; //only here to test the relic progress bar @@ -79,6 +80,10 @@ public class RelicTimer { forceGUI = false; } + if (Phase.inP5()) { + placeTick++; + } + return false; }); @@ -93,6 +98,7 @@ public class RelicTimer { if (Phase.inP5()) { phaseStartTime = System.currentTimeMillis(); tick = Floor7.relicSpawnTicks; + placeTick = 0; } return false; }); @@ -121,14 +127,19 @@ public class RelicTimer { for (Entity entity : entities) { if (entity instanceof ArmorStandEntity armorStand) { - if (!EntityUtil.isWearing(armorStand, EquipmentSlot.HEAD, "Relic")) continue; + ItemStack item = armorStand.getWeaponStack(); + String id = ItemUtil.getId(item); + + if (id == null || !id.contains("RELIC")) continue; + Debug.sendDebugMessage(Text.literal("item id is " + id)); double ax = armorStand.getX(); double az = armorStand.getZ(); for (Relic relic : Relic.values()) { - if (relic.placedTime != 0 && Misc.getDistance(relic.box.maxX, relic.box.maxZ, ax, az) < 1) { - relic.placedTime = System.currentTimeMillis(); + if (relic.placedTick != 0 && Misc.getDistance(relic.box.maxX, relic.box.maxZ, ax, az) < 1.5) { + relic.placedTick = placeTick; + Debug.sendDebugMessage(Text.literal("Set" + relic.name + " time to " + relic.placedTick + ", item id is " + id)); } } } @@ -136,8 +147,7 @@ public class RelicTimer { if (allRelicsPlaced()) { for (Relic relic : Relic.values()) { - long time = relic.placedTime - phaseStartTime; - Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + Constants.DECIMAL_FORMAT.format(time) + "s&a.")); + Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + TextUtil.formatTicks(relic.placedTick) + "s&a.")); sentRelicTimes = true; } } @@ -214,14 +224,15 @@ public class RelicTimer { tick = Floor7.relicSpawnTicks; pickedupRelic = null; for (Relic relic : Relic.values()) { - relic.placedTime = 0; + relic.placedTick = 0; } sentRelicTimes = false; + placeTick = 0; } private static boolean allRelicsPlaced() { for (Relic relic : Relic.values()) { - if (relic.placedTime == 0) return false; + if (relic.placedTick == 0) return false; } return true; } @@ -0,0 +1,104 @@ +package blade.addon.features.dungeon.f7.dragons; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.sound.SoundEvents; + +public class DragSpawnTimer { + + public enum Team { + ARCHER_TEAM("Archer team"), BERS_TEAM("Bers team"); + + private final String label; + + Team(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } + } + + private static final int SPAWN_DURATION = 100; + + private static Dragon currentDragon = Dragon.NONE; + private static boolean hasDoneSplit = false; + private static int tick = 0; + + public static void init() { + Events.ON_PACKET.register(packet -> { + if (packet instanceof ParticleS2CPacket particle) { + if (!validParticle(particle)) return false; + Dragon dragon = Dragon.getDragon(particle.getX(), particle.getY(), particle.getZ()); + testDragon(dragon); + } + + return false; + }); + + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + + if (tick == 0 && currentDragon != Dragon.NONE) { + currentDragon = Dragon.NONE; + } + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + reset(); + return false; + }); + } + + private static void testDragon(Dragon dragon) { + if (dragon == Dragon.NONE) return; + + if (currentDragon == Dragon.NONE) { + currentDragon = dragon; + tick = SPAWN_DURATION; + + if (Floor7.sendSoundOnDragSpawn) { + Misc.sendSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0.75f, 1); + } + + } else if (currentDragon != dragon && !hasDoneSplit) { + currentDragon = Dragon.getPrio(dragon, currentDragon); + hasDoneSplit = true; + } + } + + private static boolean validParticle(ParticleS2CPacket packet) { + if (packet.getCount() != 20) return false; + if (packet.getY() != 19) return false; + if (packet.getParameters().getType() != ParticleTypes.FLAME) return false; + if (packet.getOffsetX() != 2) return false; + if (packet.getOffsetY() != 3) return false; + if (packet.getOffsetZ() != 2) return false; + if (packet.getX() % 1 != 0) return false; + if (packet.getZ() % 1 != 0) return false; + return true; + } + + private static void reset() { + hasDoneSplit = false; + currentDragon = Dragon.NONE; + tick = 0; + } + + public static boolean display() { + return Floor7.dragSpawnTimers && currentDragon != Dragon.NONE; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawTimer(component, context, tick, currentDragon.color); + } +} @@ -0,0 +1,61 @@ +package blade.addon.features.dungeon.f7.dragons; + +import blade.addon.utils.dungeon.DungeonClass; + +public enum Dragon { + PURPLE(0xffff55ff, 0, 4), + BLUE(0xff55ffff, 1, 3), + RED(0xffff5555, 2, 2), + GREEN(0xff55ff55, 3, 1), + ORANGE(0xffffaa00, 4, 0), + NONE(0xffffffff, 99, 99); + + final int color; + final int archPrio; + final int bersPrio; + + Dragon(int color, int archPrio, int bersPrio) { + this.color = color; + this.archPrio = archPrio; + this.bersPrio = bersPrio; + } + + //checks are from valley addons + public static Dragon getDragon(double x, double y, double z) { + if (y >= 14 && y <= 19) { + if (x >= 27 && x <= 32) { + if (z == 59) { + return Dragon.RED; + } else if (z == 94) { + return Dragon.GREEN; + } + } else if (x >= 79 && x <= 85) { + if (z == 94) { + return Dragon.BLUE; + } else if (z == 56) { + return Dragon.ORANGE; + } + } else if (x == 56) { + return Dragon.PURPLE; + } + } + return Dragon.NONE; + } + + public static Dragon getPrio(Dragon dragon1, Dragon dragon2) { + if (DungeonClass.isArchTeam()) { + if (dragon1.archPrio < dragon2.archPrio) { + return dragon1; + } else { + return dragon2; + } + } else if (DungeonClass.isBersTeam()) { + if (dragon1.bersPrio < dragon2.bersPrio) { + return dragon1; + } else { + return dragon2; + } + } + return Dragon.NONE; + } +} @@ -0,0 +1,87 @@ +package blade.addon.features.dungeon.f7.dragons; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.boss.dragon.EnderDragonEntity; +import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class DragonHealth { + + static class DataHolder { + EnderDragonEntity dragon; + float health; + + public DataHolder(EnderDragonEntity dragon, float health) { + this.dragon = dragon; + this.health = health; + } + } + + static final ConcurrentLinkedQueue<DataHolder> dragons = new ConcurrentLinkedQueue<>(); + + public static void init() { + + Events.ON_ENTITY_SPAWNED.register((entity, world) -> { + if (!Location.inDungeon()) return false; + + if (entity instanceof EnderDragonEntity dragon) { + dragons.add(new DataHolder(dragon, dragon.getHealth())); + } + + return false; + }); + + ClientTickEvents.END_WORLD_TICK.register(world -> dragons.removeIf(dataHolder -> dataHolder.dragon.isRemoved())); + RenderingEvents.FILLED_ENTITY.register(DragonHealth::render); + Events.ON_LOCATION_CHANGE.register(newLocation -> { + reset(); + return false; + }); + } + + private static void reset() { + dragons.clear(); + } + + private static int getColor(float health) { + if (health >= 7.5e8) return Constants.GREEN; + if (health >= 5e8) return Constants.YELLOW; + if (health >= 2.5e8) return Constants.GOLD; + return Constants.RED; + } + + private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!Floor7.dragonHealth) return; + + dragons.forEach(dataHolder -> { + + EnderDragonEntity dragon = dataHolder.dragon; + float currHealth = dragon.getHealth(); + + if (currHealth != 1024.0f) { + dataHolder.health = currHealth; + } + + float health = dataHolder.health; + + if (health == 0) return; + Vec3d pos = EntityUtil.getLerpedPos(dragon); + RenderUtils.renderText(context, matrixStack, Text.literal(RenderUtils.formatHealth(health)).withColor(getColor(health)), pos, 5); + + }); + + } + +} @@ -154,7 +154,7 @@ public class InvincibilityTimer { } private static void drawSprite(DrawContext context, Identifier identifier, int x, int y, boolean isOn, int ticks, Text timerText) { - int color = (ticks > 0? Constants.RED_COLOR: isOn? Constants.YELLOW_COLOR: Constants.GREEN_COLOR); + int color = (ticks > 0? Constants.RED: isOn? Constants.YELLOW: Constants.GREEN); context.fill(x, y, x + SPRITE_SIZE, y + SPRITE_SIZE, color); context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, identifier, x, y, SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); if (ticks > 0) { @@ -9,14 +9,15 @@ import net.minecraft.util.math.Vec3d; public class PositionMessage { - private final String message, check; + private final String message; + private final String[] checks; private final Box box; private boolean sent; private final int[] sections; - public PositionMessage(String message, String check, Box box, int[] sections) { + public PositionMessage(String message, String[] checks, Box box, int[] sections) { this.message = message; - this.check = check; + this.checks = checks; this.box = box; this.sent = true; this.sections = sections; @@ -42,8 +43,15 @@ public class PositionMessage { } } + private boolean matchesACheck(String string) { + for (String check : checks) { + if (string.contains(check)) return true; + } + return false; + } + public boolean hasBeenSent(String string) { - if (!string.toLowerCase().contains(check)) return false; + if (!matchesACheck(string.toLowerCase())) return false; if (sent) { return true; @@ -21,16 +21,16 @@ public class PositionMessages { static final ArrayList<PositionMessage> positionMessages = new ArrayList<>(); - static PositionMessage SS = new PositionMessage("At SS!", "ss", new Box(107, 120, 93, 110, 121, 95), new int[]{0, 1}); - static PositionMessage EE2 = new PositionMessage("At EE2!", "ee2", new Box(57, 109, 130, 59, 110, 132), new int[]{1, 2}); - static PositionMessage HEE2 = new PositionMessage("At High EE2!", "ee2", new Box(59, 132, 138, 62, 133, 140), new int[]{1, 2}); - static PositionMessage EE3 = new PositionMessage("At EE3!", "ee3", new Box(1, 109, 103, 3, 110, 106), new int[]{2, 3}); - static PositionMessage CORE = new PositionMessage("At Core!", "core", new Box(53, 115, 51, 56, 116, 54), new int[]{2, 3, 4}); - static PositionMessage TUNNEL = new PositionMessage("Inside Goldor Tunnel!", "tunnel", new Box(52, 114, 55, 57, 116, 58), new int[]{4, 5}); - static PositionMessage SAFE_2 = new PositionMessage("At 2 Safespot!", "2 safespot", new Box(46, 109, 121.987, 49, 110, 121.988), new int[]{1, 2}); - static PositionMessage SAFE_3 = new PositionMessage("At 3 Safespot!", "3 safespot", new Box(18, 121, 91, 19, 126, 99), new int[]{2, 3}); - static PositionMessage SPLIT_2 = new PositionMessage("At Split ee2!", "split ee2", new Box(58, 119, 124, 60, 123, 126), new int[]{1, 2}); - static PositionMessage SAFE_2_HIGH = new PositionMessage("At High 2 Safespot!", "2 safespot", new Box(70, 127, 143.7, 57, 133, 146.7), new int[]{1, 2}); + static PositionMessage SS = new PositionMessage("At SS!", new String[]{"ss"}, new Box(107, 120, 93, 110, 121, 95), new int[]{0, 1}); + static PositionMessage EE2 = new PositionMessage("At EE2!", new String[]{"ee2", "early enter 2"}, new Box(57, 109, 130, 59, 110, 132), new int[]{1, 2}); + static PositionMessage HEE2 = new PositionMessage("At High EE2!", new String[]{"high ee2", "highee2", "hee2"}, new Box(59, 132, 138, 62, 133, 140), new int[]{1, 2}); + static PositionMessage EE3 = new PositionMessage("At EE3!", new String[]{"ee3", "early enter 3", "early entry 3"}, new Box(1, 109, 103, 3, 110, 106), new int[]{2, 3}); + static PositionMessage CORE = new PositionMessage("At Core!", new String[]{"core"}, new Box(53, 115, 51, 56, 116, 54), new int[]{2, 3, 4}); + static PositionMessage TUNNEL = new PositionMessage("Inside Goldor Tunnel!", new String[]{"tunnel"}, new Box(52, 114, 55, 57, 116, 58), new int[]{4, 5}); + static PositionMessage SAFE_2 = new PositionMessage("At 2 Safespot!", new String[]{"2 safespot", "ee2 safespot", "safespot ee2", "s2 safespot", "safespot s2"}, new Box(46, 109, 121.987, 49, 110, 121.988), new int[]{1, 2}); + static PositionMessage SAFE_3 = new PositionMessage("At 3 Safespot!", new String[]{"3 safespot", "ee3 safespot", "freaky ee3", "freak ee", "safespot s3", "safespot 3"}, new Box(18, 121, 91, 19, 126, 99), new int[]{2, 3}); + static PositionMessage SPLIT_2 = new PositionMessage("At Split ee2!", new String[]{"split ee2", "splitee2", "mage term"}, new Box(58, 119, 124, 60, 123, 126), new int[]{1, 2}); + static PositionMessage SAFE_2_HIGH = new PositionMessage("At High 2 Safespot!", new String[]{"2 safespot"}, new Box(70, 127, 143.7, 57, 133, 146.7), new int[]{1, 2}); public static void init() { ClientTickEvents.END_CLIENT_TICK.register(PositionMessages::tick); @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.maxor; import blade.addon.utils.Constants; import blade.addon.utils.Location; @@ -0,0 +1,59 @@ +package blade.addon.features.dungeon.f7.maxor; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.TextUtil; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; + +public class MaxorStun { + + private static final int TOTAL_TICKS = 240; + + private static int tick = 0; + private static boolean stunned = false; + + public static void init() { + + Events.ON_GAME_MESSAGE.register(text -> { + if (!Location.inDungeon() || !Phase.inP1()) + return false; + String string = text.getString(); + + if (string.equals("[BOSS] Maxor: THAT BEAM! IT HURTS! IT HURTS!!") || string.equals("[BOSS] Maxor: YOU TRICKED ME!")) { + stunned = true; + } else if (string.equals("⚠ Maxor is enraged! ⚠")) { + tick = TOTAL_TICKS; + stunned = false; + } + + return false; + }); + + Events.ON_SERVER_TICK.register(() -> { + if (stunned) { + tick = Math.max(0, tick - 1); + } + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + stunned = false; + tick = TOTAL_TICKS; + return false; + }); + } + + public static boolean display() { + return tick > 0 && Location.inDungeon() && Phase.inP1() && Floor7.maxorStunDuration && stunned; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawPrefixedText(component, context, "Stunned", TextUtil.formatTicks(tick)); + } + + +} @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.storm; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.storm; import blade.addon.utils.Constants; import blade.addon.utils.Location; @@ -44,7 +44,7 @@ public class PillarExplode { } public static void renderTimer(HUDComponent component, DrawContext context) { - int color = tick < 6 ? Constants.GREEN_COLOR : Constants.RED_COLOR; + int color = tick < 6 ? Constants.GREEN : Constants.RED; RenderUtils.drawTimer(component, context, tick, color); } @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.storm; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.utils.Constants; @@ -34,7 +34,7 @@ public class GoldorTickTimer { public static void render(HUDComponent component, DrawContext context) { double num = tick * Constants.TICK_DURATION; double mod = num % 3; - int color = (mod < 1? Constants.GREEN_COLOR: mod < 2? Constants.ORANGE_COLOR: Constants.RED_COLOR); + int color = (mod < 1? Constants.GREEN: mod < 2? Constants.ORANGE: Constants.RED); if (Floor7.inDeathTicks) num = mod; RenderUtils.drawTimer(component, context, num, color); @@ -34,6 +34,6 @@ public class TermStartTimer { public static void render(HUDComponent component, DrawContext context) { double num = tick * Constants.TICK_DURATION; - RenderUtils.drawCenteredText(context, component, Text.literal(Constants.DECIMAL_FORMAT.format(num)), Constants.YELLOW_COLOR); + RenderUtils.drawCenteredText(context, component, Text.literal(Constants.DECIMAL_FORMAT.format(num)), Constants.YELLOW); } } @@ -0,0 +1,156 @@ +package blade.addon.features.filter; + +import config.practical.utilities.Constants; +import config.practical.utilities.DrawHelper; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.Click; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.input.CharInput; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; +import net.minecraft.util.math.MathHelper; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class FilterEntry extends TextFieldWidget { + + private static final Identifier CROSS = Identifier.of(blade.addon.utils.Constants.NAMESPACE, "cross"); + + private static final int HEIGHT = 20; + private static final int INPUT_COLOR = 0xff222222; + + private static final int SPRITE_SIZE = 16; + private static final int SPRITE_WIDTH_AREA = SPRITE_SIZE + 10; + private int maxLength; + private int selectionEnd; + private Consumer<String> changedListener; + + private final int index; + private final FilterList parent; + + public FilterEntry(Supplier<String> supplier, Consumer<String> consumer, int index, FilterList parent) { + super(MinecraftClient.getInstance().textRenderer, Constants.WIDGET_WIDTH, HEIGHT, Text.empty()); + this.setMaxLength(100); + this.setText(supplier.get()); + this.setChangedListener(consumer); + this.index = index; + this.parent = parent; + } + + @Override + public void renderWidget(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + DrawHelper.drawBackground(context, getX(), super.getY(), width - SPRITE_WIDTH_AREA, height, INPUT_COLOR); + Pair<Integer, Integer> pos = getRemovePos(); + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, CROSS, pos.getLeft(), pos.getRight(), SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); + super.renderWidget(context, mouseX, mouseY, deltaTicks); + } + + @Override + public boolean charTyped(CharInput input) { + if (!this.isActive()) { + return false; + } else if (input.isValidChar() || isValid(input)) { + this.write(input.asString()); + return true; + } else { + return false; + } + } + + + private boolean isValid(CharInput input) { + return input.asString().contains("§"); + } + + /** + * A slightly modified version of the TextFieldWidget write(String) + * because it removes chars like § + * + * @param text The text to add + */ + @Override + public void write(String text) { + int i = Math.min(getCursor(), this.selectionEnd); + int j = Math.max(getCursor(), this.selectionEnd); + int k = this.maxLength - getText().length() - (i - j); + if (k > 0) { + //String string = StringHelper.stripInvalidChars(text); + String string = text; + int l = string.length(); + if (k < l) { + if (Character.isHighSurrogate(string.charAt(k - 1))) { + k--; + } + + string = string.substring(0, k); + l = k; + } + String string2 = new StringBuilder(getText()).replace(i, j, string).toString(); + setText(string2); + this.setSelectionStart(i + l); + this.setSelectionEnd(getCursor()); + changedListener.accept(getText()); + } + } + + @Override + public void setSelectionEnd(int index) { + this.selectionEnd = MathHelper.clamp(index, 0, getText().length()); + super.setSelectionEnd(index); + } + + @Override + public void setMaxLength(int maxLength) { + this.maxLength = maxLength; + super.setMaxLength(maxLength); + } + + @Override + public void setChangedListener(Consumer<String> changedListener) { + this.changedListener = changedListener; + super.setChangedListener(changedListener); + } + + @Override + public int getY() { + return super.getY(); + } + + @Override + public int getInnerWidth() { + return width - SPRITE_WIDTH_AREA - 8; + } + + @Override + public boolean drawsBackground() { + return false; + } + + private Pair<Integer, Integer> getRemovePos() { + return new Pair<>(getX() + width - SPRITE_SIZE - 5, getY() + (height - SPRITE_SIZE) / 2); + } + + private boolean inRemovalBounds(double x, double y) { + Pair<Integer, Integer> pos = getRemovePos(); + return x >= pos.getLeft() && x <= pos.getLeft() + SPRITE_SIZE && y >= pos.getRight() && y <= pos.getRight() + SPRITE_SIZE; + } + + @Override + public void onClick(Click click, boolean doubled) { + double x = click.x(); + double y = click.y(); + + if (inRemovalBounds(x, y)) { + parent.removeFilter(index); + return; + } + + //make sure you cant click around the button accidentally + if (width + getX() - SPRITE_WIDTH_AREA < x) return; + super.onClick(click, doubled); + } +} @@ -0,0 +1,93 @@ +package blade.addon.features.filter; + +import blade.addon.features.notifications.Notifications; +import config.practical.ConfigScroll; +import config.practical.utilities.Constants; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.Window; +import net.minecraft.text.Text; +import org.joml.Matrix3x2fStack; + +public class FilterList extends Screen { + + private static final int TITLE_COLOR = 0xffffffff; + private static final float TITLE_SCALAR = 1.5f; + private static final int TITLE_Y_OFFSET = 20; + + private static final int BUTTON_HEIGHT = 30; + + private final Screen parent; + private final ConfigScroll scroll; + private final ButtonWidget addFilter; + + public FilterList() { + super(Text.literal("Filter")); + + MinecraftClient client = MinecraftClient.getInstance(); + parent = client.currentScreen; + Window window = client.getWindow(); + + addFilter = ButtonWidget.builder(Text.literal("Add Filter"), this::addFilter).position((window.getScaledWidth() - Constants.WIDGET_WIDTH) / 2, TITLE_Y_OFFSET + 16).width(100).build(); + scroll = new ConfigScroll(0, BUTTON_HEIGHT + TITLE_Y_OFFSET + 16, window.getScaledWidth(), window.getScaledHeight() - BUTTON_HEIGHT, Constants.WIDGET_WIDTH); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + super.render(context, mouseX, mouseY, deltaTicks); + + float centerX = (MinecraftClient.getInstance().getWindow().getScaledWidth() - (this.textRenderer.getWidth(this.title) * TITLE_SCALAR)) / 2; + Matrix3x2fStack stack = context.getMatrices(); + stack.pushMatrix(); + stack.translate(centerX, TITLE_Y_OFFSET); + stack.scale(TITLE_SCALAR, TITLE_SCALAR); + context.drawText(this.textRenderer, this.title, 0, 0, TITLE_COLOR, true); + stack.popMatrix(); + } + + @Override + protected void init() { + super.init(); + this.addDrawableChild(scroll); + this.addDrawableChild(addFilter); + updateList(); + } + + private void updateList() { + scroll.children().clear(); + + for (int i = 0; i < Filters.filters.size(); i++) { + int finalI = i; + scroll.add(new FilterEntry(() -> Filters.filters.get(finalI), string -> { + //race condition check + if (finalI >= Filters.filters.size()) return; + Filters.filters.set(finalI, string); + }, finalI, this)); + } + + scroll.update(); + scroll.setScrollY(0); + } + + @Override + public void close() { + assert this.client != null; + Notifications.save(); + this.client.setScreen(this.parent); + Filters.filterManager.save(); + } + + private void addFilter(ButtonWidget buttonWidget) { + Filters.filters.add(""); + updateList(); + } + + public void removeFilter(int index) { + if (Filters.filters.size() <= index) return; + Filters.filters.remove(index); + updateList(); + } + +} @@ -0,0 +1,31 @@ +package blade.addon.features.filter; + +import blade.addon.utils.config.FolderUtility; +import config.practical.manager.ConfigManager; +import config.practical.manager.ConfigValue; +import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; + +import java.util.ArrayList; +import java.util.List; + +public class Filters { + + public static final ConfigManager filterManager = new ConfigManager(FolderUtility.CONFIG_PATH + FolderUtility.FILTERS_NAME, + List.of(Filters.class)); + + @ConfigValue + public static ArrayList<String> filters = new ArrayList<>(); + + public static void init() { + filterManager.load(); + ClientReceiveMessageEvents.ALLOW_GAME.register((message, overlay) -> { + if (overlay) return true; + String string = message.getString(); + for (String filter : filters) { + if (string.matches(filter)) return false; + } + return true; + }); + } + +} @@ -1,4 +0,0 @@ -package blade.addon.features.highlight; - -public class Highlight { -} @@ -43,14 +43,14 @@ public class MimicHighlight { private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { - if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled()) return; + if (!MobHighlight.highlightMimicChests || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicFilledColor); mimics.forEach(mimic -> RenderUtils.renderFilled(matrixStack, consumer, box.offset(mimic.getPos()), rgba)); } private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { - if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline()) return; + if (!MobHighlight.highlightMimicChests || !MobHighlight.renderOutline()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); mimics.forEach(mimic -> RenderUtils.renderOutline(matrixStack, consumer, box.offset(mimic.getPos()), rgba)); @@ -62,7 +62,7 @@ public class TeammateHighlight { } if (Dungeons.renderClassName) { - Text text = Text.literal(player.getName().getString()).withColor(color).append(Text.literal(" [" + DungeonClass.getChar(clazz) + "]").withColor(Constants.YELLOW_COLOR)); + Text text = Text.literal(player.getName().getString()).withColor(color).append(Text.literal(" [" + DungeonClass.getChar(clazz) + "]").withColor(Constants.YELLOW)); Vec3d pos = EntityUtil.getLerpedPos(player); RenderUtils.renderText(context, matrixStack, text, pos.getX(), pos.getY() + 2.75, pos.getZ(), 2); } @@ -28,7 +28,7 @@ class NotificationEntry extends ClickableWidget { private final Notification notification; public NotificationEntry(NotificationList parent, Notification notification) { - super(0, 0, Constants.WIDGET_WIDTH, 30, Text.empty()); + super(0, 0, Constants.WIDGET_WIDTH, 28, Text.empty()); this.parent = parent; this.notification = notification; } @@ -25,7 +25,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class Notifications { private static final String filePath = FolderUtility.CONFIG_PATH + FolderUtility.NOTIFICATIONS_NAME; - private static final String WAYPOINTS_NAME = "waypoints"; + private static final String NOTIFICATIONS_NAME = "notifications"; @ConfigValue public static CopyOnWriteArrayList<Notification> notifications; @@ -82,7 +82,7 @@ public class Notifications { JsonObject obj = new JsonObject(); Gson gson = new Gson(); - obj.add(WAYPOINTS_NAME, gson.toJsonTree(notifications)); + obj.add(NOTIFICATIONS_NAME, gson.toJsonTree(notifications)); JsonElement tree = gson.toJsonTree(obj); try (FileWriter writer = new FileWriter(filePath)) { @@ -101,7 +101,15 @@ public class Notifications { } Gson gson = new Gson(); JsonObject object = gson.fromJson(jsonContent, JsonObject.class); - JsonElement element = object.get(WAYPOINTS_NAME); + + JsonElement element; + if (object.has("waypoints")) { + //backwards compatibility because I forgot to change the name + //before release... + element = object.get("waypoints"); + } else { + element = object.get(NOTIFICATIONS_NAME); + } if (!element.isJsonArray()) return; JsonArray array = element.getAsJsonArray(); @@ -0,0 +1,95 @@ +package blade.addon.features.other; + +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.ItemUtil; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ArrowSwapper { + + private static final int TOTAL_TICK = 20; + + private static final Pattern ARROW_PATTERN = Pattern.compile("^You set your selected arrow type to (.+)!$"); + private static final Text NOT_SCANNED_TEXT = Text.literal("Cant find arrow").formatted(Formatting.RED); + + private static Text displayedText = NOT_SCANNED_TEXT; + private static int tick = 0; + + public static void init() { + ClientTickEvents.END_WORLD_TICK.register(world -> { + tick = Math.max(0, tick - 1); + }); + + Events.ON_GAME_MESSAGE.register(text -> { + String string = text.getString(); + + Matcher matcher = ARROW_PATTERN.matcher(string); + if (!matcher.find()) return false; + + List<Text> siblings = text.getSiblings(); + if (siblings.size() < 2) return false; + setDisplayedText(siblings.get(1)); + + return false; + }); + + Events.ON_SLOT_CHANGE.register((slot, item) -> { + if (displayedText != NOT_SCANNED_TEXT) return false; + if (!ItemUtil.itemHasName(item, "Arrow Swapper")) return false; + + if (item ==null) return false; + LoreComponent lore = item.get(DataComponentTypes.LORE); + if (lore == null) return false; + + List<Text> lines = lore.lines(); + if (lines.isEmpty()) return false; + + Pattern p = Pattern.compile("^Selected: (.+)$"); + + for (Text line : lines) { + Matcher matcher = p.matcher(line.getString()); + if (matcher.find()) { + List<Text> foundLine = line.getSiblings(); + if (foundLine.size() < 2) return false; + setDisplayedText(foundLine.get(1)); + break; + } + } + return false; + }); + } + + private static void setDisplayedText(Text text) { + if (displayedText != NOT_SCANNED_TEXT) { + tick = TOTAL_TICK; + } + displayedText = text; + } + + public static boolean display() { + return ExtraOptions.displayCurrentArrow; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawText(context, component, displayedText, 0xffffffff); + } + + public static boolean displayNotification() { + return ExtraOptions.arrowSwapNotification && tick > 0; + } + + public static void renderNotification(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, displayedText, 0xffffffff); + } +} …… diff 过长已截断 …… |
| - added a toggle for key notification on all classes - added a toggle to instantly display place crystal reminder - added old bonzo staff sound - added time until quiz question - fixed leap getting blocked in relics (ops) (needs testing)
- fixed when transparency was 0 it still kind of rendered
- fixed some colors being wrong
- fixed the new mob highlight being bad, Thanks to ratph6 for the legendary tips 查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 5 ++ src/main/java/blade/addon/features/dungeon/ChestCounter.java | 3 +- src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 18 +++++-- src/main/java/blade/addon/features/dungeon/QuizTimer.java | 54 +++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 6 ++- src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 2 +- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 25 +++++++--- src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 6 ++- src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 2 +- src/main/java/blade/addon/features/highlight/BatHighlight.java | 2 +- src/main/java/blade/addon/features/highlight/Highlight.java | 4 ++ src/main/java/blade/addon/features/highlight/MimicHighlight.java | 2 +- src/main/java/blade/addon/features/highlight/MobHighlight.java | 166 +++++++++++++++++++++-------------------------------------------- src/main/java/blade/addon/features/highlight/SheepHighlight.java | 2 +- src/main/java/blade/addon/features/highlight/WitherHighlight.java | 4 +- src/main/java/blade/addon/features/other/KickedTimer.java | 2 +- src/main/java/blade/addon/features/other/RagDisplay.java | 6 +-- src/main/java/blade/addon/features/sound/BonzoSound.java | 29 ++++++++++++ src/main/java/blade/addon/mixin/ArmorStandEntityMixin.java | 23 --------- src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 4 -- src/main/java/blade/addon/mixin/ItemStackMixin.java | 17 ++++++- src/main/java/blade/addon/utils/Misc.java | 5 +- src/main/java/blade/addon/utils/config/Config.java | 14 ++++-- src/main/java/blade/addon/utils/config/components/Components.java | 4 ++ src/main/java/blade/addon/utils/config/values/Dungeons.java | 12 +++-- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 ++ src/main/java/blade/addon/utils/config/values/Floor7.java | 3 ++ src/main/java/blade/addon/utils/interfaces/ArmourStandHolder.java | 10 ---- src/main/java/blade/addon/utils/rendering/RenderLayers.java | 1 - src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 1 - src/main/java/blade/addon/utils/rendering/RenderUtils.java | 23 +++++++-- src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 4 +- src/main/resources/assets/blade-addons/sounds.json | 11 +++++ src/main/resources/assets/blade-addons/sounds/ghast-moan-1.ogg | Bin 0 -> 7986 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan-2.ogg | Bin 0 -> 8909 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan-3.ogg | Bin 0 -> 8925 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan-4.ogg | Bin 0 -> 9393 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan-5.ogg | Bin 0 -> 14107 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan-6.ogg | Bin 0 -> 18305 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan-7.ogg | Bin 0 -> 9222 bytes src/main/resources/assets/blade-addons/sounds/ghast-moan.ogg | Bin 0 -> 7986 bytes src/main/resources/blade-addons.mixins.json | 1 - 44 files changed, 281 insertions(+), 197 deletions(-) @@ -13,7 +13,7 @@ loader_version=0.18.4 loom_version=1.14-SNAPSHOT # Mod Properties -mod_version=2.3.1 +mod_version=2.3.2 maven_group=blade.addon archives_base_name=blade-addons @@ -7,6 +7,7 @@ import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.ItemHighlight; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.LeapMessage; +import blade.addon.features.dungeon.QuizTimer; import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; @@ -42,6 +43,7 @@ import blade.addon.features.other.KickedTimer; import blade.addon.features.other.PracticeSS; import blade.addon.features.other.RagDisplay; import blade.addon.features.other.SelectedPet; +import blade.addon.features.sound.BonzoSound; import blade.addon.utils.Commands; import blade.addon.utils.Keybinds; import blade.addon.utils.Location; @@ -59,6 +61,7 @@ import blade.addon.utils.dungeon.Section; import blade.addon.utils.events.CustomEvents; import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; public class Bladeaddons implements ModInitializer { @Override @@ -124,5 +127,7 @@ public class Bladeaddons implements ModInitializer { InvincibilityDuration.init(); TeammateHighlight.init(); SectionProgress.init(); + BonzoSound.init(); + QuizTimer.init(); } } \ No newline at end of file @@ -7,6 +7,7 @@ import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -71,7 +72,7 @@ public class ChestCounter { int y = component.getScaledY(); if (hasUpdatedData) { - context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, Dungeons.chestCountColor , true); + RenderUtils.drawPrefixedText(component, context, "Chests", Math.min(chestDisplayCount + countedChests, 60) + ""); } else { context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, Constants.RED_COLOR, true); @@ -43,7 +43,6 @@ public class KeyNotifier { public static void init() { ClientTickEvents.END_WORLD_TICK.register((world) -> { if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return; - if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return; for (Entity entity : world.getEntities()) { if (entity instanceof ArmorStandEntity armorStand && !foundKeys.contains(entity)) { @@ -56,7 +55,9 @@ public class KeyNotifier { if (uuid.equals(WITHER_UUID)) { foundKeys.add(entity); hasKey = true; - Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + if (isValidClass()) { + Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + } return; } @@ -64,7 +65,10 @@ public class KeyNotifier { foundKeys.add(entity); isBloodKey = true; hasKey = true; - Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + + if (isValidClass()) { + Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + } return; } } @@ -73,7 +77,7 @@ public class KeyNotifier { Events.ON_GAME_MESSAGE.register(message -> { if (!Location.inDungeon() || !hasKey || !Dungeons.enableKeyNotifier) return false; - if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return false; + if (!isValidClass()) return false; Matcher matcher = AUTOMATIC_PICKUP_PATTERN.matcher(message.getString()); if (matcher.find()) { @@ -101,8 +105,12 @@ public class KeyNotifier { }); } + private static boolean isValidClass() { + return Dungeons.displayKeyForAllClasses || DungeonClass.isClass(DungeonClass.ARCHER) || DungeonClass.isClass(DungeonClass.MAGE); + } + public static boolean display() { - return Location.inDungeon() && hasKey; + return Location.inDungeon() && hasKey && isValidClass(); } public static void render(HUDComponent component, DrawContext context) { @@ -0,0 +1,54 @@ +package blade.addon.features.dungeon; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; + +public class QuizTimer { + + private static final int START_DURATION = 220; + private static final int QUESTION_DURATION = 100; + + private static int tick = 0; + + public static void init() { + + Events.ON_GAME_MESSAGE.register(text -> { + if (!Location.inDungeon()) return false; + + String string = text.getString(); + if (string.equals("[STATUE] Oruo the Omniscient: I am Oruo the Omniscient. I have lived many lives. I have learned all there is to know.")) { + tick = START_DURATION; + } else if (string.equals("[STATUE] Oruo the Omniscient: 2 questions left... Then you will have proven your worth to me!")) { + tick = QUESTION_DURATION; + } else if (string.equals("[STATUE] Oruo the Omniscient: One more question!")) { + tick = QUESTION_DURATION; + } + + return false; + }); + + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + tick = 0; + return false; + }); + } + + public static boolean display() { + return Dungeons.quizTimer && tick > 0; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawPrefixedTimer(component, context, "Quiz", tick); + } + + +} @@ -42,6 +42,6 @@ public class WarpCooldown { public static void render(HUDComponent component, DrawContext context) { double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); - RenderUtils.drawPrefixedTimer(component, context, timeRemaining, "Warp Cooldown"); + RenderUtils.drawPrefixedTimer(component, context, "Warp Cooldown", timeRemaining); } } @@ -60,6 +60,10 @@ public class BossWaypoints { return place; } + public static boolean getIgnoreBoss() { + return ignoreBoss; + } + public static void setPlace(boolean shouldPlace) { place = shouldPlace; Misc.addChatMessage(Text.literal("Edit mode: ").append(Misc.getStatusText(place))); @@ -85,7 +89,7 @@ public class BossWaypoints { private static void addWaypoint(double x, double y, double z, double dx, double dy, double dz) { float[] colorAsFloat = RenderUtils.toFloats(Floor7.nextWaypointColor); - waypoints.add(new Waypoint(x, y, z, dx, dy, dz, colorAsFloat[0], colorAsFloat[1], colorAsFloat[2], colorAsFloat[3],Floor7.nextWaypointThroughWall)); + waypoints.add(new Waypoint(x, y, z, dx, dy, dz, colorAsFloat[0], colorAsFloat[1], colorAsFloat[2], colorAsFloat[3], Floor7.nextWaypointThroughWall)); save(); } @@ -104,7 +104,7 @@ public class CrystalSpawn { } public static boolean displayNotification() { - return tickSincePicked > REMINDER_TICK && Location.inDungeon() && Phase.inP1() && Floor7.crystalPlaceReminder && pickedUp; + return (Floor7.instantlyDisplayCrystalReminder || tickSincePicked > REMINDER_TICK) && Location.inDungeon() && Phase.inP1() && Floor7.crystalPlaceReminder && pickedUp; } public static void renderNotification(HUDComponent component, DrawContext context) { @@ -151,6 +151,8 @@ public class RelicTimer { BlockPos pos = result.getBlockPos(); + if (!isARelicPos(pos)) return false; + //skyblock menu check is there incase the item doesnt get updated if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu")) { if (Floor7.blockIncorrectRelicPlace) { @@ -162,7 +164,7 @@ public class RelicTimer { } } - if (pos.getX() == pickedupRelic.box.minX && (pos.getY() == pickedupRelic.box.minY || pos.getY() == pickedupRelic.box.minY - 1) && pos.getZ() == pickedupRelic.box.minZ) { + if (clickedRelic(pickedupRelic, pos)) { if (Floor7.enableRelicPlaceTime) { MutableText text = Text.literal("The ").formatted(Formatting.GREEN) .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) @@ -192,6 +194,22 @@ public class RelicTimer { } + private static boolean isARelicPos(BlockPos pos) { + try { + for (Relic relic : Relic.values()) { + if (clickedRelic(relic, pos)) return true; + } + } catch (Exception e) { + Misc.addChatMessage(Text.literal("Relic not found!")); + } + return false; + } + + private static boolean clickedRelic(Relic relic, BlockPos pos) { + if (relic == null) return false; + return (pos.getX() == relic.box.minX && (pos.getY() == relic.box.minY || pos.getY() == relic.box.minY - 1) && pos.getZ() == relic.box.minZ); + } + private static void reset() { tick = Floor7.relicSpawnTicks; pickedupRelic = null; @@ -225,11 +243,6 @@ public class RelicTimer { public static void printRelic() { Misc.addChatMessage(Text.literal("Relic: " + pickedupRelic)); - - } - - public static void debugCommands() { - } private static void worldRender(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { @@ -27,6 +27,10 @@ public class InvincibilityDuration { } public static void render(HUDComponent component, DrawContext context) { - RenderUtils.drawTimer(component, context, ticks, 0xffffffff); + int color = 0xffffffff; + if (Dungeons.useStatusColorForInvincibility) { + color = RenderUtils.getStatusColor(40, 20, ticks); + } + RenderUtils.drawTimer(component, context, ticks, color); } } @@ -49,7 +49,7 @@ public class LocationNotifier { color = DungeonClass.getColor(username); } - notification = Text.literal(username).withColor(color).append(Text.literal("§6" + message).setStyle(Style.EMPTY)); + notification = Text.literal(username).withColor(color).append(Text.literal("§e" + message).setStyle(Style.EMPTY)); ticks = Floor7.notificationDuration; for (int i = 0; i < Floor7.notificationRepetitions; i++) { @@ -23,7 +23,7 @@ public class BatHighlight { Events.ON_ENTITY_TRACKED.register((entity, world) -> { if (!Location.inDungeon() || !MobHighlight.mobHighlight) return false; - if (entity instanceof BatEntity bat) { + if (entity instanceof BatEntity bat && !bats.contains(bat)) { for (float health : BAT_HEALTHS) { if (health == bat.getHealth()) { bats.add(bat); @@ -0,0 +1,4 @@ +package blade.addon.features.highlight; + +public class Highlight { +} @@ -29,7 +29,7 @@ public class MimicHighlight { Events.ON_BLOCK_ENTITY.register(blockEntity -> { if (!Location.inDungeon()) return false; - if (blockEntity instanceof TrappedChestBlockEntity mimic) { + if (blockEntity instanceof TrappedChestBlockEntity mimic && !mimics.contains(mimic)) { mimics.add(mimic); } return false; @@ -3,23 +3,19 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.events.Events; -import blade.addon.utils.interfaces.ArmourStandHolder; import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.rendering.RenderingEvents; import config.practical.manager.ConfigValue; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.mob.EndermanEntity; -import net.minecraft.entity.mob.SkeletonEntity; -import net.minecraft.entity.mob.WitherSkeletonEntity; import net.minecraft.entity.mob.ZombieEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; @@ -29,10 +25,8 @@ import net.minecraft.text.Text; import net.minecraft.text.TextColor; import net.minecraft.util.math.Box; -import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.function.Predicate; public class MobHighlight { @@ -40,7 +34,8 @@ public class MobHighlight { STAR, TANK, MINI, FEL, ASSASSIN, MIMIC } - record DataHolder(Entity entity, MobHighlight.MobType type) {} + public record DataHolder(Entity entity, MobHighlight.MobType type) { + } public enum HighlightType { FILLED("Filled"), OUTLINE("Outline"), BOTH("Both"); @@ -57,11 +52,10 @@ public class MobHighlight { } } - private static final int DIAMOND_HELMET_ID = Item.getRawId(Items.DIAMOND_HELMET); - private static final int PLAYER_HEAD_ID = Item.getRawId(Items.PLAYER_HEAD); private static final int LEATHER_BOOTS_ID = Item.getRawId(Items.LEATHER_BOOTS); - private static final ConcurrentLinkedQueue<DataHolder> savedEntities = new ConcurrentLinkedQueue<>(); + private static final ConcurrentHashMap<Integer, Entity> foundEntities = new ConcurrentHashMap<>(); + public static final ConcurrentLinkedQueue<DataHolder> savedEntities = new ConcurrentLinkedQueue<>(); public static boolean dontRenderHighlight = false; @ConfigValue @@ -121,22 +115,12 @@ public class MobHighlight { public static int sheepOutlineColor = 0xffffffff; - public static void init() { - ClientTickEvents.END_CLIENT_TICK.register(client -> { - if (!Location.inDungeon()) return; - - ClientWorld world = client.world; - if (world == null) return; - for (Entity entity: world.getEntities()) { - if (entity instanceof ArmorStandEntity armorStand) { - ArmourStandHolder holder = (ArmourStandHolder) armorStand; - if (holder.blade_addons$hasBeenScanned()) continue; - holder.blade_addons$setScanned(true); - testArmourStand(armorStand, client); - } - } - savedEntities.removeIf(dataHolder -> dataHolder.entity.isRemoved()); + + Events.ON_ENTITY_SPAWNED.register((entity, world) -> { + if (entity instanceof ArmorStandEntity) return false; + foundEntities.put(entity.getId(), entity); + return false; }); Events.ON_ENTITY_TRACKED.register((entity, world) -> { @@ -148,6 +132,10 @@ public class MobHighlight { } } + if (entity instanceof ArmorStandEntity armorStand) { + testArmorStand(armorStand); + } + return false; }); @@ -162,35 +150,51 @@ public class MobHighlight { dontRenderHighlight = player.hasStatusEffect(StatusEffects.BLINDNESS); }); + ClientEntityEvents.ENTITY_UNLOAD.register((entity, world) -> { + if (entity == null) return; + int id = entity.getId(); + savedEntities.removeIf(dataHolder -> dataHolder.entity == entity); + foundEntities.remove(id); + }); + RenderingEvents.FILLED_ENTITY.register(MobHighlight::renderFilled); RenderingEvents.OUTLINE_ENTITY.register(MobHighlight::renderOutline); } - public static void testArmourStand(ArmorStandEntity armorStand, MinecraftClient client) { - Text text = armorStand.getCustomName(); - if (text == null) return; - String name = text.getString(); + private static void testArmorStand(ArmorStandEntity armorStand) { + MobType type = getType(armorStand); + if (type == null) return; - ClientWorld world = client.world; - if (world == null) return; + int idOffset = getIdOffset(armorStand); + if (idOffset < 0) return; - if (name.contains("Mimic")) { - attemptAddMob(armorStand, MobHighlight::isAPossibleMimic, 3.5, MobHighlight.MobType.MIMIC, world); - return; - } + int id = armorStand.getId() - idOffset; + Entity entity = foundEntities.getOrDefault(id, null); + if (entity == null) return; + foundEntities.remove(id); + savedEntities.add(new DataHolder(entity, type)); + } - if (!MobHighlight.containsStarText(text)) return; + public static MobType getType(ArmorStandEntity armorStand) { + Text text = armorStand.getCustomName(); + if (text == null) return null; + String name = text.getString(); + if (name.contains("King Midas")) return MobType.MINI; + if (name.contains("Mimic")) return MobType.MIMIC; + if (!MobHighlight.containsStarText(text)) return null; + if (name.contains("Fel")) return MobType.FEL; + if (isMiniBoss(name)) return MobType.MINI; + if (isTankMob(name)) return MobType.TANK; + return MobType.STAR; + } - if (name.contains("Fel")) { - attemptAddMob(armorStand, entity -> entity instanceof EndermanEntity, 4, MobHighlight.MobType.FEL, world); - } else if (isMiniBoss(name)) { - attemptAddMob(armorStand, MobHighlight::isMiniBoss, 4, MobHighlight.MobType.MINI, world); - } else if (isTankMob(name)) { - attemptAddMob(armorStand, MobHighlight::isAPossibleStaredMob, 3, MobHighlight.MobType.TANK, world); - } else { - attemptAddMob(armorStand, MobHighlight::isAPossibleStaredMob, 3, MobHighlight.MobType.STAR, world); - } + public static int getIdOffset(ArmorStandEntity armorStand) { + Text text = armorStand.getCustomName(); + if (text == null) return -1; + String name = text.getString(); + if (name.toLowerCase().contains("withermancer")) return 3; + return 1; } public static boolean containsStarText(Text text) { @@ -201,58 +205,19 @@ public class MobHighlight { if (color.getRgb() == 0xFFAA00 && sib.getString().equals("✯ ")) { return true; } - } return false; } public static boolean isTankMob(String name) { - return name.contains("Zombie Commander") || name.contains("Zombie Lord") || name.contains("Skeleton Lord")|| name.contains("Withermancer") || name.contains("Super Archer"); + return name.contains("Zombie Commander") || name.contains("Zombie Lord") || name.contains("Skeleton Lord") || name.contains("Withermancer") || name.contains("Super Archer"); } public static boolean isMiniBoss(String name) { return name.contains("Lost Adventurer") || name.contains("Angry Archaeologist") || name.contains("Frozen Adventurer"); } - public static void attemptAddMob(ArmorStandEntity armorStand, Predicate<Entity> requirements, double maxDistance, MobHighlight.MobType mobType, ClientWorld world) { - Entity closest = null; - double smallestDistance = maxDistance; - double maxY = armorStand.getY(); - Box boundingBox = Box.of(armorStand.getEntityPos().subtract(0, 0.5, 0), 2, 3, 2); - - - ArrayList<Entity> meetsRequirements = new ArrayList<>(); - - Iterable<Entity> entities = world.getEntities(); - entities.forEach(entity -> { - if (!entity.getBoundingBox().intersects(boundingBox)) return; - if (!requirements.test(entity)) return; - if (entity.getY() > maxY) return; - - meetsRequirements.add(entity); - }); - - for (Entity current : meetsRequirements) { - if (!current.getBoundingBox().intersects(boundingBox)) continue; - if (!requirements.test(current)) continue; - if (current.getY() > maxY) continue; - - double distance = armorStand.getEntityPos().distanceTo(current.getEntityPos()); - if (smallestDistance > distance) { - closest = current; - smallestDistance = distance; - } - - } - - if (closest == null) { - return; - } - - savedEntities.add(new DataHolder(closest, mobType)); - } - public static boolean isShadowAssassin(PlayerEntity player) { if (EntityUtil.isARealPlayer(player)) return false; ItemStack heldItem = player.getMainHandStack(); @@ -265,34 +230,6 @@ public class MobHighlight { return Item.getRawId(boots.getItem()) == LEATHER_BOOTS_ID; } - public static boolean isAPossibleStaredMob(Entity entity) { - return switch (entity) { - case ZombieEntity ignored -> true; - case SkeletonEntity ignored -> true; - case WitherSkeletonEntity ignored -> true; - case PlayerEntity ignored -> !EntityUtil.isARealPlayer(entity) && !EntityUtil.isClientPlayer(entity) && !isMiniBoss(entity); - default -> false; - }; - } - - public static boolean isAPossibleMimic(Entity entity) { - if (entity instanceof ZombieEntity zombie) { - return zombie.isBaby(); - } - return false; - } - - public static boolean isMiniBoss(Entity entity) { - if (entity instanceof PlayerEntity player) { - if (EntityUtil.isARealPlayer(player)) return false; - ItemStack helmet = player.getInventory().getStack(39); - int id = Item.getRawId(helmet.getItem()); - return id == DIAMOND_HELMET_ID || id == PLAYER_HEAD_ID; - } - - return false; - } - public static int getFilledColor(MobType mob) { return switch (mob) { case STAR -> starFilledColor; @@ -342,6 +279,7 @@ public class MobHighlight { return box; } + private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || dontRenderHighlight || !MobHighlight.renderFilled()) return; @@ -21,7 +21,7 @@ public class SheepHighlight { Events.ON_ENTITY_SPAWNED.register((entity, world) -> { if (!Location.inDungeon()) return false; - if (entity instanceof SheepEntity sheep) { + if (entity instanceof SheepEntity sheep && !sheeps.contains(sheep)) { sheeps.add(sheep); } return false; @@ -28,7 +28,7 @@ public class WitherHighlight { if (Phase.inBoss()) { if (entity instanceof WitherEntity wither) { - if (wither.getHealth() != WITHER_BORN_HEALTH) { + if (wither.getHealth() != WITHER_BORN_HEALTH && !withers.contains(wither)) { withers.add(wither); } } @@ -42,7 +42,7 @@ public class WitherHighlight { return false; }); - ClientTickEvents.END_CLIENT_TICK.register(client -> withers.removeIf(wither -> wither.isRemoved() || wither.isDead())); + ClientTickEvents.END_CLIENT_TICK.register(client -> {withers.removeIf(wither -> wither.isRemoved() || wither.isDead());}); RenderingEvents.FILLED_ENTITY.register(WitherHighlight::renderFilled); RenderingEvents.OUTLINE_ENTITY.register(WitherHighlight::renderOutline); @@ -34,7 +34,7 @@ public class KickedTimer { long diff = System.currentTimeMillis() - kickedTime; if (diff > 60 * 1000) isKicked = false; double drawnTime = Math.min(diff / 1000.0, 60.0); - RenderUtils.drawPrefixedTimer(component, context, drawnTime, "Time kicked"); + RenderUtils.drawPrefixedTimer(component, context, "Time kicked", drawnTime); } } @@ -1,7 +1,7 @@ package blade.addon.features.other; import blade.addon.utils.Constants; -import blade.addon.utils.Scheduler; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.data.ItemUtil; import blade.addon.utils.events.Events; @@ -34,10 +34,10 @@ public class RagDisplay { } if (ExtraOptions.useOldRagSound) { - Scheduler.scheduleSound(OLD_RAG_SOUND, 1, 1.4920635223388672f); + Misc.sendSound(OLD_RAG_SOUND, volume, pitch); return true; } else if (ExtraOptions.useCustomRagSound) { - Scheduler.scheduleSound(ExtraOptions.ragSound); + Misc.sendSound(ExtraOptions.ragSound); return true; } return false; @@ -0,0 +1,29 @@ +package blade.addon.features.sound; + +import blade.addon.utils.Constants; +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Identifier; + +public class BonzoSound { + + private static final SoundEvent OLD_BONZO_SOUND = SoundEvent.of(Identifier.of(Constants.NAMESPACE, "ghast-moan")); + + + public static void init() { + Events.ON_SOUND.register((soundEvent, volume, pitch) -> { + if (volume != 1.0 || soundEvent != SoundEvents.ENTITY_GHAST_WARN) return false; + + if (ExtraOptions.oldBonzoSound) { + Misc.sendSound(OLD_BONZO_SOUND, volume, pitch); + return true; + } + + return ExtraOptions.disableBonzoSound; + }); + } + +} @@ -1,23 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.utils.interfaces.ArmourStandHolder; -import net.minecraft.entity.decoration.ArmorStandEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -@Mixin(ArmorStandEntity.class) -public class ArmorStandEntityMixin implements ArmourStandHolder { - - @Unique - private boolean scanned = false; - - @Override - public boolean blade_addons$hasBeenScanned() { - return scanned; - } - - @Override - public void blade_addons$setScanned(boolean value) { - scanned = value; - } -} @@ -69,10 +69,6 @@ public class ClientPlayNetworkHandlerMixin { ci.cancel(); } - if (ExtraOptions.disableBonzoSound && volume == 1.0 && event == SoundEvents.ENTITY_GHAST_WARN) { - ci.cancel(); - } - if (Debug.sendSound) { Misc.addChatMessage(Text.literal("Sound: " + event.id() + " Volume: " + volume + " Pitch: " + pitch)); } @@ -38,85 +38,100 @@ public class ItemStackMixin implements ItemRarityHolder, PetHolder, StarCountHol @Unique MaskType maskType = null; + @Unique @Override public ItemRarity blade_addons$getItemRarity() { return itemRarity; } + @Unique @Override public boolean blade_addons$hasItemRarity() { return itemRarity != ItemRarity.NONE; } + @Unique @Override public void blade_addons$setItemRarity(ItemRarity itemRarity) { this.itemRarity = itemRarity; } + @Unique @Override public boolean blade_addons$hasScanned() { return itemRarity != null; } + @Unique @Override public boolean blade_addons$hasScannedPet() { return scannedPet; } + @Unique @Override public void blade_addons$setSelected(boolean selected) { selectedPet = selected; scannedPet = true; } + @Unique @Override public boolean blade_addons$isSelected() { return selectedPet; } + @Unique @Override public boolean blade_addons$hasScannedStars() { return scannedStars; } + @Unique @Override public void blade_addons$setStarCount(int count) { starCount = count; scannedStars = true; } - + @Unique @Override public int blade_addons$getStarCount() { return starCount; } + @Unique @Override public boolean blade_addons$hasScannedProtection() { return scannedProtected; } + @Unique @Override public void blade_addons$setProtected(boolean value) { scannedProtected = true; isItemProtected = value; } + @Unique @Override public boolean blade_addons$isProtected() { return isItemProtected; } + @Unique @Override public boolean blade_addons$scannedMask() { return maskType != null; } + @Unique @Override public void blade_addons$setMask(MaskType maskType) { this.maskType = maskType; } + @Unique @Override public MaskType blade_addons$getMask() { return maskType; @@ -67,7 +67,7 @@ public class Misc { } public static void sendSound(SoundEvent soundEvent, float volume, float pitch) { - ClientPlayerEntity player = INSTANCE.player; + ClientPlayerEntity player = INSTANCE.player; if (player == null) return; forceMainThread(() -> player.playSound(soundEvent, volume, pitch)); } @@ -75,7 +75,8 @@ public class Misc { public static void sendSound(SoundData soundData) { sendSound(SoundEvent.of(soundData.getSound()), soundData.getVolume(), soundData.getPitch()); } - public static void forceMainThread(Runnable runnable) { + + public static void forceMainThread(Runnable runnable) { if (INSTANCE.isOnThread()) { runnable.run(); } else { @@ -75,8 +75,8 @@ public class Config { invincibility.add(new ConfigOptions<>(Text.literal("Display when"), InvincibilityTimer.DisplayWhen.values(), () -> Dungeons.displayWhen, when -> Dungeons.displayWhen = when)); invincibility.add(new ConfigBool(Text.literal("Use sprites"), () -> Dungeons.useSprites, bool -> Dungeons.useSprites = bool)); invincibility.add(new ConfigBool(Text.literal("Show title on proc"), () -> Dungeons.showProcTitle, bool -> Dungeons.showProcTitle = bool)); - invincibility.add(new ConfigBool(Text.literal("invincibility duration"), () -> Dungeons.InvincibilityDuration, bool -> Dungeons.InvincibilityDuration = bool)); - + invincibility.add(new ConfigBool(Text.literal("Invincibility duration"), () -> Dungeons.InvincibilityDuration, bool -> Dungeons.InvincibilityDuration = bool)); + invincibility.add(new ConfigBool(Text.literal("Duration changing color"), () -> Dungeons.useStatusColorForInvincibility, bool -> Dungeons.useStatusColorForInvincibility = bool)); dungeons.add(invincibility); ConfigSection classColors = new ConfigSection(Text.literal("Class Colors")); @@ -106,7 +106,6 @@ public class Config { chests.add(new ConfigBool(Text.literal("Only display after run is over"), () -> Dungeons.onlyAfterRunOver, bool -> Dungeons.onlyAfterRunOver = bool)); chests.add(new ConfigBool(Text.literal("Send chest count warning"), () -> Dungeons.sendChestWarning, bool -> Dungeons.sendChestWarning = bool)); chests.add(new ConfigInt(Text.literal("Warning at chest"), () -> Dungeons.chestWarningCount, num -> Dungeons.chestWarningCount = num, 1, 1, 60)); - chests.add(new ConfigColor(Text.literal("Widget color"), () -> Dungeons.chestCountColor, color -> Dungeons.chestCountColor = color, "chest-color", false)); dungeons.add(chests); dungeons.add(new ConfigBool(Text.literal("Leap message"), () -> Dungeons.enableLeapMessages, bool -> Dungeons.enableLeapMessages = bool)); @@ -118,6 +117,7 @@ public class Config { dungeons.add(expo); dungeons.add(new ConfigBool(Text.literal("Notification on key spawn"), () -> Dungeons.enableKeyNotifier, bool -> Dungeons.enableKeyNotifier = bool)); + dungeons.add(new ConfigBool(Text.literal("Display key noti for all classes"), () -> Dungeons.displayKeyForAllClasses, bool -> Dungeons.displayKeyForAllClasses = bool)); dungeons.add(new ConfigBool(Text.literal("Secret spawn timer"), () -> Dungeons.enableSecretSpawnTimer, bool -> Dungeons.enableSecretSpawnTimer = bool)); dungeons.add(new ConfigBool(Text.literal("Item highlight"), () -> Dungeons.highlightItems, bool -> Dungeons.highlightItems = bool)); dungeons.add(new ConfigBool(Text.literal("Combine screen notifications"), () -> Dungeons.combineScreenNotifications, bool -> Dungeons.combineScreenNotifications = bool)); @@ -127,6 +127,7 @@ public class Config { dungeons.add(new ConfigBool(Text.literal("Mask cooldown highlight"), () -> Dungeons.maskHighlight, bool -> Dungeons.maskHighlight = bool)); dungeons.add(new ConfigBool(Text.literal("Highlight teammates"), () -> Dungeons.highlightTeammates, bool -> Dungeons.highlightTeammates = bool)); dungeons.add(new ConfigBool(Text.literal("Render class names"), () -> Dungeons.renderClassName, bool -> Dungeons.renderClassName = bool)); + dungeons.add(new ConfigBool(Text.literal("Time until quiz question"), () -> Dungeons.quizTimer, bool -> Dungeons.quizTimer = bool)); return dungeons; } @@ -138,6 +139,7 @@ public class Config { ConfigSection waypoints = new ConfigSection(Text.literal("Waypoints")); waypoints.add(new ConfigBool(Text.literal("Enable boss waypoints"), () -> Floor7.enableBossWaypoints, bool -> Floor7.enableBossWaypoints = bool)); waypoints.add(new ConfigBool(Text.literal("Enable placing waypoints"), BossWaypoints::getPlace, BossWaypoints::setPlace)); + waypoints.add(new ConfigBool(Text.literal("temporarily ignore boss"), BossWaypoints::getIgnoreBoss, BossWaypoints::setIgnoreBoss)); waypoints.add(new ConfigColor(Text.literal("Next waypoint color"), () -> Floor7.nextWaypointColor, color -> Floor7.nextWaypointColor = color, "next-waypoint-color", true)); waypoints.add(new ConfigBool(Text.literal("Next waypoint no depth check"), () -> Floor7.nextWaypointThroughWall, bool -> Floor7.nextWaypointThroughWall = bool)); floor7.add(waypoints); @@ -145,6 +147,7 @@ public class Config { ConfigSection maxor = new ConfigSection(Text.literal("Maxor")); maxor.add(new ConfigBool(Text.literal("Crystal Spawn Time"), () -> Floor7.enableCrystalSpawnTime, bool -> Floor7.enableCrystalSpawnTime = bool)); maxor.add(new ConfigBool(Text.literal("Crystal place reminder"), () -> Floor7.crystalPlaceReminder, bool -> Floor7.crystalPlaceReminder = bool)); + maxor.add(new ConfigBool(Text.literal("Display reminder instantly"), () -> Floor7.instantlyDisplayCrystalReminder, bool -> Floor7.instantlyDisplayCrystalReminder = bool)); floor7.add(maxor); ConfigSection storm = new ConfigSection(Text.literal("Storm")); @@ -275,11 +278,12 @@ public class Config { extra.add(new ConfigBool(Text.literal("Display kicked time"), () -> ExtraOptions.enableKickedTimer, bool -> ExtraOptions.enableKickedTimer = bool)); extra.add(new ConfigBool(Text.literal("Disable recipe book"), () -> ExtraOptions.disableRecipeBook, bool -> ExtraOptions.disableRecipeBook = bool)); extra.add(new ConfigBool(Text.literal("Enable moveable held item tooltip"), () -> ExtraOptions.moveToolTip, bool -> ExtraOptions.moveToolTip = bool)); - extra.add(new ConfigColor(Text.literal("Timer text color prefix"), () -> ExtraOptions.timerPrefixColor, color -> ExtraOptions.timerPrefixColor = color, "timer-prefix", false)); + extra.add(new ConfigColor(Text.literal("Prefix text color"), () -> ExtraOptions.timerPrefixColor, color -> ExtraOptions.timerPrefixColor = color, "timer-prefix", false)); ConfigSection sound = new ConfigSection(Text.literal("Sound options")); sound.add(new ConfigBool(Text.literal("Disable \"on cooldown\" sound"), () -> ExtraOptions.disableAbilityCooldownSound, bool -> ExtraOptions.disableAbilityCooldownSound = bool)); sound.add(new ConfigBool(Text.literal("Disable bonzo sound"), () -> ExtraOptions.disableBonzoSound, bool -> ExtraOptions.disableBonzoSound = bool)); + sound.add(new ConfigBool(Text.literal("Old bonzo sound"), () -> ExtraOptions.oldBonzoSound, bool -> ExtraOptions.oldBonzoSound = bool)); extra.add(sound); ConfigSection rag = new ConfigSection(Text.literal("Ragnarock")); @@ -302,7 +306,7 @@ public class Config { pets.add(new ConfigBool(Text.literal("Draw the pets sprite"), () -> ExtraOptions.includePetSprite, bool -> ExtraOptions.includePetSprite = bool)); pets.add(new ConfigBool(Text.literal("Send sound on petswap"), () -> ExtraOptions.sendOnPetSound, bool -> ExtraOptions.sendOnPetSound = bool)); pets.add(new ConfigSound(Text.literal("Pet swap sound"), ExtraOptions.petSound)); - pets.add(new ConfigBool(Text.literal("Swap pet notification"), () -> ExtraOptions.sendPetSwapNotification, bool -> ExtraOptions.sendPetSwapNotification = bool)); + pets.add(new ConfigBool(Text.literal("Pet swap notification"), () -> ExtraOptions.sendPetSwapNotification, bool -> ExtraOptions.sendPetSwapNotification = bool)); extra.add(pets); ConfigSection diana = new ConfigSection(Text.literal("Diana notifications")); @@ -1,6 +1,7 @@ package blade.addon.utils.config.components; import blade.addon.features.dungeon.ChestCounter; +import blade.addon.features.dungeon.QuizTimer; import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.SecretSpawnTimer; @@ -134,4 +135,7 @@ public class Components { @ConfigValue public static HUDComponent sectionProgressDisplay = new HUDComponent(0, 0, 30, 10, 1, "Section progress", SectionProgress::display, SectionProgress::render, () -> Floor7.showSectionProgress); + + @ConfigValue + public static HUDComponent quizTimerDisplay = new HUDComponent(0, 0, 60, 10, 1, "Quiz timer", QuizTimer::display, QuizTimer::render, () -> Dungeons.quizTimer); } @@ -47,9 +47,6 @@ public class Dungeons { @ConfigValue public static int chestWarningCount = 55; - @ConfigValue - public static int chestCountColor = 0xffffffff; - @ConfigValue public static boolean enableLeapMessages = false; @@ -119,6 +116,9 @@ public class Dungeons { @ConfigValue public static boolean InvincibilityDuration = false; + @ConfigValue + public static boolean useStatusColorForInvincibility = false; + @ConfigValue public static boolean highlightTeammates = false; @@ -127,4 +127,10 @@ public class Dungeons { @ConfigValue public static boolean dontHighlightHiddenTeammates = false; + + @ConfigValue + public static boolean displayKeyForAllClasses = false; + + @ConfigValue + public static boolean quizTimer = false; } @@ -102,4 +102,7 @@ public class ExtraOptions { @ConfigValue public static int timerPrefixColor = Constants.DARK_PURPLE; + + @ConfigValue + public static boolean oldBonzoSound = false; } @@ -142,4 +142,7 @@ public class Floor7 { @ConfigValue public static boolean disableTitlesAtSS = false; + @ConfigValue + public static boolean instantlyDisplayCrystalReminder = false; + } @@ -1,10 +0,0 @@ -package blade.addon.utils.interfaces; - -public interface ArmourStandHolder { - - boolean scanned = false; - - boolean blade_addons$hasBeenScanned(); - - void blade_addons$setScanned(boolean value); -} @@ -26,7 +26,6 @@ public class RenderLayers { .layering(RenderPhase.VIEW_OFFSET_Z_LAYERING) .build(false)); - public static RenderLayer getOutline(int width, boolean depthCheck) { if (depthCheck) { if (OUTLINE_WIDTHS.containsKey(width)) { @@ -31,7 +31,6 @@ public class RenderPipelines { .withDepthWrite(true) .build()); - public static final RenderPipeline OUTLINE_ENTITY_PIPELINE_NO_DEPTH = net.minecraft.client.gl.RenderPipelines.register(RenderPipeline.builder(net.minecraft.client.gl.RenderPipelines.RENDERTYPE_LINES_SNIPPET) .withLocation(Identifier.of(Constants.NAMESPACE, "outline-entity-no-depth")) .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) @@ -26,6 +26,10 @@ public class RenderUtils { return new float[]{r, g, b, a}; } + public static int getStatusColor(int lastGreenTick, int lastOrangeTick, int currentTick) { + return currentTick >= lastGreenTick ? Constants.GREEN_COLOR : currentTick >= lastOrangeTick ? Constants.ORANGE_COLOR : Constants.RED_COLOR; + } + public static void drawCenteredText(DrawContext context, TextRenderer textRenderer, Text text, int x, int y, int maxWidth, int color) { if (textRenderer == null) return; int centered = (maxWidth - textRenderer.getWidth(text)) / 2; @@ -57,16 +61,29 @@ public class RenderUtils { RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); } - public static void drawPrefixedTimer(HUDComponent component, DrawContext context, double num, String text) { - Text drawnText = Text.literal(text + ": ").withColor(ExtraOptions.timerPrefixColor).append(Text.literal(Constants.DECIMAL_FORMAT.format(num) + "s").withColor(0xffffffff)); - RenderUtils.drawCenteredText(context, component, drawnText); + public static void drawPrefixedTimer(HUDComponent component, DrawContext context, String prefix, int num) { + drawPrefixedText(component, context, prefix, Constants.DECIMAL_FORMAT.format(num * Constants.TICK_DURATION) + "s"); + } + + public static void drawPrefixedTimer(HUDComponent component, DrawContext context, String prefix, double num) { + drawPrefixedText(component, context, prefix, Constants.DECIMAL_FORMAT.format(num) + "s"); + } + + public static void drawPrefixedText(HUDComponent component, DrawContext context, String prefix, String text) { + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + if (textRenderer == null) return; + + Text drawnText = Text.literal(prefix + ": ").withColor(ExtraOptions.timerPrefixColor).append(Text.literal(text).withColor(0xffffffff)); + context.drawText(textRenderer, drawnText, component.getScaledX(), component.getScaledY(), 0xffffffff, true); } public static void renderFilled(MatrixStack matrixStack, VertexConsumer consumer, Box box, float[] rgba) { + if (rgba[3] == 0) return; VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); } public static void renderOutline(MatrixStack matrixStack, VertexConsumer consumer, Box box, float[] rgba) { + if (rgba[3] == 0) return; VertexRendering.drawBox(matrixStack.peek(), consumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); } @@ -17,8 +17,8 @@ public class RenderingEvents { public static RenderHandler NO_DEPTH_OUTLINE_ENTITY = new RenderHandler(); public static void init() { - WorldRenderEvents.BEFORE_ENTITIES.register(RenderingEvents::filled); - WorldRenderEvents.BEFORE_ENTITIES.register(RenderingEvents::filledNoDepth); + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::filled); + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(RenderingEvents::filledNoDepth); WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityFilled); WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityOutline); WorldRenderEvents.AFTER_ENTITIES.register(RenderingEvents::entityOutlineNoDepth); @@ -3,5 +3,16 @@ "sounds": [ "blade-addons:wolf-howl" ] + }, + "ghast-moan": { + "sounds": [ + { "name": "blade-addons:ghast-moan-1", "weight": 1 }, + { "name": "blade-addons:ghast-moan-2", "weight": 1 }, + { "name": "blade-addons:ghast-moan-3", "weight": 1 }, + { "name": "blade-addons:ghast-moan-4", "weight": 1 }, + { "name": "blade-addons:ghast-moan-5", "weight": 1 }, + { "name": "blade-addons:ghast-moan-6", "weight": 1 }, + { "name": "blade-addons:ghast-moan-7", "weight": 1 } + ] } } \ No newline at end of file @@ -3,7 +3,6 @@ "package": "blade.addon.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "ArmorStandEntityMixin", "ChunkMixin", "ClientConnectionMixin", "ClientPlayNetworkHandlerMixin", |
- refactored alot - atp i dont even remember查看变更gradle.properties | 2 +-
src/main/java/blade/addon/Bladeaddons.java | 11 ++++++--
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 7 ++---
src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 67 ++++++++++++++++++++++++++++++++--------------
src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 11 ++++----
src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 9 ++-----
src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 36 ++++++++++++++++++-------
src/main/java/blade/addon/features/dungeon/f7/PillarExplode.java | 7 +----
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 28 +++++++++----------
src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 8 +++---
src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 6 +----
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 3 ++-
src/main/java/blade/addon/features/dungeon/f7/terms/{Pre4Notifier.java => DeviceNotifier.java} | 31 ++++++++++++++-------
src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 7 +----
src/main/java/blade/addon/features/dungeon/f7/terms/MelodyWarning.java | 7 +----
src/main/java/blade/addon/features/dungeon/f7/terms/SectionProgress.java | 51 +++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 7 +----
src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 2 +-
src/main/java/blade/addon/features/highlight/MobHighlight.java | 5 ++--
src/main/java/blade/addon/features/highlight/TeammateHighlight.java | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/highlight/WitherHighlight.java | 4 +--
src/main/java/blade/addon/features/item/HeldItemToolTip.java | 3 ++-
src/main/java/blade/addon/features/other/KickedTimer.java | 10 ++-----
src/main/java/blade/addon/features/other/SelectedPet.java | 24 ++++++++++++++---
src/main/java/blade/addon/mixin/ClientConnectionMixin.java | 9 +++----
src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 31 +--------------------
src/main/java/blade/addon/mixin/ClientPlayerEntityMixin.java | 18 ++++++-------
src/main/java/blade/addon/mixin/DrawContextMixin.java | 35 +++++++++++++++++++++++-
src/main/java/blade/addon/mixin/EntityRendererMixin.java | 33 +++++++++++------------
src/main/java/blade/addon/mixin/InGameHudMixin.java | 6 ++---
src/main/java/blade/addon/mixin/MinecraftClientMixin.java | 6 ++---
src/main/java/blade/addon/mixin/PlayerEntityMixin.java | 23 ----------------
src/main/java/blade/addon/mixin/SkullBlockEntityRendererMixin.java | 44 ++++++++++++++++++++++++++++++
src/main/java/blade/addon/utils/Keybinds.java | 83 ++++++++++++++++++++++++++++++++++++++++++++++-----------
src/main/java/blade/addon/utils/Location.java | 8 +++---
src/main/java/blade/addon/utils/config/Config.java | 23 +++++++++++++---
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 30 ++++++++++++---------
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 9 +++----
src/main/java/blade/addon/utils/config/components/Components.java | 14 ++++++++--
src/main/java/blade/addon/utils/config/values/Dungeons.java | 9 +++++++
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 7 +++++
src/main/java/blade/addon/utils/config/values/Floor7.java | 13 +++++++++
src/main/java/blade/addon/utils/config/values/Visual.java | 6 +++++
src/main/java/blade/addon/utils/data/EntityUtil.java | 56 +++++++++++++++++++++++++++++++++-----
src/main/java/blade/addon/utils/debug/Debug.java | 4 +--
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 80 +++++++++++++++++++++++++++---------------------------
src/main/java/blade/addon/utils/events/Events.java | 4 +++
src/main/java/blade/addon/utils/events/interfaces/WorldEvent.java | 7 +++++
src/main/java/blade/addon/utils/interfaces/PlayerDataHolder.java | 11 --------
src/main/java/blade/addon/utils/rendering/RenderLayers.java | 54 ++++++++++++++++++++-----------------
src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 24 ++++++++---------
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 42 ++++++++++++++++++++---------
src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 23 +++++++++++++---
src/main/resources/assets/blade-addons/textures/entity/essence.png | Bin 0 -> 1018 bytes
src/main/resources/blade-addons.mixins.json | 2 +-
55 files changed, 755 insertions(+), 377 deletions(-)@@ -20,6 +20,6 @@ archives_base_name=blade-addons # Dependencies fabric_version=0.138.4+1.21.10 # I love dependencies sometimes breaking -practical_config=1.4.1 +practical_config=1.4.3 modmenu_version = 16.0.0-rc.2 hypixel_api_version = 1.0.1 \ No newline at end of file @@ -25,12 +25,14 @@ import blade.addon.features.dungeon.f7.location.PositionMessages; import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; import blade.addon.features.dungeon.f7.terms.LeapNotification; import blade.addon.features.dungeon.f7.terms.MelodyWarning; -import blade.addon.features.dungeon.f7.terms.Pre4Notifier; +import blade.addon.features.dungeon.f7.terms.DeviceNotifier; +import blade.addon.features.dungeon.f7.terms.SectionProgress; import blade.addon.features.dungeon.f7.terms.TermStartTimer; import blade.addon.features.highlight.BatHighlight; import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; import blade.addon.features.highlight.SheepHighlight; +import blade.addon.features.highlight.TeammateHighlight; import blade.addon.features.highlight.WitherHighlight; import blade.addon.features.item.DropAnimation; import blade.addon.features.notifications.Notifications; @@ -48,6 +50,7 @@ import blade.addon.utils.config.Config; import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.components.Components; import blade.addon.utils.config.values.Buttons; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.data.PartyUtil; import blade.addon.utils.debug.Debug; import blade.addon.utils.dungeon.DungeonClass; @@ -72,7 +75,9 @@ public class Bladeaddons implements ModInitializer { Phase.init(); Section.init(); DungeonClass.init(); + PartyUtil.init(); + EntityUtil.init(); RenderingEvents.init(); @@ -103,7 +108,7 @@ public class Bladeaddons implements ModInitializer { LocationNotifier.init(); PredevTimer.init(); KickedTimer.init(); - Pre4Notifier.init(); + DeviceNotifier.init(); PillarExplode.init(); MelodyWarning.init(); RagDisplay.init(); @@ -117,5 +122,7 @@ public class Bladeaddons implements ModInitializer { BatHighlight.init(); WitherHighlight.init(); InvincibilityDuration.init(); + TeammateHighlight.init(); + SectionProgress.init(); } } \ No newline at end of file @@ -1,5 +1,6 @@ package blade.addon.features.dungeon; +import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.data.EntityUtil; @@ -8,14 +9,10 @@ import blade.addon.utils.events.Events; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.math.Vec3d; public class HidePlayers { private static final int HIDE_DURATION = 3 * 1000; - private static final double DISTANCE = 3; - - private static final Vec3d SS_POSITION = new Vec3d(108, 119, 94); private static long startTime; private static boolean justLeapt = false; @@ -45,7 +42,7 @@ public class HidePlayers { if (!Dungeons.hideAtSS || !Phase.inBoss()) return false; if (Dungeons.hideBeforeTermsOnly && Phase.inP3()) return false; - return SS_POSITION.distanceTo(player.getEntityPos()) <= DISTANCE; + return DeviceNotifier.atSS(player); } public static boolean testHideInRange(PlayerEntity player) { @@ -7,12 +7,19 @@ import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.ProfileComponent; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.decoration.ArmorStandEntity; +import net.minecraft.item.ItemStack; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -21,41 +28,58 @@ public class KeyNotifier { private final static Text BLOOD_KEY = Text.literal("§l§cBlood Key Dropped"); private final static Text WITHER_KEY = Text.literal("§l§7Wither Key Dropped"); - private final static Pattern KEY_ENTITY_PATTERN = Pattern.compile("(Wither|Blood) Key"); + //Thanks to mio for this key detection system + private final static String WITHER_UUID = "2865274b-3097-394e-8149-ec629c72d850"; + private final static String BLOOD_UUID = "73f6d1f9-df41-3d1d-b98c-e1442d915885"; + private final static Pattern AUTOMATIC_PICKUP_PATTERN = Pattern.compile("A (Wither|Blood) Key was picked up!"); private final static Pattern NORMAL_PICKUP_PATTERN = Pattern.compile("has obtained (Wither|Blood) Key!"); + private final static CopyOnWriteArrayList<Entity> foundKeys = new CopyOnWriteArrayList<>(); + private static boolean hasKey = false; private static boolean isBloodKey = false; public static void init() { - Events.ON_ENTITY_TRACKED.register((entity, world) -> { - if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return false; - if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return false; - - - Text text = entity.getCustomName(); - if (text == null) return false; + ClientTickEvents.END_WORLD_TICK.register((world) -> { + if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return; + if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return; - Matcher matcher = KEY_ENTITY_PATTERN.matcher(text.getString()); - if (matcher.find()) { - isBloodKey = matcher.group(1).matches("Blood"); - hasKey = true; - Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + for (Entity entity : world.getEntities()) { + if (entity instanceof ArmorStandEntity armorStand && !foundKeys.contains(entity)) { + ItemStack head = armorStand.getEquippedStack(EquipmentSlot.HEAD); + ProfileComponent profile = head.get(DataComponentTypes.PROFILE); + if (profile == null) continue; + String uuid = profile.getGameProfile().id().toString(); + if (uuid == null) continue; + + if (uuid.equals(WITHER_UUID)) { + foundKeys.add(entity); + hasKey = true; + Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + return; + } + + if (uuid.equals(BLOOD_UUID)) { + foundKeys.add(entity); + isBloodKey = true; + hasKey = true; + Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); + return; + } + } } - - return false; }); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !hasKey || !Dungeons.enableKeyNotifier) return; - if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return; + Events.ON_GAME_MESSAGE.register(message -> { + if (!Location.inDungeon() || !hasKey || !Dungeons.enableKeyNotifier) return false; + if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return false; Matcher matcher = AUTOMATIC_PICKUP_PATTERN.matcher(message.getString()); if (matcher.find()) { hasKey = false; isBloodKey = false; - return; + return false; } matcher = NORMAL_PICKUP_PATTERN.matcher(message.getString()); @@ -63,12 +87,15 @@ public class KeyNotifier { hasKey = false; isBloodKey = false; } + + return false; }); Events.ON_LOCATION_CHANGE.register(locations -> { if (Location.inDungeon()) { isBloodKey = false; hasKey = false; + foundKeys.clear(); } return false; }); @@ -61,7 +61,8 @@ public class RunStartValidator { Events.ON_PLAYER_ENTRY.register(receivedEntry -> { //will only check after the first game message in case of false positives if (!hasTicked) return false; - if (!Location.inDungeon() || Phase.runStarted() || (!Dungeons.detectDuplicateClass && !Dungeons.detectPlayerCount)) return false; + if (!Location.inDungeon() || Phase.runStarted() || (!Dungeons.detectDuplicateClass && !Dungeons.detectPlayerCount)) + return false; validate(); return false; }); @@ -135,14 +136,12 @@ public class RunStartValidator { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); if (hasDupeClasses) { - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, DUPE_CLASS_TEXT, x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, component, DUPE_CLASS_TEXT); } else if (notEnoughPlayers) { - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, PLAYER_COUNT_TEXT, x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, component, PLAYER_COUNT_TEXT); } else { - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal("§cSome warning text"), x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, component, Text.literal("§cSome warning text")); } } } @@ -1,12 +1,10 @@ package blade.addon.features.dungeon; -import blade.addon.utils.Constants; import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -43,10 +41,7 @@ public class WarpCooldown { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); - context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("§5Warp Cooldown: §f" + Constants.DECIMAL_FORMAT.format(timeRemaining)), x, y, 0xffffffff, true); + RenderUtils.drawPrefixedTimer(component, context, timeRemaining, "Warp Cooldown"); } } @@ -21,34 +21,35 @@ import java.util.regex.Pattern; public class CrystalSpawn { - private static final Pattern PATTERN_1 = Pattern.compile("^\\[BOSS] Maxor: THAT BEAM! IT HURTS! IT HURTS!!$"); - private static final Pattern PATTERN_2 = Pattern.compile("^\\[BOSS] Maxor: YOU TRICKED ME!$"); private static final Pattern RELIC_PICK_UP = Pattern.compile("(\\w+) picked up an Energy Crystal!$"); + private static final int REMINDER_TICK = 240; + private static final int TICK_SPAWN = 34; + private static long pickupTime = 0; private static boolean pickedUp = false; - private static final int TICK_SPAWN = 34; private static int tick = 0; + private static int tickSincePicked = 0; public static void init() { Events.ON_GAME_MESSAGE.register(text -> { - if (!Location.inDungeon() || !Phase.inP1() || !Floor7.enableCrystalSpawnTime) return false; + if (!Location.inDungeon() || !Phase.inP1() || (!Floor7.enableCrystalSpawnTime && !Floor7.crystalPlaceReminder)) + return false; + String string = text.getString(); - Matcher matcher = PATTERN_1.matcher(text.getString()); - if (matcher.find()) { + if (string.equals("[BOSS] Maxor: THAT BEAM! IT HURTS! IT HURTS!!")) { tick = TICK_SPAWN; return false; } - matcher = PATTERN_2.matcher(text.getString()); - if (matcher.find()) { + if (string.equals("[BOSS] Maxor: YOU TRICKED ME!")) { tick = TICK_SPAWN; return false; } - matcher = RELIC_PICK_UP.matcher(text.getString()); + Matcher matcher = RELIC_PICK_UP.matcher(text.getString()); if (matcher.find()) { String name = matcher.group(1); if (EntityUtil.isClientPlayer(name)) { @@ -61,11 +62,15 @@ public class CrystalSpawn { }); Events.ON_SERVER_TICK.register(() -> { tick = Math.max(tick - 1, 0); + if (pickedUp) { + tickSincePicked++; + } return false; }); Events.ON_LOCATION_CHANGE.register(newLocation -> { tick = 0; + tickSincePicked = 0; pickedUp = false; return false; }); @@ -82,6 +87,7 @@ public class CrystalSpawn { if (distance < 6 && crystal.getY() == 224.375) { PersonalBests.crystalTime.testNewTime(Text.literal("§aCrystal placed in "), pickupTime); pickedUp = false; + tickSincePicked = 0; } } @@ -90,10 +96,20 @@ public class CrystalSpawn { } public static boolean display() { - return tick > 0 && Location.inDungeon() && Floor7.enableCrystalSpawnTime; + return tick > 0 && Location.inDungeon() && Phase.inP1() && Floor7.enableCrystalSpawnTime; } public static void render(HUDComponent component, DrawContext context) { RenderUtils.drawTimer(component, context, tick, Constants.LIGHT_PURPLE); } + + public static boolean displayNotification() { + return tickSincePicked > REMINDER_TICK && Location.inDungeon() && Phase.inP1() && Floor7.crystalPlaceReminder && pickedUp; + } + + public static void renderNotification(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, Text.literal("§bPlace Crystal!")); + } + + } @@ -8,11 +8,9 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; public class PillarExplode { @@ -55,9 +53,6 @@ public class PillarExplode { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal("§6||| §bStorm crushed! §6|||"), x, y, component.getWidth()); - + RenderUtils.drawCenteredText(context, component, Text.literal("§6||| §bStorm crushed! §6|||")); } } @@ -17,7 +17,6 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; @@ -66,7 +65,6 @@ public class RelicTimer { private static int tick = Floor7.relicSpawnTicks; private static boolean sentRelicTimes = false; - private static boolean ignoreChecks = false; //only here to test the relic progress bar private static boolean forceGUI = false; @@ -86,7 +84,7 @@ public class RelicTimer { Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { - reset(); + reset(); } return false; }); @@ -107,9 +105,7 @@ public class RelicTimer { String name = matcher.group(1); String relicString = matcher.group(2); - ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player == null) return false; - if (name.equals(player.getName().getString())) { + if (EntityUtil.isClientPlayer(name)) { pickedupRelic = Relic.valueOf(relicString.toUpperCase()); Debug.sendDebugMessage(Text.literal("Picked up relic " + relicString)); } @@ -119,7 +115,7 @@ public class RelicTimer { }); ClientTickEvents.END_WORLD_TICK.register(world -> { - if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes ||sentRelicTimes) return; + if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes || sentRelicTimes) return; Iterable<Entity> entities = world.getEntities(); @@ -133,7 +129,6 @@ public class RelicTimer { for (Relic relic : Relic.values()) { if (relic.placedTime != 0 && Misc.getDistance(relic.box.maxX, relic.box.maxZ, ax, az) < 1) { relic.placedTime = System.currentTimeMillis(); - break; } } } @@ -150,15 +145,14 @@ public class RelicTimer { Events.ON_BLOCK_INTERACTION.register((result, itemStack) -> { - if (!ignoreChecks) { - if ((!Location.inDungeon() || !Phase.inP5())) return false; - } + if ((!Location.inDungeon() || !Phase.inP5())) return false; if (pickedupRelic == null) return false; BlockPos pos = result.getBlockPos(); - if (!ItemUtil.itemHasName(itemStack, "Relic")) { + //skyblock menu check is there incase the item doesnt get updated + if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu")) { if (Floor7.blockIncorrectRelicPlace) { Debug.sendDebugMessage(Text.literal("Item: " + itemStack.getName())); Misc.addChatMessage(Text.literal("Blocked a weird click")); @@ -186,6 +180,7 @@ public class RelicTimer { pickedupRelic = null; } else { if (Floor7.blockIncorrectRelicPlace) { + Debug.sendDebugMessage(Text.literal("Relic: " + pickedupRelic)); Misc.addChatMessage(Text.literal("incorrect click!")); return true; } @@ -228,9 +223,12 @@ public class RelicTimer { } } - public static void testIgnoreChecks() { - ignoreChecks = !ignoreChecks; - Misc.addChatMessage(Text.literal("Ignore relic checks: ").append(Misc.getStatusText(ignoreChecks))); + public static void printRelic() { + Misc.addChatMessage(Text.literal("Relic: " + pickedupRelic)); + + } + + public static void debugCommands() { } @@ -1,6 +1,6 @@ package blade.addon.features.dungeon.f7.invincibility; -import blade.addon.features.dungeon.f7.terms.Pre4Notifier; +import blade.addon.features.dungeon.f7.terms.DeviceNotifier; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; @@ -111,21 +111,21 @@ public class InvincibilityTimer { Matcher matcher = BONZO_PATTERN.matcher(string); if (matcher.matches()) { bonzoMaskTicks = BONZO_MASK_COOLDOWN; - if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { + if (Dungeons.showProcTitle && !DeviceNotifier.at4thDev()) { Misc.setTitle(Text.literal("Bonzo")); } InvincibilityDuration.proc(); } if (string.equals("Second Wind Activated! Your Spirit Mask saved your life!")) { spiritMaskTicks = SPIRIT_MASK_COOLDOWN; - if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { + if (Dungeons.showProcTitle && !DeviceNotifier.at4thDev()) { Misc.setTitle(Text.literal("Spirit")); } InvincibilityDuration.proc(); } if (string.equals("Your Phoenix Pet saved you from certain death!")) { phoenixTicks = PHOENIX_COOLDOWN; - if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { + if (Dungeons.showProcTitle && !DeviceNotifier.at4thDev()) { Misc.setTitle(Text.literal("Phoenix")); } InvincibilityDuration.proc(); @@ -11,7 +11,6 @@ import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Style; import net.minecraft.text.Text; @@ -63,9 +62,6 @@ public class LocationNotifier { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, notification, x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, component, notification); } } @@ -1,5 +1,6 @@ package blade.addon.features.dungeon.f7.location; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Section; import net.minecraft.client.network.ClientPlayerEntity; @@ -37,7 +38,7 @@ public class PositionMessage { if (sent || !inAValidSection() || !inRange(player.getEntityPos())) return; sent = true; if (Floor7.enablePositionalMessages) { - player.networkHandler.sendChatCommand("pc " + message); + Misc.executeCommand("pc " + message); } } @@ -10,22 +10,27 @@ import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; -public class Pre4Notifier { +public class DeviceNotifier { private static final long TOTAL_DURATION = 1500; + private static final Vec3d SS_POSITION = new Vec3d(108, 119, 94); + private static final double DISTANCE = 3; + private static long completedTime = 0; private static boolean showNotification = false; public static void init() { Events.ON_TERMINAL.register((name, action, objective, current, total) -> { - if (!Floor7.notifyPre4Completion) return true; + if (!objective.equals("device") || !EntityUtil.isClientPlayer(name)) return false; - if (objective.equals("device") && EntityUtil.isClientPlayer(name) && atDev()) { + if ((Floor7.notifyPre4Completion && at4thDev()) || (Floor7.notifySSCompletion && atSS())) { completedTime = System.currentTimeMillis(); showNotification = true; Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); @@ -35,14 +40,24 @@ public class Pre4Notifier { }); } - public static boolean atDev() { + public static boolean atSS() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return false; + return SS_POSITION.distanceTo(player.getEntityPos()) <= DISTANCE; + } + + public static boolean atSS(PlayerEntity player) { + return SS_POSITION.distanceTo(player.getEntityPos()) <= DISTANCE; + } + + public static boolean at4thDev() { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player == null) return false; return (player.getX() >= 63 && player.getX() <= 64 && player.getY() == 127 && player.getZ() >= 35 && player.getZ() <= 36); } public static boolean disableTitles() { - return Floor7.disableTitlesAtPre4 && atDev() && Phase.inTerminals(); + return ((Floor7.disableTitlesAtPre4 && at4thDev()) || (Floor7.disableTitlesAtSS && atSS())) && Phase.inTerminals(); } public static boolean display() { @@ -51,10 +66,6 @@ public class Pre4Notifier { public static void render(HUDComponent component, DrawContext context) { if (System.currentTimeMillis() - completedTime >= TOTAL_DURATION) showNotification = false; - - int x = component.getScaledX(); - int y = component.getScaledY(); - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal("§aDevice Completed!"), x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, component, Text.literal("§aDevice Completed!")); } } @@ -7,7 +7,6 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.world.ClientWorld; @@ -89,14 +88,10 @@ public class LeapNotification { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - String start; if (currentSpot == 3) start = (count > 2 ? "§9" : "§4"); else start = (count > 3 ? "§9" : "§4"); - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(start + count + "§9/4 Players Leaped"), x, y, component.getWidth()); - + RenderUtils.drawCenteredText(context, component, Text.literal(start + count + "§9/4 Players Leaped")); } } @@ -10,7 +10,6 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.MutableText; import net.minecraft.text.Style; @@ -83,9 +82,6 @@ public class MelodyWarning { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - DungeonClass dungeonClass = DungeonClass.getClass(name); int num = Math.min(furthestProgress / 25, 3); @@ -94,13 +90,12 @@ public class MelodyWarning { color = DungeonClass.getColor(name); } - MutableText nameText = Text.literal(dungeonClass != null ? dungeonClass.name() : name != null? name: "Someone").setStyle(Style.EMPTY.withColor(color).withBold(true)); MutableText infoText = Text.literal(" §r§dhas melody! " + num + "/4").setStyle(Style.EMPTY); Text text = nameText.append(infoText); - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, text, x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, component, text); } } @@ -0,0 +1,51 @@ +package blade.addon.features.dungeon.f7.terms; + +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.dungeon.Section; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +public class SectionProgress { + + private static int completed = 0; + private static int sectionTotal = 7; + + public static void init() { + + Events.ON_TERMINAL.register((formattedName, action, objective, current, total) -> { + completed = current; + sectionTotal = total; + return false; + }); + + Events.ON_SECTION_CHANGE.register(() -> { + if (completed == sectionTotal) completed = 0; + sectionTotal = getTotal(); + return false; + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + completed = 0; + sectionTotal = 7; + return false; + }); + + } + + private static int getTotal() { + return Section.getSection() != 2? 7: 8; + } + + public static boolean display() { + return Floor7.showSectionProgress && Phase.inTerminals(); + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, Text.literal("§a(§c" + completed + "§a/" + sectionTotal + ")")); + } + +} @@ -7,7 +7,6 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -34,11 +33,7 @@ public class TermStartTimer { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - double num = tick * Constants.TICK_DURATION; - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), Constants.YELLOW_COLOR); - + RenderUtils.drawCenteredText(context, component, Text.literal(Constants.DECIMAL_FORMAT.format(num)), Constants.YELLOW_COLOR); } } @@ -18,7 +18,7 @@ public class TitleHider { public static void processSubtitle(SubtitleS2CPacket packet) { if (!shouldHideTitle()) return; - if (Section.inSection(1) && Pre4Notifier.atDev()) return; + if (Section.inSection(1) && DeviceNotifier.at4thDev()) return; String string = packet.text().getString().replaceAll("§.", ""); @@ -30,6 +30,7 @@ import net.minecraft.text.TextColor; import net.minecraft.util.math.Box; import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Predicate; @@ -62,7 +63,6 @@ public class MobHighlight { private static final ConcurrentLinkedQueue<DataHolder> savedEntities = new ConcurrentLinkedQueue<>(); - public static boolean dontRenderHighlight = false; @ConfigValue public static boolean mobHighlight = false; @@ -136,7 +136,6 @@ public class MobHighlight { testArmourStand(armorStand, client); } } - savedEntities.removeIf(dataHolder -> dataHolder.entity.isRemoved()); }); @@ -271,7 +270,7 @@ public class MobHighlight { case ZombieEntity ignored -> true; case SkeletonEntity ignored -> true; case WitherSkeletonEntity ignored -> true; - case PlayerEntity ignored -> !isMiniBoss(entity); + case PlayerEntity ignored -> !EntityUtil.isARealPlayer(entity) && !EntityUtil.isClientPlayer(entity) && !isMiniBoss(entity); default -> false; }; } @@ -0,0 +1,72 @@ +package blade.addon.features.highlight; + +import blade.addon.features.dungeon.HidePlayers; +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.data.EntityUtil; +import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.math.Vec3d; + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class TeammateHighlight { + + private static final ConcurrentLinkedQueue<PlayerEntity> teammates = new ConcurrentLinkedQueue<>(); + + public static void init() { + + Events.ON_ENTITY_TRACKED.register((entity, world) -> { + if (!Location.inDungeon()) return false; + if (entity instanceof PlayerEntity player) { + if (EntityUtil.isARealPlayer(player) && !EntityUtil.isClientPlayer(player) && !teammates.contains(player)) { + teammates.add(player); + } + } + return false; + }); + + Events.ON_LOCATION_CHANGE.register(location -> { + teammates.clear(); + return false; + }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> teammates.removeIf(Entity::isRemoved)); + + RenderingEvents.NO_DEPTH_OUTLINE_ENTITY.register(TeammateHighlight::renderOutline); + } + + private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!Dungeons.highlightTeammates && !Dungeons.renderClassName) return; + + teammates.forEach(player -> { + if (Dungeons.dontHighlightHiddenTeammates && HidePlayers.shouldHidePlayers(player)) return; + DungeonClass clazz = DungeonClass.getClass(player); + if (clazz == null) return; + + int color = DungeonClass.getColor(clazz); + + if (Dungeons.highlightTeammates) { + float[] rgba = RenderUtils.toFloats(color); + RenderUtils.renderOutline(matrixStack, consumer, EntityUtil.getBox(player), rgba); + } + + if (Dungeons.renderClassName) { + Text text = Text.literal(player.getName().getString()).withColor(color).append(Text.literal(" [" + DungeonClass.getChar(clazz) + "]").withColor(Constants.YELLOW_COLOR)); + Vec3d pos = EntityUtil.getLerpedPos(player); + RenderUtils.renderText(context, matrixStack, text, pos.getX(), pos.getY() + 2.75, pos.getZ(), 2); + } + }); + } + +} @@ -55,14 +55,14 @@ public class WitherHighlight { private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled() || MobHighlight.dontRenderHighlight) return; - float[] rgba = RenderUtils.toFloats(MobHighlight.batFilledColor); + float[] rgba = RenderUtils.toFloats(MobHighlight.witherFilledColor); withers.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, getBox(entity), rgba)); } private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline() || MobHighlight.dontRenderHighlight) return; - float[] rgba = RenderUtils.toFloats(MobHighlight.batOutlineColor); + float[] rgba = RenderUtils.toFloats(MobHighlight.witherOutlineColor); withers.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, getBox(entity), rgba)); } @@ -30,7 +30,8 @@ public class HeldItemToolTip { } public static void render(HUDComponent component, DrawContext context) { - RenderUtils.drawCenteredText(context, component, tooltip, color); + int currentColor = heldItemFade > 0? color: 0xffffffff; + RenderUtils.drawCenteredText(context, component, tooltip, currentColor); } } @@ -1,11 +1,9 @@ package blade.addon.features.other; -import blade.addon.utils.Constants; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; public class KickedTimer { @@ -35,12 +33,8 @@ public class KickedTimer { public static void render(HUDComponent component, DrawContext context) { long diff = System.currentTimeMillis() - kickedTime; if (diff > 60 * 1000) isKicked = false; - - int x = component.getScaledX(); - int y = component.getScaledY(); - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, "§5Time kicked: §f" + Constants.DECIMAL_FORMAT.format(Math.min(diff / 1000.0, 60)) + "s", x, y, component.getWidth()); - + double drawnTime = Math.min(diff / 1000.0, 60.0); + RenderUtils.drawPrefixedTimer(component, context, drawnTime, "Time kicked"); } } @@ -1,11 +1,13 @@ package blade.addon.features.other; import blade.addon.utils.Constants; -import blade.addon.utils.debug.Debug; -import blade.addon.utils.Scheduler; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; @@ -27,12 +29,15 @@ public class SelectedPet { private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (?:\\[Lvl \\d+] )?(?:\\[[^\\]]+\\] )?(.+)!$"); private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl \\d+] (?:\\[[^\\]]+\\] )?(.+)! VIEW RULE$"); + private static final int TOTAL_TICKS = 20; + private static final Text NO_PET = Text.literal("§cNo pet"); private static final String identifierPrefix = "pets/"; private static Text currentPetText = NO_PET; private static String currentPetString = ""; private static Identifier spriteId = null; + private static int tick = 0; public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { @@ -85,6 +90,11 @@ public class SelectedPet { return false; }); + + ClientTickEvents.END_WORLD_TICK.register((world -> { + tick = Math.max(tick - 1, 0); + })); + } private static void despawnPet() { @@ -107,7 +117,8 @@ public class SelectedPet { updateSprite(stringName); if (sendSound && ExtraOptions.sendOnPetSound) { - Scheduler.scheduleSound(ExtraOptions.petSound); + Misc.sendSound(ExtraOptions.petSound); + tick = TOTAL_TICKS; } } @@ -152,7 +163,14 @@ public class SelectedPet { TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; context.drawText(textRenderer, currentPetText, x + (ExtraOptions.includePetSprite ? 18 : 0), y + component.getHeight() - textRenderer.fontHeight, 0xffffffff, true); + } + + public static boolean displayNotification() { + return ExtraOptions.sendPetSwapNotification && tick > 0; + } + public static void renderNotification(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, currentPetText); } } @@ -47,11 +47,8 @@ public class ClientConnectionMixin { @Inject(method = "sendImmediately", at = @At("HEAD")) private void sendImmediately(Packet<?> packet, ChannelFutureListener channelFutureListener, boolean flush, CallbackInfo ci) { - if (packet instanceof CommonPingS2CPacket common) { - if (common.getParameter() == 0) return; - Events.ON_SERVER_TICK.invoke(ServerTickEvent::onServerTick); - } - - + // for some reason this just being here + // fixes player tracking and I don't know why + // will hopefully look into it later } } @@ -1,20 +1,16 @@ package blade.addon.mixin; import blade.addon.features.dungeon.f7.terms.TitleHider; -import blade.addon.utils.data.EntityUtil; -import blade.addon.utils.debug.Debug; import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.interfaces.PlayerDataHolder; +import blade.addon.utils.debug.Debug; import blade.addon.utils.events.Events; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket; @@ -28,7 +24,6 @@ import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -110,32 +105,8 @@ public class ClientPlayNetworkHandlerMixin { @Inject(method = "onEntitySpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;playSpawnSound(Lnet/minecraft/entity/Entity;)V")) public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo ci, @Local Entity entity) { - if (entity instanceof PlayerEntity player) { - PlayerDataHolder dataHolder = (PlayerDataHolder) (Object) player; - boolean isRealPlayer = isARealPlayer(player); - dataHolder.blade_addons$setIsRealPlayer(isRealPlayer); - } Events.ON_ENTITY_SPAWNED.invoke(entityTrackEvent -> entityTrackEvent.onEntity(entity, world)); } - @Unique - private static boolean isARealPlayer(Entity entity) { - if (entity instanceof PlayerEntity player) { - - if (EntityUtil.isClientPlayer(player)) return true; - - ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); - if (networkHandler == null) return false; - - PlayerListEntry entry = networkHandler.getPlayerListEntry(player.getUuid()); - - //this is a hack which will fail if someone has a really old bugged ign that includes a space - if (entry != null) { - String name = entry.getProfile().name(); - return !name.isEmpty() && !name.contains(" "); - } - } - return false; - } } \ No newline at end of file @@ -4,10 +4,7 @@ import blade.addon.features.item.DropAnimation; import blade.addon.features.item.ProtectItem; import blade.addon.utils.config.values.Dungeons; import com.llamalad7.mixinextras.sugar.Local; -import com.mojang.authlib.GameProfile; -import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -15,16 +12,15 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ClientPlayerEntity.class) -public class ClientPlayerEntityMixin extends AbstractClientPlayerEntity { - - public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) { - super(world, profile); - } +public class ClientPlayerEntityMixin { @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) public void protectItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) { if (Dungeons.dontProtectHeldItem && ProtectItem.isInADungeon()) return; - if (ProtectItem.protect(this.getInventory().getSelectedStack())) { + + ClientPlayerEntity self = (ClientPlayerEntity) (Object) this; + + if (ProtectItem.protect(self.getInventory().getSelectedStack())) { cir.setReturnValue(false); } } @@ -32,7 +28,9 @@ public class ClientPlayerEntityMixin extends AbstractClientPlayerEntity { @Inject(method = "dropSelectedItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V")) public void getDropped(boolean entireStack, CallbackInfoReturnable<Boolean> cir, @Local ItemStack itemStack) { if (!DropAnimation.shouldProceed()) return; - int slot = getInventory().getSelectedSlot(); + + ClientPlayerEntity self = (ClientPlayerEntity) (Object) this; + int slot = self.getInventory().getSelectedSlot(); DropAnimation.setDroppedData(itemStack, slot); } } @@ -2,16 +2,49 @@ package blade.addon.mixin; import blade.addon.utils.config.values.Visual; import net.minecraft.client.gui.DrawContext; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.world.World; +import org.joml.Matrix3x2fStack; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(DrawContext.class) public class DrawContextMixin { - @ModifyVariable(method = "drawCooldownProgress", at=@At("STORE"), ordinal = 0) + @Final + @Shadow + private Matrix3x2fStack matrices; + + + @ModifyVariable(method = "drawCooldownProgress", at=@At("STORE"), ordinal = 0) private float noCooldown(float f) { return Visual.hideCooldown? 0: f; } + @Inject(method = "drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;III)V", at=@At("HEAD")) + private void scaleUp(LivingEntity entity, World world, ItemStack stack, int x, int y, int seed, CallbackInfo ci) { + if (Visual.oldPlayerHead && stack.getItem() == Items.PLAYER_HEAD) { + float scale = 0.875f; + int offset = (16 - (int)(scale * 16)) / 2; + + matrices.pushMatrix(); + matrices.translate(x * (1 - scale) + offset, y * (1 - scale) + offset); + matrices.scale(scale); + } + } + + @Inject(method = "drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;III)V", at=@At("TAIL")) + private void scaleDown(LivingEntity entity, World world, ItemStack stack, int x, int y, int seed, CallbackInfo ci) { + if (Visual.oldPlayerHead && stack.getItem() == Items.PLAYER_HEAD) { + matrices.popMatrix(); + } + } + } @@ -1,16 +1,15 @@ package blade.addon.mixin; +import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.Visual; import blade.addon.utils.data.EntityUtil; -import net.minecraft.client.render.command.OrderedRenderCommandQueue; +import blade.addon.utils.dungeon.DungeonClass; +import net.minecraft.client.network.OtherClientPlayerEntity; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.state.EntityRenderState; -import net.minecraft.client.render.state.CameraRenderState; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; -import net.minecra …… diff 过长已截断 …… |
- changed notifications a bit - added invincibility duration timer - made rendering a bit more straight forward - fixed bat not getting highlight查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 5 ++++ src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 47 +++++++++++++--------------------- src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 41 +++++------------------------- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 38 +++++++++------------------- src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityDuration.java | 32 +++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 3 +++ src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 26 ++++--------------- src/main/java/blade/addon/features/highlight/BatHighlight.java | 75 ++++++++---------------------------------------------- src/main/java/blade/addon/features/highlight/MimicHighlight.java | 63 ++++++++++----------------------------------- src/main/java/blade/addon/features/highlight/MobHighlight.java | 90 ++++++++++++++++------------------------------------------------- src/main/java/blade/addon/features/highlight/SheepHighlight.java | 85 +++++++++++-------------------------------------------------- src/main/java/blade/addon/features/highlight/WitherHighlight.java | 80 +++++++++++---------------------------------------------- src/main/java/blade/addon/features/item/HeldItemToolTip.java | 36 ++++++++++++++++++++++++++ src/main/java/blade/addon/features/notifications/Notification.java | 15 +++++++++-- src/main/java/blade/addon/features/notifications/NotificationEditScreen.java | 1 + src/main/java/blade/addon/features/notifications/NotificationEntry.java | 35 +++++++++++++++++-------- src/main/java/blade/addon/features/notifications/Notifications.java | 10 ++++---- src/main/java/blade/addon/features/other/PracticeSS.java | 32 ++++++++--------------- src/main/java/blade/addon/mixin/InGameHudMixin.java | 23 +++++++++++++++++ src/main/java/blade/addon/utils/Constants.java | 2 +- src/main/java/blade/addon/utils/config/Config.java | 2 ++ src/main/java/blade/addon/utils/config/components/Components.java | 8 ++++++ src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 +++ src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 +++ src/main/java/blade/addon/utils/data/EntityUtil.java | 13 ++++++++++ src/main/java/blade/addon/utils/rendering/RenderHandler.java | 22 ++++++++++++++++ src/main/java/blade/addon/utils/rendering/RenderUtils.java | 18 +++++++++++++ src/main/java/blade/addon/utils/rendering/RenderingEvent.java | 10 ++++++++ src/main/java/blade/addon/utils/rendering/RenderingEvents.java | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/resources/assets/blade-addons/textures/gui/sprites/cross.png | Bin 0 -> 653 bytes 31 files changed, 439 insertions(+), 469 deletions(-) @@ -20,6 +20,6 @@ archives_base_name=blade-addons # Dependencies fabric_version=0.138.4+1.21.10 # I love dependencies sometimes breaking -practical_config=74a456703958c0a6381956ccf9be4a5e8dd7d84f +practical_config=1.4.1 modmenu_version = 16.0.0-rc.2 hypixel_api_version = 1.0.1 \ No newline at end of file @@ -18,6 +18,7 @@ import blade.addon.features.dungeon.f7.PillarExplode; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; +import blade.addon.features.dungeon.f7.invincibility.InvincibilityDuration; import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.features.dungeon.f7.location.LocationNotifier; import blade.addon.features.dungeon.f7.location.PositionMessages; @@ -53,6 +54,7 @@ import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; import blade.addon.utils.events.CustomEvents; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.api.ModInitializer; public class Bladeaddons implements ModInitializer { @@ -72,6 +74,8 @@ public class Bladeaddons implements ModInitializer { DungeonClass.init(); PartyUtil.init(); + RenderingEvents.init(); + StormTickTimer.init(); GoldorTickTimer.init(); TermStartTimer.init(); @@ -112,5 +116,6 @@ public class Bladeaddons implements ModInitializer { Notifications.init(); BatHighlight.init(); WitherHighlight.init(); + InvincibilityDuration.init(); } } \ No newline at end of file @@ -4,15 +4,14 @@ import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; @@ -21,7 +20,6 @@ import net.minecraft.entity.ItemEntity; import net.minecraft.text.Text; import net.minecraft.util.math.Box; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; import java.util.HashSet; import java.util.List; @@ -57,32 +55,23 @@ public class ItemHighlight { } }); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(context -> { - if (!Dungeons.highlightItems) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer buffer = consumers.getBuffer(RenderLayers.THROUGH_WALL_FILLED_LAYER); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - trackedItems.forEach((itemEntity, integer) -> { - double x = MathHelper.lerp(tickProgress, itemEntity.lastRenderX, itemEntity.getX()); - double y = MathHelper.lerp(tickProgress, itemEntity.lastRenderY, itemEntity.getY()); - double z = MathHelper.lerp(tickProgress, itemEntity.lastRenderZ, itemEntity.getZ()); - - EntityDimensions dimension = itemEntity.getDimensions(itemEntity.getPose()); - Box box = dimension.getBoxAt(x, y, z).expand(0.1).offset(0, 0.05, 0); - float[] color = RenderUtils.toFloats(getColor(itemEntity)); - VertexRendering.drawFilledBox(matrices, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); - }); + RenderingEvents.NO_DEPTH_FILLED.register(ItemHighlight::render); + } + + private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!Dungeons.highlightItems) return; + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + + trackedItems.forEach((itemEntity, integer) -> { + double x = MathHelper.lerp(tickProgress, itemEntity.lastRenderX, itemEntity.getX()); + double y = MathHelper.lerp(tickProgress, itemEntity.lastRenderY, itemEntity.getY()); + double z = MathHelper.lerp(tickProgress, itemEntity.lastRenderZ, itemEntity.getZ()); - matrices.pop(); + EntityDimensions dimension = itemEntity.getDimensions(itemEntity.getPose()); + Box box = dimension.getBoxAt(x, y, z).expand(0.1).offset(0, 0.05, 0); + float[] color = RenderUtils.toFloats(getColor(itemEntity)); + VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); }); } @@ -7,17 +7,15 @@ import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.text.Text; @@ -25,7 +23,6 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import java.io.FileWriter; @@ -47,8 +44,8 @@ public class BossWaypoints { public static void init() { load(); //needs separate consumers because of depth checking or smth - WorldRenderEvents.BEFORE_ENTITIES.register(BossWaypoints::renderThroughWall); - WorldRenderEvents.BEFORE_ENTITIES.register(BossWaypoints::render); + RenderingEvents.FILLED_BLOCK.register(BossWaypoints::render); + RenderingEvents.NO_DEPTH_FILLED.register(BossWaypoints::renderThroughWall); UseBlockCallback.EVENT.register(BossWaypoints::onBlock); } @@ -138,48 +135,24 @@ public class BossWaypoints { return ActionResult.PASS; } - private static void renderThroughWall(WorldRenderContext context) { + private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.FILLED_LAYER); - waypoints.forEach(waypoint -> { if (waypoint.isThroughWall()) { - waypoint.Render(consumer, matrices); + waypoint.Render(consumer, matrixStack); } }); - matrices.pop(); - } - private static void render(WorldRenderContext context) { + private static void renderThroughWall(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!isInValidArea()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.THROUGH_WALL_FILLED_LAYER); waypoints.forEach(waypoint -> { if (!waypoint.isThroughWall()) { - waypoint.Render(consumer, matrices); + waypoint.Render(consumer, matrixStack); } }); - matrices.pop(); - } public static boolean waypointExists(double x, double y, double z) { @@ -9,17 +9,16 @@ import blade.addon.utils.data.ItemUtil; import blade.addon.utils.debug.Debug; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; @@ -30,7 +29,6 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -133,7 +131,7 @@ public class RelicTimer { double az = armorStand.getZ(); for (Relic relic : Relic.values()) { - if (relic.placedTime != 0 && Misc.getDistance(relic.box.maxX, ax, relic.box.maxZ, az) < 1) { + if (relic.placedTime != 0 && Misc.getDistance(relic.box.maxX, relic.box.maxZ, ax, az) < 1) { relic.placedTime = System.currentTimeMillis(); break; } @@ -195,27 +193,7 @@ public class RelicTimer { return false; }); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(context -> { - if (pickedupRelic == null || !Floor7.renderRelicHighlight) return; - - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer buffer = consumers.getBuffer(RenderLayers.FILLED_LAYER); - - - Box box = pickedupRelic.box; - float[] color = RenderUtils.toFloats(pickedupRelic.color); - VertexRendering.drawFilledBox(matrices, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); - - - matrices.pop(); - }); + RenderingEvents.FILLED_BLOCK.register(RelicTimer::worldRender); } @@ -256,6 +234,14 @@ public class RelicTimer { } + private static void worldRender(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (pickedupRelic == null || !Floor7.renderRelicHighlight) return; + + Box box = pickedupRelic.box; + float[] color = RenderUtils.toFloats(pickedupRelic.color); + VertexRendering.drawFilledBox(matrixStack, consumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); + } + public static boolean display() { return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && !Floor7.replaceWithProgressBar; } @@ -0,0 +1,32 @@ +package blade.addon.features.dungeon.f7.invincibility; + +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; + +public class InvincibilityDuration { + + private static final int MAX_DURATION = 3 * 20; + private static int ticks = 0; + + public static void init() { + Events.ON_SERVER_TICK.register(() -> { + ticks = Math.max(0, ticks - 1); + return false; + }); + } + + public static void proc() { + ticks = MAX_DURATION; + } + + public static boolean display() { + return ticks > 0 && Dungeons.InvincibilityDuration; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawTimer(component, context, ticks, 0xffffffff); + } +} @@ -114,18 +114,21 @@ public class InvincibilityTimer { if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { Misc.setTitle(Text.literal("Bonzo")); } + InvincibilityDuration.proc(); } if (string.equals("Second Wind Activated! Your Spirit Mask saved your life!")) { spiritMaskTicks = SPIRIT_MASK_COOLDOWN; if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { Misc.setTitle(Text.literal("Spirit")); } + InvincibilityDuration.proc(); } if (string.equals("Your Phoenix Pet saved you from certain death!")) { phoenixTicks = PHOENIX_COOLDOWN; if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { Misc.setTitle(Text.literal("Phoenix")); } + InvincibilityDuration.proc(); } } @@ -1,22 +1,19 @@ package blade.addon.features.dungeon.f7.location; -import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.debug.Debug; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.ArrayList; @@ -37,7 +34,7 @@ public class PositionMessages { public static void init() { ClientTickEvents.END_CLIENT_TICK.register(PositionMessages::tick); - WorldRenderEvents.BEFORE_ENTITIES.register(PositionMessages::render); + RenderingEvents.FILLED_BLOCK.register(PositionMessages::render); Events.ON_LOCATION_CHANGE.register(newLocation -> { disableAll(); return false; @@ -98,19 +95,10 @@ public class PositionMessages { } } - private static void render(WorldRenderContext context) { + private static void render(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { if (!Location.inDungeon() || !Debug.renderPositions) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer consumer = consumers.getBuffer(RenderLayers.OUTLINE_LAYER); - MatrixStack.Entry entry = matrices.peek(); + MatrixStack.Entry entry = matrixStack.peek(); for (PositionMessage positionMessage : positionMessages) { Box box = positionMessage.getBox(); if (positionMessage.sent()) { @@ -119,9 +107,5 @@ public class PositionMessages { VertexRendering.drawBox(entry, consumer, box, 1, 0, 0, 1); } } - - - matrices.pop(); - } } @@ -1,22 +1,15 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; -import blade.addon.utils.Misc; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.passive.BatEntity; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.concurrent.ConcurrentLinkedQueue; @@ -47,70 +40,22 @@ public class BatHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> bats.removeIf(bat -> bat.isRemoved() ||bat.isDead())); - WorldRenderEvents.AFTER_ENTITIES.register(BatHighlight::renderFilled); - WorldRenderEvents.AFTER_ENTITIES.register(BatHighlight::renderOutline); + RenderingEvents.FILLED_ENTITY.register(BatHighlight::renderFilled); + RenderingEvents.OUTLINE_ENTITY.register(BatHighlight::renderOutline); } - private static void renderFilled(WorldRenderContext context) { - if (!MobHighlight.mobHighlight) return; - if (!MobHighlight.renderFilled()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.batFilledColor); - bats.forEach(entity -> { - - Vec3d pos = Misc.getPos(entity, tickProgress); - - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos); - - VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); - + bats.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } - private static void renderOutline(WorldRenderContext context) { - if (!MobHighlight.mobHighlight) return; - if (!MobHighlight.renderOutline()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); + private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline()) return; - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - MatrixStack.Entry entry = matrices.peek(); float[] rgba = RenderUtils.toFloats(MobHighlight.batOutlineColor); - - bats.forEach(entity -> { - - Vec3d pos = Misc.getPos(entity, tickProgress); - - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos); - - VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); - + bats.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } } @@ -2,19 +2,15 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.TrappedChestBlockEntity; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.concurrent.ConcurrentLinkedQueue; @@ -22,74 +18,41 @@ public class MimicHighlight { private static final Box box = new Box(0.0625, 0, 0.0625, 0.9375, 0.875, 0.9375); - private static final ConcurrentLinkedQueue<TrappedChestBlockEntity> mimicList = new ConcurrentLinkedQueue<>(); + private static final ConcurrentLinkedQueue<TrappedChestBlockEntity> mimics = new ConcurrentLinkedQueue<>(); public static void init() { Events.ON_LOCATION_CHANGE.register(location -> { - mimicList.clear(); + mimics.clear(); return false; }); Events.ON_BLOCK_ENTITY.register(blockEntity -> { if (!Location.inDungeon()) return false; if (blockEntity instanceof TrappedChestBlockEntity mimic) { - mimicList.add(mimic); + mimics.add(mimic); } return false; }); - ClientTickEvents.END_CLIENT_TICK.register(client -> mimicList.removeIf(BlockEntity::isRemoved)); + ClientTickEvents.END_CLIENT_TICK.register(client -> mimics.removeIf(BlockEntity::isRemoved)); - WorldRenderEvents.AFTER_ENTITIES.register(MimicHighlight::renderFilled); - WorldRenderEvents.AFTER_ENTITIES.register(MimicHighlight::renderOutline); + RenderingEvents.FILLED_ENTITY.register(MimicHighlight::renderFilled); + RenderingEvents.OUTLINE_ENTITY.register(MimicHighlight::renderOutline); } - private static void renderFilled(WorldRenderContext context) { - if (!MobHighlight.highlightMimicChests) return; - if (!MobHighlight.renderFilled()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.mimicFilledColor); - mimicList.forEach(blockEntity -> { - Box renderBox = box.offset(blockEntity.getPos()); - VertexRendering.drawFilledBox(matrices, filledConsumer, renderBox.minX, renderBox.minY, renderBox.minZ, renderBox.maxX, renderBox.maxY, renderBox.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); - + mimics.forEach(mimic -> RenderUtils.renderFilled(matrixStack, consumer, box.offset(mimic.getPos()), rgba)); } - private static void renderOutline(WorldRenderContext context) { - if (!MobHighlight.highlightMimicChests) return; - if (!MobHighlight.renderOutline()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); + private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline()) return; - MatrixStack.Entry entry = matrices.peek(); float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); - - mimicList.forEach(blockEntity -> { - Box renderBox = box.offset(blockEntity.getPos()); - VertexRendering.drawBox(entry, outlineConsumer, renderBox, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); - + mimics.forEach(mimic -> RenderUtils.renderOutline(matrixStack, consumer, box.offset(mimic.getPos()), rgba)); } } @@ -1,25 +1,20 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; -import blade.addon.utils.Misc; import blade.addon.utils.data.EntityUtil; import blade.addon.utils.events.Events; import blade.addon.utils.interfaces.ArmourStandHolder; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.mob.EndermanEntity; @@ -33,7 +28,6 @@ import net.minecraft.item.Items; import net.minecraft.text.Text; import net.minecraft.text.TextColor; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.ArrayList; import java.util.concurrent.ConcurrentLinkedQueue; @@ -69,7 +63,7 @@ public class MobHighlight { private static final ConcurrentLinkedQueue<DataHolder> savedEntities = new ConcurrentLinkedQueue<>(); - private static boolean dontRenderHighlight = false; + public static boolean dontRenderHighlight = false; @ConfigValue public static boolean mobHighlight = false; @ConfigValue @@ -169,8 +163,8 @@ public class MobHighlight { dontRenderHighlight = player.hasStatusEffect(StatusEffects.BLINDNESS); }); - WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::renderFilled); - WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::renderOutline); + RenderingEvents.FILLED_ENTITY.register(MobHighlight::renderFilled); + RenderingEvents.OUTLINE_ENTITY.register(MobHighlight::renderOutline); } public static void testArmourStand(ArmorStandEntity armorStand, MinecraftClient client) { @@ -331,9 +325,8 @@ public class MobHighlight { return currentHighlight == HighlightType.BOTH || currentHighlight == HighlightType.OUTLINE; } - public static Box getBox(Entity entity, Vec3d pos) { - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos); + public static Box getBox(Entity entity) { + Box box = EntityUtil.getBox(entity); //only shows the head if (entity instanceof EndermanEntity && entity.isInvisible() && MobHighlight.dontShowInvisibleMobs) { @@ -350,77 +343,38 @@ public class MobHighlight { return box; } - private static void renderFilled(WorldRenderContext context) { - if (!mobHighlight || dontRenderHighlight) return; - if (!renderFilled()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); + private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || dontRenderHighlight || !MobHighlight.renderFilled()) return; - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - savedEntities.forEach(dataHolder -> { - - Entity entity = dataHolder.entity; - MobType type = dataHolder.type; + for (DataHolder savedEntity : savedEntities) { + Entity entity = savedEntity.entity; + MobType type = savedEntity.type; if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; - Vec3d pos = Misc.getPos(entity, tickProgress); - - Box box = getBox(entity, pos); - - + Box box = getBox(entity); int filledColor = getFilledColor(type); float[] rgba = RenderUtils.toFloats(filledColor); - VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - }); + RenderUtils.renderFilled(matrixStack, consumer, box, rgba); - matrices.pop(); - + } } - private static void renderOutline(WorldRenderContext context) { - if (!mobHighlight || dontRenderHighlight) return; - if (!renderOutline()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); + private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || dontRenderHighlight || !MobHighlight.renderOutline()) return; - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(outlineWidth)); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - MatrixStack.Entry entry = matrices.peek(); - - savedEntities.forEach(dataHolder -> { - - Entity entity = dataHolder.entity; - MobType type = dataHolder.type; + for (DataHolder savedEntity : savedEntities) { + Entity entity = savedEntity.entity; + MobType type = savedEntity.type; if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; - Vec3d pos = Misc.getPos(entity, tickProgress); - Box box = getBox(entity, pos); - + Box box = getBox(entity); int outlineColor = getOutlineColor(type); float[] rgba = RenderUtils.toFloats(outlineColor); - VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - - matrices.pop(); + RenderUtils.renderOutline(matrixStack, consumer, box, rgba); + } } } @@ -1,110 +1,55 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; -import blade.addon.utils.Misc; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.passive.SheepEntity; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.concurrent.ConcurrentLinkedQueue; public class SheepHighlight { - private static final ConcurrentLinkedQueue<SheepEntity> sheepList = new ConcurrentLinkedQueue<>(); + private static final ConcurrentLinkedQueue<SheepEntity> sheeps = new ConcurrentLinkedQueue<>(); public static void init() { Events.ON_ENTITY_SPAWNED.register((entity, world) -> { if (!Location.inDungeon()) return false; if (entity instanceof SheepEntity sheep) { - sheepList.add(sheep); + sheeps.add(sheep); } return false; }); Events.ON_LOCATION_CHANGE.register(location -> { - sheepList.clear(); + sheeps.clear(); return false; }); - ClientTickEvents.END_CLIENT_TICK.register(client -> sheepList.removeIf(sheep -> sheep.isRemoved() || sheep.isDead())); + ClientTickEvents.END_CLIENT_TICK.register(client -> sheeps.removeIf(sheep -> sheep.isRemoved() || sheep.isDead())); - WorldRenderEvents.AFTER_ENTITIES.register(SheepHighlight::renderFilled); - WorldRenderEvents.AFTER_ENTITIES.register(SheepHighlight::renderOutline); + RenderingEvents.FILLED_ENTITY.register(SheepHighlight::renderFilled); + RenderingEvents.OUTLINE_ENTITY.register(SheepHighlight::renderOutline); } - private static void renderFilled(WorldRenderContext context) { - if (!MobHighlight.highlightSheep) return; - if (!MobHighlight.renderFilled()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.highlightSheep || !MobHighlight.renderFilled()) return; float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); - sheepList.forEach(entity -> { - - Vec3d pos = Misc.getPos(entity, tickProgress); - - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos); - - VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); - + sheeps.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } - private static void renderOutline(WorldRenderContext context) { - if (!MobHighlight.highlightSheep) return; - if (!MobHighlight.renderOutline()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - MatrixStack.Entry entry = matrices.peek(); - float[] rgba = RenderUtils.toFloats(MobHighlight.sheepOutlineColor); - - sheepList.forEach(entity -> { - - Vec3d pos = Misc.getPos(entity, tickProgress); - - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos); - - VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); + private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.highlightSheep || !MobHighlight.renderOutline()) return; + float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); + sheeps.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, EntityUtil.getBox(entity), rgba)); } } @@ -1,23 +1,17 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; -import blade.addon.utils.Misc; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EntityDimensions; import net.minecraft.entity.boss.WitherEntity; import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; import java.util.concurrent.ConcurrentLinkedQueue; @@ -50,70 +44,26 @@ public class WitherHighlight { ClientTickEvents.END_CLIENT_TICK.register(client -> withers.removeIf(wither -> wither.isRemoved() || wither.isDead())); - WorldRenderEvents.AFTER_ENTITIES.register(WitherHighlight::renderFilled); - WorldRenderEvents.AFTER_ENTITIES.register(WitherHighlight::renderOutline); + RenderingEvents.FILLED_ENTITY.register(WitherHighlight::renderFilled); + RenderingEvents.OUTLINE_ENTITY.register(WitherHighlight::renderOutline); } - private static void renderFilled(WorldRenderContext context) { - if (!MobHighlight.mobHighlight) return; - if (!MobHighlight.renderFilled()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); - - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - float[] rgba = RenderUtils.toFloats(MobHighlight.witherFilledColor); - withers.forEach(entity -> { - - Vec3d pos = Misc.getPos(entity, tickProgress); - - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos).expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); - - VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - }); - - matrices.pop(); - + private static Box getBox(WitherEntity wither) { + return EntityUtil.getBox(wither).expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); } - private static void renderOutline(WorldRenderContext context) { - if (!MobHighlight.mobHighlight) return; - if (!MobHighlight.renderOutline()) return; - Vec3d camera = context.worldState().cameraRenderState.pos; - MatrixStack matrices = context.matrices(); - if (matrices == null) return; - matrices.push(); - matrices.translate(-camera.x, -camera.y, -camera.z); + private static void renderFilled(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || !MobHighlight.renderFilled() || MobHighlight.dontRenderHighlight) return; - VertexConsumerProvider consumers = context.consumers(); - if (consumers == null) return; - VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); - - double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - - MatrixStack.Entry entry = matrices.peek(); - float[] rgba = RenderUtils.toFloats(MobHighlight.witherOutlineColor); - - withers.forEach(entity -> { - - Vec3d pos = Misc.getPos(entity, tickProgress); - - EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(pos).expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); - - VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - }); + float[] rgba = RenderUtils.toFloats(MobHighlight.batFilledColor); + withers.forEach(entity -> RenderUtils.renderFilled(matrixStack, consumer, getBox(entity), rgba)); + } - matrices.pop(); + private static void renderOutline(WorldRenderContext context, MatrixStack matrixStack, VertexConsumer consumer) { + if (!MobHighlight.mobHighlight || !MobHighlight.renderOutline() || MobHighlight.dontRenderHighlight) return; + float[] rgba = RenderUtils.toFloats(MobHighlight.batOutlineColor); + withers.forEach(entity -> RenderUtils.renderOutline(matrixStack, consumer, getBox(entity), rgba)); } } @@ -0,0 +1,36 @@ +package blade.addon.features.item; + +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import net.minecraft.util.math.ColorHelper; + +public class HeldItemToolTip { + + private static Text tooltip = Text.literal("Some toolTip"); + private static int color = 0xffffffff; + private static int heldItemFade = 0; + + public static void setText(Text newToolTip) { + tooltip = newToolTip; + } + + public static void setColor(int newColor) { + color = ColorHelper.withAlpha(newColor, -1); + } + + public static void setFade(int fade) { + heldItemFade = fade; + } + + public static boolean display() { + return ExtraOptions.moveToolTip && heldItemFade > 0; + } + + public static void render(HUDComponent component, DrawContext context) { + RenderUtils.drawCenteredText(context, component, tooltip, color); + } + +} @@ -11,7 +11,7 @@ import java.util.regex.PatternSyntaxException; public class Notification { private String matchString, notificationString, command; - private boolean useRegex, sendCommand; + private boolean useRegex, sendCommand, enabled; private int ticks; private final SoundData sound; @@ -21,16 +21,18 @@ public class Notification { this.command = ""; this.useRegex = false; this.sendCommand = false; + this.enabled = true; this.ticks = 20; this.sound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); } - public Notification(String matchString, String notificationString, String command, boolean useRegex, boolean sendCommand, int ticks, SoundData sound) { + public Notification(String matchString, String notificationString, String command, boolean useRegex, boolean sendCommand, boolean enabled, int ticks, SoundData sound) { this.matchString = matchString; this.notificationString = notificationString; this.command = command; this.useRegex = useRegex; this.sendCommand = sendCommand; + this.enabled = enabled; this.ticks = ticks; this.sound = sound; } @@ -63,6 +65,9 @@ public class Notification { return useRegex; } + public boolean isEnabled() { + return enabled; + } public void setMatchString(String matchString) { this.matchString = matchString; @@ -88,7 +93,12 @@ public class Notification { this.useRegex = useRegex; } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + public void testMessage(String message) { + if (!enabled) return; if (useRegex) { try { if (!message.matches(matchString)) return; @@ -113,6 +123,7 @@ public class Notification { ", command='" + command + '\'' + ", useRegex=" + useRegex + ", sendCommand=" + sendCommand + + ", enabled=" + enabled + ", ticks=" + ticks + ", sound=" + sound + '}'; @@ -30,6 +30,7 @@ public class NotificationEditScreen extends Screen { private void initScrollWidgets() { scroll.children().clear(); + scroll.add(new ConfigBool(Text.literal("Enabled"), notification::isEnabled, notification::setEnabled)); scroll.add(new ConfigString(Text.literal("Trigger on message"), notification::getMatchString, notification::setMatchString, false)); scroll.add(new ConfigString(Text.literal("Notification message"), notification::getNotificationString, notification::setNotificationString)); scroll.add(new ConfigBool(Text.literal("Use regex"), notification::useRegex, notification::setUseRegex)); @@ -4,19 +4,25 @@ import config.practical.utilities.Constants; import config.practical.utilities.DrawHelper; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; import net.minecraft.client.gui.widget.ClickableWidget; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.Pair; class NotificationEntry extends ClickableWidget { + private static final Identifier CROSS = Identifier.of(blade.addon.utils.Constants.NAMESPACE, "cross"); + private static final int PADDING = 5; - private static final int TEXT_SPACE = 100; - private static final int MAX_TEXT_WIDTH = 75; - private static final int BUTTON_WIDTH = 60; + private static final int TEXT_SPACE = 125; + private static final int MAX_TEXT_WIDTH = 100; + private static final int SPRITE_SIZE = 16; + private static final int SPRITE_WIDTH_AREA = SPRITE_SIZE + 10; private final NotificationList parent ; private final Notification notification; @@ -33,7 +39,7 @@ class NotificationEntry extends ClickableWidget { int y = getY(); int width = getWidth(); int height = getHeight(); - DrawHelper.drawBackground(context, x, y, width, height); + DrawHelper.drawBackground(context, x, y, width - SPRITE_WIDTH_AREA, height); MinecraftClient mc = MinecraftClient.getInstance(); TextRenderer textRenderer = mc.textRenderer; @@ -41,11 +47,8 @@ class NotificationEntry extends ClickableWidget { drawText(context, textRenderer, notification.getMatchString(), x + PADDING, y); drawText(context, textRenderer, notification.getNotificationString(), x + PADDING * 2 + TEXT_SPACE, y); - int buttonWidth = 60; - String remove = "Remove"; - textRenderer.trimToWidth(remove, TEXT_SPACE - 2); - DrawHelper.drawBackground(context, x + width - buttonWidth - PADDING, y + 4, buttonWidth, height - 8); - context.drawText(textRenderer, remove, x + width - buttonWidth, y + (30 - Constants.TEXT_HEIGHT) / 2, 0xffffffff, true); + Pair<Integer, Integer> pos = getRemovePos(); + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, CROSS, pos.getLeft(), pos.getRight(), SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); } private void drawText(DrawContext context, TextRenderer textRenderer, String string, int x, int y) { @@ -64,16 +67,28 @@ class NotificationEntry extends ClickableWidget { context.disableScissor(); } + private Pair<Integer, Integer> getRemovePos() { + return new Pair<>(getX() + width - SPRITE_SIZE - 5, getY() + (height - SPRITE_SIZE) / 2); + } + + private boolean inRemovalBounds(double x, double y) { + Pair<Integer, Integer> pos = getRemovePos(); + return x >= pos.getLeft() && x <= pos.getLeft() + SPRITE_SIZE && y >= pos.getRight() && y <= pos.getRight() + SPRITE_SIZE; + } + @Override public void onClick(Click click, boolean doubled) { double x = click.x(); double y = click.y(); - if (x >= getX() + width - BUTTON_WIDTH - PADDING && x <= getX() + width + BUTTON_WIDTH && y >= getY() + 4 && y <= getY() + height - 4) { + if (inRemovalBounds(x, y)) { parent.removeNotification(notification); return; } + //make sure you cant click around the button accidentally + if (width + getX() - SPRITE_WIDTH_AREA < x) return; + MinecraftClient.getInstance().setScreen(new NotificationEditScreen(notification)); } @@ -36,7 +36,6 @@ public class Notifications { public static void init() { notifications = new CopyOnWriteArrayList<>(); load(); - System.out.println("Noti: " + notifications); Events.ON_GAME_MESSAGE.register(text -> { String message = text.getString(); for (Notification notification : notifications) { @@ -46,9 +45,7 @@ public class Notifications { return false; }); - ClientTickEvents.END_CLIENT_TICK.register(event -> { - tick = Math.max(tick - 1, 0); - }); + ClientTickEvents.END_CLIENT_TICK.register(event -> tick = Math.max(tick - 1, 0)); } public static void addNotification(Notification notification) { @@ -129,6 +126,9 @@ public class Notifications { if (!notification.has("sendCommand")) continue; boolean sendCommand = notification.get("sendCommand").getAsBoolean(); + if (!notification.has("enabled")) continue; + boolean enabled = notification.get("enabled").getAsBoolean(); + if (!notification.has("ticks")) continue; int ticks = notification.get("ticks").getAsInt(); @@ -136,7 +136,7 @@ public class Notifications { SoundData sound = loadSoundData(notification.get("sound")); if (sound == null) continue; - notifications.add(new Notification(matchString, notificationString, command, useRegex, sendCommand, ticks, sound)); + notifications.add(new Notification(matchString, notificationString, command, useRegex, sendCommand, enabled, ticks, sound)); } catch (NumberFormatException e) { System.out.println("msg: " + e.getMessage()); } @@ -7,6 +7,7 @@ import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.rendering.RenderingEvents; import blade.addon.utils.times.PersonalBests; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; @@ -116,7 +117,7 @@ public class PracticeSS { } }); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(PracticeSS::render); + RenderingEvents.FILLED_BLOCK.register(PracticeSS::render); Events.ON_LOCAT …… diff 过长已截断 …… |
- hopefully improved highlighting - moved around and made config file a bit easier to navigate - added selectable sound for ss查看变更src/main/java/blade/addon/Bladeaddons.java | 4 ++ src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 21 ++++---- src/main/java/blade/addon/features/highlight/BatHighlight.java | 116 ++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/highlight/MobHighlight.java | 220 +++++++++++++++++++++++++++++------------------------------------------------------ src/main/java/blade/addon/features/highlight/SheepHighlight.java | 4 +- src/main/java/blade/addon/features/highlight/WitherHighlight.java | 119 +++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/CompactHoppity.java | 4 +- src/main/java/blade/addon/features/other/PracticeSS.java | 9 ++++ src/main/java/blade/addon/mixin/ArmorStandEntityMixin.java | 23 +++++++++ src/main/java/blade/addon/mixin/DrawContextMixin.java | 17 +++++++ src/main/java/blade/addon/mixin/EntityMixin.java | 8 +-- src/main/java/blade/addon/mixin/EntityRenderManagerMixin.java | 4 +- src/main/java/blade/addon/mixin/EntityRendererMixin.java | 9 +++- src/main/java/blade/addon/mixin/HandledScreenMixin.java | 7 +-- src/main/java/blade/addon/mixin/InGameHudMixin.java | 10 ++-- src/main/java/blade/addon/mixin/StatusEffectsDisplayMixin.java | 6 +-- src/main/java/blade/addon/mixin/StuckArrowsFeatureRendererMixin.java | 4 +- src/main/java/blade/addon/utils/config/Config.java | 79 ++++++++++++++++++++---------- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 30 ++---------- src/main/java/blade/addon/utils/config/values/Visual.java | 40 +++++++++++++++ src/main/java/blade/addon/utils/events/Events.java | 1 - src/main/java/blade/addon/utils/interfaces/ArmourStandHolder.java | 10 ++++ src/main/resources/blade-addons.mixins.json | 2 + 23 files changed, 514 insertions(+), 233 deletions(-) @@ -26,9 +26,11 @@ import blade.addon.features.dungeon.f7.terms.LeapNotification; import blade.addon.features.dungeon.f7.terms.MelodyWarning; import blade.addon.features.dungeon.f7.terms.Pre4Notifier; import blade.addon.features.dungeon.f7.terms.TermStartTimer; +import blade.addon.features.highlight.BatHighlight; import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; import blade.addon.features.highlight.SheepHighlight; +import blade.addon.features.highlight.WitherHighlight; import blade.addon.features.item.DropAnimation; import blade.addon.features.notifications.Notifications; import blade.addon.features.other.CompactHoppity; @@ -108,5 +110,7 @@ public class Bladeaddons implements ModInitializer { MimicHighlight.init(); SheepHighlight.init(); Notifications.init(); + BatHighlight.init(); + WitherHighlight.init(); } } \ No newline at end of file @@ -14,7 +14,6 @@ import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; @@ -57,7 +56,6 @@ public class RelicTimer { } } - private static boolean ignoreChecks = false; private static final int GREEN_COLOR = 0xff00ff00; private static final int RED_COLOR = 0xffff0000; @@ -68,7 +66,9 @@ public class RelicTimer { private static Relic pickedupRelic = null; private static int tick = Floor7.relicSpawnTicks; + private static boolean sentRelicTimes = false; + private static boolean ignoreChecks = false; //only here to test the relic progress bar private static boolean forceGUI = false; @@ -101,9 +101,8 @@ public class RelicTimer { return false; }); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !Phase.inP5()) return; - Debug.sendDebugMessage(Text.literal("Debug: ").append(message)); + Events.ON_GAME_MESSAGE.register(message -> { + if (!Location.inDungeon() || !Phase.inP5()) return false; String str = message.getString().replaceAll("§.", ""); Matcher matcher = PATTERN.matcher(str); if (matcher.find()) { @@ -111,24 +110,24 @@ public class RelicTimer { String relicString = matcher.group(2); ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player == null) return; + if (player == null) return false; if (name.equals(player.getName().getString())) { pickedupRelic = Relic.valueOf(relicString.toUpperCase()); Debug.sendDebugMessage(Text.literal("Picked up relic " + relicString)); } } - }); + return false; + }); ClientTickEvents.END_WORLD_TICK.register(world -> { - if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes) return; + if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes ||sentRelicTimes) return; Iterable<Entity> entities = world.getEntities(); - if (allRelicsPlaced()) return; for (Entity entity : entities) { if (entity instanceof ArmorStandEntity armorStand) { - if (!EntityUtil.isWearing(armorStand, EquipmentSlot.HEAD, "Relic")) return; + if (!EntityUtil.isWearing(armorStand, EquipmentSlot.HEAD, "Relic")) continue; double ax = armorStand.getX(); double az = armorStand.getZ(); @@ -146,6 +145,7 @@ public class RelicTimer { for (Relic relic : Relic.values()) { long time = relic.placedTime - phaseStartTime; Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + Constants.DECIMAL_FORMAT.format(time) + "s&a.")); + sentRelicTimes = true; } } }); @@ -225,6 +225,7 @@ public class RelicTimer { for (Relic relic : Relic.values()) { relic.placedTime = 0; } + sentRelicTimes = false; } private static boolean allRelicsPlaced() { @@ -0,0 +1,116 @@ +package blade.addon.features.highlight; + +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderUtils; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.passive.BatEntity; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class BatHighlight { + + private static final float[] BAT_HEALTHS = {100.0f, 200.0f, 400.0f, 800.0f}; + + private static final ConcurrentLinkedQueue<BatEntity> bats = new ConcurrentLinkedQueue<>(); + + public static void init() { + + Events.ON_ENTITY_TRACKED.register((entity, world) -> { + if (!Location.inDungeon() || !MobHighlight.mobHighlight) return false; + if (entity instanceof BatEntity bat) { + for (float health : BAT_HEALTHS) { + if (health == bat.getHealth()) { + bats.add(bat); + } + } + } + return false; + }); + + Events.ON_LOCATION_CHANGE.register(location -> { + bats.clear(); + return false; + }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> bats.removeIf(bat -> bat.isRemoved() ||bat.isDead())); + + WorldRenderEvents.AFTER_ENTITIES.register(BatHighlight::renderFilled); + WorldRenderEvents.AFTER_ENTITIES.register(BatHighlight::renderOutline); + } + + private static void renderFilled(WorldRenderContext context) { + if (!MobHighlight.mobHighlight) return; + if (!MobHighlight.renderFilled()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + float[] rgba = RenderUtils.toFloats(MobHighlight.batFilledColor); + bats.forEach(entity -> { + + Vec3d pos = Misc.getPos(entity, tickProgress); + + EntityDimensions dimension = entity.getDimensions(entity.getPose()); + Box box = dimension.getBoxAt(pos); + + VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + + private static void renderOutline(WorldRenderContext context) { + if (!MobHighlight.mobHighlight) return; + if (!MobHighlight.renderOutline()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); + + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + MatrixStack.Entry entry = matrices.peek(); + float[] rgba = RenderUtils.toFloats(MobHighlight.batOutlineColor); + + bats.forEach(entity -> { + + Vec3d pos = Misc.getPos(entity, tickProgress); + + EntityDimensions dimension = entity.getDimensions(entity.getPose()); + Box box = dimension.getBoxAt(pos); + + VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + +} @@ -3,33 +3,29 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.data.EntityUtil; -import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; +import blade.addon.utils.interfaces.ArmourStandHolder; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; import config.practical.manager.ConfigValue; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.boss.WitherEntity; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.mob.EndermanEntity; import net.minecraft.entity.mob.SkeletonEntity; import net.minecraft.entity.mob.WitherSkeletonEntity; import net.minecraft.entity.mob.ZombieEntity; -import net.minecraft.entity.passive.BatEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -40,17 +36,17 @@ import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class MobHighlight { - enum MobType { - STAR, TANK, MINI, FEL, ASSASSIN, BAT, WITHER, MIMIC + public enum MobType { + STAR, TANK, MINI, FEL, ASSASSIN, MIMIC } + record DataHolder(Entity entity, MobHighlight.MobType type) {} + public enum HighlightType { FILLED("Filled"), OUTLINE("Outline"), BOTH("Both"); @@ -70,17 +66,8 @@ public class MobHighlight { private static final int PLAYER_HEAD_ID = Item.getRawId(Items.PLAYER_HEAD); private static final int LEATHER_BOOTS_ID = Item.getRawId(Items.LEATHER_BOOTS); - private static final Pattern MIMIC_PATTERN = Pattern.compile("Mimic"); - private static final Pattern WEAPON_PATTERN = Pattern.compile("^Silent Death$"); - private static final Pattern FEL_PATTERN = Pattern.compile("Fel"); - - private static final float WITHER_BORN_HEALTH = 300f; - private static final float[] BAT_HEALTHS = {100.0f, 200.0f, 400.0f, 800.0f}; - private static final String[] TANK_MOBS = {"Zombie Commander", "Zombie Lord", "Skeleton Lord", "Withermancer", "Super Archer"}; - private static final String[] MINI_BOSSES = {"Lost Adventurer", "Angry Archaeologist", "Frozen Adventurer"}; + private static final ConcurrentLinkedQueue<DataHolder> savedEntities = new ConcurrentLinkedQueue<>(); - private static final ConcurrentHashMap<Entity, MobType> trackedMobs = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap<Entity, Integer> possibleEntities = new ConcurrentHashMap<>(); private static boolean dontRenderHighlight = false; @ConfigValue @@ -142,93 +129,75 @@ public class MobHighlight { public static void init() { - Events.ON_ENTITY_TRACKED.register((entity, world) -> { - if (!Location.inDungeon() || !mobHighlight) return false; + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (!Location.inDungeon()) return; - if (Phase.inBoss()) { - if (entity instanceof WitherEntity wither) { - if (wither.getHealth() != WITHER_BORN_HEALTH) { - trackedMobs.put(wither, MobType.WITHER); - } - } - } else { + ClientWorld world = client.world; + if (world == null) return; + for (Entity entity: world.getEntities()) { if (entity instanceof ArmorStandEntity armorStand) { - testArmourStand(armorStand); - } - - if (entity instanceof BatEntity bat) { - for (float health : BAT_HEALTHS) { - if (health == bat.getHealth()) { - trackedMobs.put(bat, MobType.BAT); - } - } + ArmourStandHolder holder = (ArmourStandHolder) armorStand; + if (holder.blade_addons$hasBeenScanned()) continue; + holder.blade_addons$setScanned(true); + testArmourStand(armorStand, client); } } + savedEntities.removeIf(dataHolder -> dataHolder.entity.isRemoved()); + }); + + Events.ON_ENTITY_TRACKED.register((entity, world) -> { + if (!Location.inDungeon()) return false; + if (entity instanceof PlayerEntity player) { - if (isShadowAssassin(player)) { - trackedMobs.put(player, MobType.ASSASSIN); + if (MobHighlight.isShadowAssassin(player)) { + savedEntities.add(new DataHolder(player, MobType.ASSASSIN)); } } return false; }); + Events.ON_LOCATION_CHANGE.register(newLocation -> { + savedEntities.clear(); + return false; + }); + ClientTickEvents.END_CLIENT_TICK.register(minecraftClient -> { ClientPlayerEntity player = minecraftClient.player; if (player == null) return; dontRenderHighlight = player.hasStatusEffect(StatusEffects.BLINDNESS); }); - ClientEntityEvents.ENTITY_LOAD.register(((entity, world) -> { - if (entity instanceof PlayerEntity player) { - if (isARealPlayer(player)) return; - } - - if (isAPossibleStaredMob(entity) || entity instanceof EndermanEntity) { - possibleEntities.put(entity, 0); - } - })); - - ClientEntityEvents.ENTITY_UNLOAD.register((entity, world) -> { - if (entity == null) return; - trackedMobs.remove(entity); - possibleEntities.remove(entity); - }); - - Events.ON_LOCATION_CHANGE.register(newLocation -> { - trackedMobs.clear(); - possibleEntities.clear(); - return false; - }); - WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::renderFilled); WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::renderOutline); } - private static void testArmourStand(ArmorStandEntity armorStand) { + public static void testArmourStand(ArmorStandEntity armorStand, MinecraftClient client) { Text text = armorStand.getCustomName(); if (text == null) return; - String string = text.getString(); + String name = text.getString(); + + ClientWorld world = client.world; + if (world == null) return; - Matcher matcher = MIMIC_PATTERN.matcher(string); - if (matcher.find()) { - attemptAddMob(armorStand, MobHighlight::isAPossibleMimic, 3.5, MobType.MIMIC); + if (name.contains("Mimic")) { + attemptAddMob(armorStand, MobHighlight::isAPossibleMimic, 3.5, MobHighlight.MobType.MIMIC, world); return; } - if (containsStarText(text)) { - matcher = FEL_PATTERN.matcher(string); - if (matcher.find()) { - attemptAddMob(armorStand, entity -> entity instanceof EndermanEntity, 4, MobType.FEL); - } else if (isMiniBoss(string)) { - attemptAddMob(armorStand, MobHighlight::isMiniBoss, 4, MobType.MINI); - } else if (isTankMob(string)) { - attemptAddMob(armorStand, MobHighlight::isAPossibleStaredMob, 3, MobType.TANK); - } else { - attemptAddMob(armorStand, MobHighlight::isAPossibleStaredMob, 3, MobType.STAR); - } + if (!MobHighlight.containsStarText(text)) return; + + if (name.contains("Fel")) { + attemptAddMob(armorStand, entity -> entity instanceof EndermanEntity, 4, MobHighlight.MobType.FEL, world); + } else if (isMiniBoss(name)) { + attemptAddMob(armorStand, MobHighlight::isMiniBoss, 4, MobHighlight.MobType.MINI, world); + } else if (isTankMob(name)) { + attemptAddMob(armorStand, MobHighlight::isAPossibleStaredMob, 3, MobHighlight.MobType.TANK, world); + } else { + attemptAddMob(armorStand, MobHighlight::isAPossibleStaredMob, 3, MobHighlight.MobType.STAR, world); } + } public static boolean containsStarText(Text text) { @@ -245,23 +214,15 @@ public class MobHighlight { return false; } - public static boolean isTankMob(String string) { - for (String tank : TANK_MOBS) { - if (string.contains(tank)) return true; - } - - return false; + public static boolean isTankMob(String name) { + return name.contains("Zombie Commander") || name.contains("Zombie Lord") || name.contains("Skeleton Lord")|| name.contains("Withermancer") || name.contains("Super Archer"); } - public static boolean isMiniBoss(String string) { - for (String mini : MINI_BOSSES) { - if (string.contains(mini)) return true; - } - - return false; + public static boolean isMiniBoss(String name) { + return name.contains("Lost Adventurer") || name.contains("Angry Archaeologist") || name.contains("Frozen Adventurer"); } - private static void attemptAddMob(ArmorStandEntity armorStand, Predicate<Entity> requirements, double maxDistance, MobType mobType) { + public static void attemptAddMob(ArmorStandEntity armorStand, Predicate<Entity> requirements, double maxDistance, MobHighlight.MobType mobType, ClientWorld world) { Entity closest = null; double smallestDistance = maxDistance; double maxY = armorStand.getY(); @@ -270,7 +231,8 @@ public class MobHighlight { ArrayList<Entity> meetsRequirements = new ArrayList<>(); - possibleEntities.forEach((entity, integer) -> { + Iterable<Entity> entities = world.getEntities(); + entities.forEach(entity -> { if (!entity.getBoundingBox().intersects(boundingBox)) return; if (!requirements.test(entity)) return; if (entity.getY() > maxY) return; @@ -279,7 +241,6 @@ public class MobHighlight { }); for (Entity current : meetsRequirements) { - if (trackedMobs.containsKey(current)) continue; if (!current.getBoundingBox().intersects(boundingBox)) continue; if (!requirements.test(current)) continue; if (current.getY() > maxY) continue; @@ -296,43 +257,22 @@ public class MobHighlight { return; } - possibleEntities.remove(closest); - trackedMobs.put(closest, mobType); + savedEntities.add(new DataHolder(closest, mobType)); } - private static boolean isShadowAssassin(PlayerEntity player) { - if (isARealPlayer(player)) return false; + public static boolean isShadowAssassin(PlayerEntity player) { + if (EntityUtil.isARealPlayer(player)) return false; ItemStack heldItem = player.getMainHandStack(); ItemStack boots = player.getInventory().getStack(36); Text text = heldItem.getCustomName(); if (text == null) return false; - Matcher matcher = WEAPON_PATTERN.matcher(text.getString()); - if (!matcher.find()) return false; + if (!text.getString().equals("Silent Death")) return false; return Item.getRawId(boots.getItem()) == LEATHER_BOOTS_ID; } - private static boolean isARealPlayer(Entity entity) { - if (entity instanceof PlayerEntity player) { - - if (EntityUtil.isClientPlayer(player)) return true; - - ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); - if (networkHandler == null) return false; - - PlayerListEntry entry = networkHandler.getPlayerListEntry(player.getUuid()); - - //this is a hack which will fail if someone has a really old bugged ign that includes a space - if (entry != null) { - String name = entry.getProfile().name(); - return !name.isEmpty() && !name.contains(" "); - } - } - return false; - } - - private static boolean isAPossibleStaredMob(Entity entity) { + public static boolean isAPossibleStaredMob(Entity entity) { return switch (entity) { case ZombieEntity ignored -> true; case SkeletonEntity ignored -> true; @@ -342,15 +282,16 @@ public class MobHighlight { }; } - private static boolean isAPossibleMimic(Entity entity) { + public static boolean isAPossibleMimic(Entity entity) { if (entity instanceof ZombieEntity zombie) { return zombie.isBaby(); } return false; } - private static boolean isMiniBoss(Entity entity) { + public static boolean isMiniBoss(Entity entity) { if (entity instanceof PlayerEntity player) { + if (EntityUtil.isARealPlayer(player)) return false; ItemStack helmet = player.getInventory().getStack(39); int id = Item.getRawId(helmet.getItem()); return id == DIAMOND_HELMET_ID || id == PLAYER_HEAD_ID; @@ -359,39 +300,28 @@ public class MobHighlight { return false; } - private static int getFilledColor(MobType mob) { + public static int getFilledColor(MobType mob) { return switch (mob) { case STAR -> starFilledColor; case TANK -> tankFilledColor; case MINI -> miniFilledColor; case FEL -> felFilledColor; case ASSASSIN -> assassinFilledColor; - case BAT -> batFilledColor; - case WITHER -> witherFilledColor; case MIMIC -> mimicFilledColor; }; } - private static int getOutLineColor(MobType mob) { + public static int getOutlineColor(MobType mob) { return switch (mob) { case STAR -> starOutlineColor; case TANK -> tankOutlineColor; case MINI -> miniOutlineColor; case FEL -> felOutlineColor; case ASSASSIN -> assassinOutlineColor; - case BAT -> batOutlineColor; - case WITHER -> witherOutlineColor; case MIMIC -> mimicOutlineColor; }; } - public static int getFilledColor(Entity entity) { - return getFilledColor(trackedMobs.get(entity)); - } - - public static int getOutlineColor(Entity entity) { - return getOutLineColor(trackedMobs.get(entity)); - } public static boolean renderFilled() { return currentHighlight == HighlightType.BOTH || currentHighlight == HighlightType.FILLED; @@ -401,14 +331,10 @@ public class MobHighlight { return currentHighlight == HighlightType.BOTH || currentHighlight == HighlightType.OUTLINE; } - private static Box getBox(Entity entity, Vec3d pos) { + public static Box getBox(Entity entity, Vec3d pos) { EntityDimensions dimension = entity.getDimensions(entity.getPose()); Box box = dimension.getBoxAt(pos); - if (entity instanceof WitherEntity) { - box = box.expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); - } - //only shows the head if (entity instanceof EndermanEntity && entity.isInvisible() && MobHighlight.dontShowInvisibleMobs) { box = box.expand(0, -1.8, 0).offset(0, -1.2, 0); @@ -439,7 +365,10 @@ public class MobHighlight { double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); - trackedMobs.forEach((entity, mobType) -> { + savedEntities.forEach(dataHolder -> { + + Entity entity = dataHolder.entity; + MobType type = dataHolder.type; if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; @@ -448,7 +377,7 @@ public class MobHighlight { Box box = getBox(entity, pos); - int filledColor = MobHighlight.getFilledColor(entity); + int filledColor = getFilledColor(type); float[] rgba = RenderUtils.toFloats(filledColor); VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); }); @@ -475,14 +404,17 @@ public class MobHighlight { MatrixStack.Entry entry = matrices.peek(); - trackedMobs.forEach((entity, mobType) -> { + savedEntities.forEach(dataHolder -> { + + Entity entity = dataHolder.entity; + MobType type = dataHolder.type; if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; Vec3d pos = Misc.getPos(entity, tickProgress); Box box = getBox(entity, pos); - int outlineColor = MobHighlight.getOutlineColor(entity); + int outlineColor = getOutlineColor(type); float[] rgba = RenderUtils.toFloats(outlineColor); VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); }); @@ -26,7 +26,7 @@ public class SheepHighlight { public static void init() { - Events.ON_ENTITY_TRACKED.register((entity, world) -> { + Events.ON_ENTITY_SPAWNED.register((entity, world) -> { if (!Location.inDungeon()) return false; if (entity instanceof SheepEntity sheep) { sheepList.add(sheep); @@ -39,7 +39,7 @@ public class SheepHighlight { return false; }); - ClientTickEvents.END_CLIENT_TICK.register(client -> sheepList.removeIf(SheepEntity::isRemoved)); + ClientTickEvents.END_CLIENT_TICK.register(client -> sheepList.removeIf(sheep -> sheep.isRemoved() || sheep.isDead())); WorldRenderEvents.AFTER_ENTITIES.register(SheepHighlight::renderFilled); WorldRenderEvents.AFTER_ENTITIES.register(SheepHighlight::renderOutline); @@ -0,0 +1,119 @@ +package blade.addon.features.highlight; + +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderUtils; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.boss.WitherEntity; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class WitherHighlight { + + private static final float WITHER_BORN_HEALTH = 300f; + + private static final ConcurrentLinkedQueue<WitherEntity> withers = new ConcurrentLinkedQueue<>(); + + + public static void init() { + Events.ON_ENTITY_TRACKED.register((entity, world) -> { + if (!Location.inDungeon() || !MobHighlight.mobHighlight) return false; + + if (Phase.inBoss()) { + if (entity instanceof WitherEntity wither) { + if (wither.getHealth() != WITHER_BORN_HEALTH) { + withers.add(wither); + } + } + } + + return false; + }); + + Events.ON_LOCATION_CHANGE.register(location -> { + withers.clear(); + return false; + }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> withers.removeIf(wither -> wither.isRemoved() || wither.isDead())); + + WorldRenderEvents.AFTER_ENTITIES.register(WitherHighlight::renderFilled); + WorldRenderEvents.AFTER_ENTITIES.register(WitherHighlight::renderOutline); + } + + private static void renderFilled(WorldRenderContext context) { + if (!MobHighlight.mobHighlight) return; + if (!MobHighlight.renderFilled()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + float[] rgba = RenderUtils.toFloats(MobHighlight.witherFilledColor); + withers.forEach(entity -> { + + Vec3d pos = Misc.getPos(entity, tickProgress); + + EntityDimensions dimension = entity.getDimensions(entity.getPose()); + Box box = dimension.getBoxAt(pos).expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); + + VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + + private static void renderOutline(WorldRenderContext context) { + if (!MobHighlight.mobHighlight) return; + if (!MobHighlight.renderOutline()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); + + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + MatrixStack.Entry entry = matrices.peek(); + float[] rgba = RenderUtils.toFloats(MobHighlight.witherOutlineColor); + + withers.forEach(entity -> { + + Vec3d pos = Misc.getPos(entity, tickProgress); + + EntityDimensions dimension = entity.getDimensions(entity.getPose()); + Box box = dimension.getBoxAt(pos).expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); + + VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + +} @@ -1,7 +1,7 @@ package blade.addon.features.other; import blade.addon.utils.Misc; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import blade.addon.utils.events.Events; import net.minecraft.text.Text; @@ -17,7 +17,7 @@ public class CompactHoppity { public static void init() { Events.ON_GAME_MESSAGE.register(text -> { - if (!ExtraOptions.compactHoppityMsgs) return false; + if (!Visual.compactHoppityMsgs) return false; String string = text.getString(); if (string.equals("HOPPITY'S HUNT You found a Hitman Egg!")) { @@ -128,13 +128,20 @@ public class PracticeSS { if (started && ExtraOptions.autoSkip) { start(world, state, pos); startPos = pos; + Misc.sendSound(ExtraOptions.ssSound); } else if (inSkipPhase || System.currentTimeMillis() - skippedTime < SKIP_TIME_MS) { clicks++; if (clicks >= 2 && inSkipPhase) { skipped = true; skippedTime = System.currentTimeMillis(); } + + if (clicks < 3) { + Misc.sendSound(ExtraOptions.ssSound); + } + } else { + Misc.sendSound(ExtraOptions.ssSound); start(world, state, pos); startPos = pos; } @@ -148,6 +155,8 @@ public class PracticeSS { BlockPos nextButton = buttons.get(currentIndex); if (samePosition(pos, nextButton)) { currentIndex++; + Misc.sendSound(ExtraOptions.ssSound); + if (currentIndex == 5) { recordTime(); @@ -0,0 +1,23 @@ +package blade.addon.mixin; + +import blade.addon.utils.interfaces.ArmourStandHolder; +import net.minecraft.entity.decoration.ArmorStandEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ArmorStandEntity.class) +public class ArmorStandEntityMixin implements ArmourStandHolder { + + @Unique + private boolean scanned = false; + + @Override + public boolean blade_addons$hasBeenScanned() { + return scanned; + } + + @Override + public void blade_addons$setScanned(boolean value) { + scanned = value; + } +} @@ -0,0 +1,17 @@ +package blade.addon.mixin; + +import blade.addon.utils.config.values.Visual; +import net.minecraft.client.gui.DrawContext; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(DrawContext.class) +public class DrawContextMixin { + + @ModifyVariable(method = "drawCooldownProgress", at=@At("STORE"), ordinal = 0) + private float noCooldown(float f) { + return Visual.hideCooldown? 0: f; + } + +} @@ -1,6 +1,6 @@ package blade.addon.mixin; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import net.minecraft.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -10,10 +10,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Entity.class) public class EntityMixin { - @Inject(method = "isGlowing", at=@At("HEAD"), cancellable = true) + @Inject(method = "isGlowing", at = @At("HEAD"), cancellable = true) public void isGlowing(CallbackInfoReturnable<Boolean> cir) { - if (ExtraOptions.disableGlowing) { - cir.setReturnValue(false); + if (Visual.disableGlowing) { + cir.setReturnValue(false); } } } @@ -5,7 +5,7 @@ import blade.addon.features.dungeon.ItemHighlight; import blade.addon.features.highlight.MobHighlight; import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.Frustum; @@ -34,7 +34,7 @@ public class EntityRenderManagerMixin { } } - if (!entity.isAlive() && ExtraOptions.hideDeadEntities) { + if (!entity.isAlive() && Visual.hideDeadEntities) { cir.setReturnValue(false); return; } @@ -1,7 +1,7 @@ package blade.addon.mixin; import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import blade.addon.utils.data.EntityUtil; import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.entity.EntityRenderer; @@ -31,7 +31,12 @@ public class EntityRendererMixin<T extends Entity, S extends EntityRenderState> @Inject(method = "updateRenderState", at = @At("TAIL")) public void hideFire(T entity, S state, float tickProgress, CallbackInfo ci) { - if (entity instanceof PlayerEntity player && ExtraOptions.hideFireInf5) { + if (Visual.hideEntityFire) { + state.onFire = false; + return; + } + + if (entity instanceof PlayerEntity player && Visual.hideFireInf5) { if (EntityUtil.isClientPlayer(player)) { state.onFire = false; } @@ -7,6 +7,7 @@ import blade.addon.features.item.SelectedPetHighlight; import blade.addon.features.item.StarCountHighlight; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; @@ -51,11 +52,11 @@ public class HandledScreenMixin<T extends ScreenHandler> { } } - if (ExtraOptions.highlightProtectedItem) { + if (Visual.highlightProtectedItem) { ProtectItem.draw(context, stack, x, y); } - if (ExtraOptions.itemRarityBackground) { + if (Visual.itemRarityBackground) { ItemRarityHighlight.draw(context, stack, x, y); } } @@ -70,7 +71,7 @@ public class HandledScreenMixin<T extends ScreenHandler> { MaskHighlight.draw(context, stack, x, y); } - if (ExtraOptions.drawStarCount) { + if (Visual.drawStarCount) { StarCountHighlight.draw(context, stack, x, y); } } @@ -5,7 +5,7 @@ import blade.addon.features.dungeon.f7.terms.TitleHider; import blade.addon.features.item.ItemRarityHighlight; import blade.addon.features.item.ProtectItem; import blade.addon.features.item.StarCountHighlight; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import blade.addon.utils.interfaces.GameHud; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; @@ -38,11 +38,11 @@ public class InGameHudMixin implements GameHud { @Inject(method = "renderHotbarItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;III)V"), order = 2000) public void drawBackground(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { - if (ExtraOptions.itemRarityBackground) { + if (Visual.itemRarityBackground) { ItemRarityHighlight.draw(context, stack, x, y); } - if (ExtraOptions.highlightProtectedItem) { + if (Visual.highlightProtectedItem) { ProtectItem.draw(context, stack, x, y); } @@ -50,14 +50,14 @@ public class InGameHudMixin implements GameHud { @Inject(method = "renderHotbarItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;III)V", shift = At.Shift.AFTER), order = 2000) public void drawStar(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { - if (ExtraOptions.drawStarCount) { + if (Visual.drawStarCount) { StarCountHighlight.draw(context, stack, x, y); } } @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD"), cancellable = true, order = 2000) public void renderStatusEffectsOverLay(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { - if (ExtraOptions.hideStatusOverLay) { + if (Visual.hideStatusOverLay) { ci.cancel(); } } @@ -1,6 +1,6 @@ package blade.addon.mixin; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.StatusEffectsDisplay; import org.spongepowered.asm.mixin.Mixin; @@ -13,14 +13,14 @@ public class StatusEffectsDisplayMixin { @Inject(method = "drawStatusEffects", at=@At("HEAD"), cancellable = true) public void drawEffects(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { - if (ExtraOptions.hideStatusOverLay) { + if (Visual.hideStatusOverLay) { ci.cancel(); } } @Inject(method = "drawStatusEffectTooltip", at=@At("HEAD"), cancellable = true) public void drawToolTip(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { - if (ExtraOptions.hideStatusOverLay) { + if (Visual.hideStatusOverLay) { ci.cancel(); } } @@ -1,6 +1,6 @@ package blade.addon.mixin; -import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.config.values.Visual; import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -12,7 +12,7 @@ public class StuckArrowsFeatureRendererMixin { @Inject(method = "getObjectCount", at=@At("TAIL"), cancellable = true) public void shouldRender(CallbackInfoReturnable<Integer> cir) { - if (ExtraOptions.hideStuckArrows) { + if (Visual.hideStuckArrows) { cir.setReturnValue(0); } @@ -12,6 +12,7 @@ import blade.addon.utils.config.values.Buttons; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.config.values.Visual; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; import blade.addon.utils.dungeon.Split; @@ -38,11 +39,29 @@ public class Config { private static final Text TITLE = Text.literal("Blade Addons"); public static final ConfigManager manager = new ConfigManager(FolderUtility.OLD_PATH + FolderUtility.ADDONS_NAME, - List.of(Phase.class, Section.class, Split.class, MobHighlight.class, ExtraOptions.class, DianaNotifier.class, Components.class, Dungeons.class, Floor7.class, Buttons.class)); + List.of(Phase.class, Section.class, Split.class, MobHighlight.class, ExtraOptions.class, DianaNotifier.class, Components.class, Dungeons.class, Floor7.class, Buttons.class, Visual.class)); public static Screen createScreen(Screen parent) { ConfigurableScreen screen = new ConfigurableScreen(TITLE, parent, manager); + screen.addCategory(general()); + screen.addCategory(dungeons()); + screen.addCategory(floor7()); + screen.addCategory(splits()); + screen.addCategory(highlight()); + screen.addCategory(extra()); + screen.addCategory(visual()); + screen.addCategory(buttons()); + return screen; + } + private static ConfigCategory general() { + ConfigCategory general = new ConfigCategory("General"); + general.add(new ConfigString(Text.literal("Message prefix"), () -> ExtraOptions.textPrefix, str -> ExtraOptions.textPrefix = str)); + general.add(new ConfigButton(Text.literal("Edit Notifications"), () -> MinecraftClient.getInstance().setScreen(new NotificationList()))); + return general; + } + + private static ConfigCategory dungeons() { ConfigCategory dungeons = new ConfigCategory("Dungeons"); ConfigSection start = new ConfigSection(Text.literal("Start of run")); start.add(new ConfigBool(Text.literal("Warp cooldown"), () -> Dungeons.enableWarpCooldown, bool -> Dungeons.enableWarpCooldown = bool)); @@ -103,9 +122,10 @@ public class Config { dungeons.add(new ConfigBool(Text.literal("Hide blaze nametags"), () -> Dungeons.hideBlazeNameTag, bool -> Dungeons.hideBlazeNameTag = bool)); dungeons.add(new ConfigBool(Text.literal("Disable drop animation"), () -> Dungeons.disableDropAnimation, bool -> Dungeons.disableDropAnimation = bool)); dungeons.add(new ConfigBool(Text.literal("Mask cooldown highlight"), () -> Dungeons.maskHighlight, bool -> Dungeons.maskHighlight = bool)); + return dungeons; + } - screen.addCategory(dungeons); - + private static ConfigCategory floor7() { ConfigCategory floor7 = new ConfigCategory("Floor 7"); floor7.add(new ConfigBool(Text.literal("Combine tick timers"), () -> Floor7.combineTickTimers, bool -> Floor7.combineTickTimers = bool)); floor7.add(new ConfigBool(Text.literal("Enable player leap count"), () -> Floor7.leapNotifications, bool -> Floor7.leapNotifications = bool)); @@ -173,8 +193,10 @@ public class Config { floor7.add(phase5); - screen.addCategory(floor7); + return floor7; + } + private static ConfigCategory splits() { ConfigCategory splits = new ConfigCategory("Splits"); splits.add(new ConfigBool(Text.literal("Enable Splits"), () -> Phase.enableSplits, bool -> Phase.enableSplits = bool)); splits.add(new ConfigBool(Text.literal("Include total time"), () -> Phase.includeTotalTime, bool -> Phase.includeTotalTime = bool)); @@ -194,8 +216,10 @@ public class Config { splits.add(new ConfigColor(Text.literal("Parentheses color (Inactive)"), () -> Split.parenthesesColorInactive, color -> Split.parenthesesColorInactive = color, "parentheses-inactive", false)); splits.add(new ConfigColor(Text.literal("Parentheses color (Ongoing)"), () -> Split.parenthesesColorOngoing, color -> Split.parenthesesColorOngoing = color, "parentheses-ongoing", false)); splits.add(new ConfigColor(Text.literal("Parentheses color (Complete)"), () -> Split.parenthesesColorComplete, color -> Split.parenthesesColorComplete = color, "parentheses-complete", false)); - screen.addCategory(splits); + return splits; + } + private static ConfigCategory highlight() { ConfigCategory highlight = new ConfigCategory("Mob Highlight"); highlight.add(new ConfigBool(Text.literal("Enable mob highlight"), () -> MobHighlight.mobHighlight, bool -> MobHighlight.mobHighlight = bool)); highlight.add(new ConfigBool(Text.literal("Don't highlight invisible mobs"), () -> MobHighlight.dontShowInvisibleMobs, bool -> MobHighlight.dontShowInvisibleMobs = bool)); @@ -229,13 +253,12 @@ public class Config { sheep.add(new ConfigColor(Text.literal("Sheep filled color"), () -> MobHighlight.sheepFilledColor, color -> MobHighlight.sheepFilledColor = color, "sheep-filled", true)); sheep.add(new ConfigColor(Text.literal("Sheep outline color"), () -> MobHighlight.sheepOutlineColor, color -> MobHighlight.sheepOutlineColor = color, "sheep-outline", true)); highlight.add(sheep); + return highlight; + } - screen.addCategory(highlight); - + private static ConfigCategory extra() { ConfigCategory extra = new ConfigCategory("Extra options"); - extra.add(new ConfigString(Text.literal("Message prefix"), () -> ExtraOptions.textPrefix, str -> ExtraOptions.textPrefix = str)); - extra.add(new ConfigButton(Text.literal("Edit Notifications"), () -> MinecraftClient.getInstance().setScreen(new NotificationList()))); extra.add(new ConfigBool(Text.literal("Show pbs in chat"), () -> ExtraOptions.showPbs, bool -> ExtraOptions.showPbs = bool)); extra.add(new ConfigBool(Text.literal("Disable scroll wheel in hotbar"), () -> ExtraOptions.disableScrollHotbar, bool -> ExtraOptions.disableScrollHotbar = bool)); extra.add(new ConfigBool(Text.literal("Display kicked time"), () -> ExtraOptions.enableKickedTimer, bool -> ExtraOptions.enableKickedTimer = bool)); @@ -246,18 +269,6 @@ public class Config { sound.add(new ConfigBool(Text.literal("Disable bonzo sound"), () -> ExtraOptions.disableBonzoSound, bool -> ExtraOptions.disableBonzoSound = bool)); extra.add(sound); - ConfigSection visual = new ConfigSection(Text.literal("Visual changes")); - visual.add(new ConfigBool(Text.literal("Disable fire in f5"), () -> ExtraOptions.hideFireInf5, bool -> ExtraOptions.hideFireInf5 = bool)); - visual.add(new ConfigBool(Text.literal("Hide arrows stuck to entities"), () -> ExtraOptions.hideStuckArrows, bool -> ExtraOptions.hideStuckArrows = bool)); - visual.add(new ConfigBool(Text.literal("Hide dead entities"), () -> ExtraOptions.hideDeadEntities, bool -> ExtraOptions.hideDeadEntities = bool)); - visual.add(new ConfigBool(Text.literal("Item rarity background"), () -> ExtraOptions.itemRarityBackground, bool -> ExtraOptions.itemRarityBackground = bool)); - visual.add(new ConfigBool(Text.literal("Hide potion effects overlay"), () -> ExtraOptions.hideStatusOverLay, bool -> ExtraOptions.hideStatusOverLay = bool)); - visual.add(new ConfigBool(Text.literal("Disable glowing"), () -> ExtraOptions.disableGlowing, bool -> ExtraOptions.disableGlowing = bool)); - visual.add(new ConfigBool(Text.literal("Draw item starCount"), () -> ExtraOptions.drawStarCount, bool -> ExtraOptions.drawStarCount = bool)); - visual.add(new ConfigBool(Text.literal("Highlight protected items"), () -> ExtraOptions.highlightProtectedItem, bool -> ExtraOptions.highlightProtectedItem = bool)); - visual.add(new ConfigBool(Text.literal("Compact hoppity messages"), () -> ExtraOptions.compactHoppityMsgs, bool -> ExtraOptions.compactHoppityMsgs = bool)); - extra.add(visual); - ConfigSection rag = new ConfigSection(Text.literal("Ragnarock")); rag.add(new ConfigBool(Text.literal("Display rag axe duration"), () -> ExtraOptions.enableRagaxeDisplay, bool -> ExtraOptions.enableRagaxeDisplay = bool)); rag.add(new ConfigBool(Text.literal("Use 1.8.9 rag sound"), () -> ExtraOptions.useOldRagSound, bool -> ExtraOptions.useOldRagSound = bool)); @@ -299,10 +310,29 @@ public class Config { ss.add(new ConfigBool(Text.literal("Block unlucky button click"), () -> ExtraOptions.blockUnluckyButtonClick, bool -> ExtraOptions.blockUnluckyButtonClick = bool)); ss.add(new ConfigDouble(Text.literal("Lucky button rng (0.1)"), () -> ExtraOptions.luckyButtonRng, num -> ExtraOptions.luckyButtonRng = num, 0.01, 0, 1)); ss.add(new ConfigColor(Text.literal("Lucky button color"), () -> ExtraOptions.luckyButtonColor, color -> ExtraOptions.luckyButtonColor = color, "lucky-button-color", true)); + ss.add(new ConfigSound(Text.literal("Button sound"), ExtraOptions.ssSound)); + extra.add(ss); + return extra; + } - screen.addCategory(extra); + private static ConfigCategory visual() { + ConfigCategory visual = new ConfigCategory("Visual changes"); + visual.add(new ConfigBool(Text.literal("Disable fire in f5"), () -> Visual.hideFireInf5, bool -> Visual.hideFireInf5 = bool)); + visual.add(new ConfigBool(Text.literal("Hide all entity on fire"), () -> Visual.hideEntityFire, bool -> Visual.hideEntityFire = bool)); + visual.add(new ConfigBool(Text.literal("Hide arrows stuck to entities"), () -> Visual.hideStuckArrows, bool -> Visual.hideStuckArrows = bool)); + visual.add(new ConfigBool(Text.literal("Hide dead entities"), () -> Visual.hideDeadEntities, bool -> Visual.hideDeadEntities = bool)); + visual.add(new ConfigBool(Text.literal("Item rarity background"), () -> Visual.itemRarityBackground, bool -> Visual.itemRarityBackground = bool)); + visual.add(new ConfigBool(Text.literal("Hide potion effects overlay"), () -> Visual.hideStatusOverLay, bool -> Visual.hideStatusOverLay = bool)); + visual.add(new ConfigBool(Text.literal("Disable glowing"), () -> Visual.disableGlowing, bool -> Visual.disableGlowing = bool)); + visual.add(new ConfigBool(Text.literal("Draw item starCount"), () -> Visual.drawStarCount, bool -> Visual.drawStarCount = bool)); + visual.add(new ConfigBool(Text.literal("Highlight protected items"), () -> Visual.highlightProtectedItem, bool -> Visual.highlightProtectedItem = bool)); + visual.add(new ConfigBool(Text.literal("Compact hoppity messages"), () -> Visual.compactHoppityMsgs, bool -> Visual.compactHoppityMsgs = bool)); + visual.add(new ConfigBool(Text.literal("Hide cooldown"), () -> Visual.hideCooldown, bool -> Visual.hideCooldown = bool)); + return visual; + } + private static ConfigCategory buttons() { ConfigCategory inventory = new ConfigCategory("Inventory buttons"); inventory.add(new ConfigString(Text.literal("Button 1"), () -> Buttons.command1, str -> Buttons.command1 = str)); inventory.add(new ConfigString(Text.literal("Button 2"), () -> Buttons.command2, str -> Buttons.command2 = str)); @@ -311,10 +341,7 @@ public class Config { inventory.add(new ConfigString(Text.literal("Button 5"), () -> Buttons.command5, str -> Buttons.command5 = str)); inventory.add(new ConfigString(Text.literal("Button 6"), () -> Buttons.command6, str -> Buttons.command6 = str)); inventory.add(new ConfigString(Text.literal("Button 7"), () -> Buttons.command7, str -> Buttons.command7 = str)); - - screen.addCategory(inventory); - - return screen; + return inventory; } } @@ -6,27 +6,9 @@ import net.minecraft.sound.SoundEvents; import net.minecraft.util.math.BlockPos; public class ExtraOptions { - @ConfigValue - public static boolean hideFireInf5 = false; - - @ConfigValue - public static boolean hideStuckArrows = false; - @ConfigValue public static boolean disableAbilityCooldownSound = true; - @ConfigValue - public static boolean hideDeadEntities = false; - - @ConfigValue - public static boolean itemRarityBackground = false; - - @ConfigValue - public static boolean hideStatusOverLay = false; - - @ConfigValue - public static boolean disableGlowing = false; - @ConfigValue public static String textPrefix = ""; @@ -39,12 +21,6 @@ public class ExtraOptions { @ConfigValue public static boolean includePetSprite = true; - @ConfigValue - public static boolean drawStarCount = false; - - @ConfigValue - public static boolean highlightProtectedItem = false; - @ConfigValue public static boolean showPbs = true; @@ -78,9 +54,6 @@ public class ExtraOptions { @ConfigValue public static boolean blockUnluckyButtonClick = false; - @ConfigValue - public static boolean compactHoppityMsgs = false; - @ConfigValue public static BlockPos startButton = new BlockPos(2, 2, 2); @@ -116,4 +89,7 @@ public class ExtraOptions { @ConfigValue public static boolean useOldRagSound = false; + + @ConfigValue + public static SoundData ssSound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0, 1); } @@ -0,0 +1,40 @@ +package blade.addon.utils.config.values; + +import config.practical.manager.ConfigValue; + +public class Visual { + + @ConfigValue + public static boolean hideFireInf5 = false; + + @ConfigValue + public static boolean hideStuckArrows = false; + + @ConfigValue + public static boolean hideDeadEntities = false; + + @ConfigValue + public static boolean itemRarityBackground = false; + + @ConfigValue + public static boolean hideStatusOverLay = false; + + @ConfigValue + public static boolean disableG …… diff 过长已截断 …… |
Merge remote-tracking branch 'origin/new' into new查看变更README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) |
| hopefully fixed block incorrect relic place not working (needs actual testing) - hopefully fixed detecting other peoples placed relic time - fixed kickedTimer being triggered if someone sent the msg in chat (needs testing) - added class colors for melody and location msgs (needs testing)
- added chat notifications (fix § not being able to be inputed in configString)
- added 1.8.9 rag sound toggle
- added mute bonzo staffs ghast sound
- did some refactoring 查看变更gradle.properties | 2 +-
src/main/java/blade/addon/Bladeaddons.java | 6 ++-
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 5 +--
src/main/java/blade/addon/features/dungeon/LeapOrder.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 3 +-
src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 3 +-
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 114 ++++++++++++++++++++++++++++++++-----------------
src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 23 +++++++---
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/MelodyWarning.java | 20 +++++++--
src/main/java/blade/addon/features/dungeon/f7/terms/Pre4Notifier.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 3 +-
src/main/java/blade/addon/features/highlight/MobHighlight.java | 3 +-
src/main/java/blade/addon/features/item/ProtectItem.java | 4 +-
src/main/java/blade/addon/features/notifications/Notification.java | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/notifications/NotificationEditScreen.java | 55 ++++++++++++++++++++++++
src/main/java/blade/addon/features/notifications/NotificationEntry.java | 84 ++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/notifications/NotificationList.java | 89 ++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/notifications/Notifications.java | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/other/DianaNotifier.java | 2 +-
src/main/java/blade/addon/features/other/KickedTimer.java | 2 +-
src/main/java/blade/addon/features/other/RagDisplay.java | 10 ++++-
src/main/java/blade/addon/features/other/SelectedPet.java | 2 +-
src/main/java/blade/addon/mixin/ChatScreenMixin.java | 43 ++++++++++++++-----
src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 32 +++++++++++---
src/main/java/blade/addon/mixin/EntityRendererMixin.java | 4 +-
src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 2 -
src/main/java/blade/addon/mixin/InventoryScreenMixin.java | 7 ---
src/main/java/blade/addon/mixin/PlayerEntityMixin.java | 2 +-
src/main/java/blade/addon/utils/Commands.java | 8 ----
src/main/java/blade/addon/utils/Constants.java | 2 +
src/main/java/blade/addon/utils/Debug.java | 82 -----------------------------------
src/main/java/blade/addon/utils/JsonUtility.java | 1 +
src/main/java/blade/addon/utils/Location.java | 1 +
src/main/java/blade/addon/utils/Misc.java | 93 +++++-----------------------------------
src/main/java/blade/addon/utils/config/Config.java | 55 +++++++++++++++++-------
src/main/java/blade/addon/utils/config/FolderUtility.java | 3 +-
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 5 +++
src/main/java/blade/addon/utils/config/components/Components.java | 4 ++
src/main/java/blade/addon/utils/config/values/Dungeons.java | 18 ++++++++
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 6 +++
src/main/java/blade/addon/utils/data/EntityUtil.java | 46 ++++++++++++++++++++
src/main/java/blade/addon/utils/data/ItemUtil.java | 27 ++++++++++++
src/main/java/blade/addon/utils/data/PartyUtil.java | 2 +-
src/main/java/blade/addon/utils/data/TextUtil.java | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/utils/debug/Debug.java | 112 ++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/utils/detection/Detection.java | 17 --------
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 17 ++++++++
src/main/java/blade/addon/utils/dungeon/Phase.java | 3 +-
src/main/java/blade/addon/utils/dungeon/Section.java | 2 +-
src/main/java/blade/addon/utils/dungeon/Split.java | 4 ++
src/main/java/blade/addon/utils/events/CustomEvents.java | 2 +-
src/main/java/blade/addon/utils/interfaces/GameHud.java | 2 +-
src/main/java/blade/addon/utils/{detection => interfaces}/PlayerDataHolder.java | 2 +-
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 6 +++
src/main/resources/assets/blade-addons/sounds.json | 7 +++
src/main/resources/assets/blade-addons/sounds/wolf-howl.ogg | Bin 0 -> 16994 bytes
58 files changed, 1148 insertions(+), 311 deletions(-)@@ -13,7 +13,7 @@ loader_version=0.18.4 loom_version=1.14-SNAPSHOT # Mod Properties -mod_version=2.3.0 +mod_version=2.3.1 maven_group=blade.addon archives_base_name=blade-addons @@ -2,12 +2,12 @@ package blade.addon; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; -import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.ExplosiveShot; import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.ItemHighlight; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.LeapMessage; +import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.BossWaypoints; @@ -30,6 +30,7 @@ import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; import blade.addon.features.highlight.SheepHighlight; import blade.addon.features.item.DropAnimation; +import blade.addon.features.notifications.Notifications; import blade.addon.features.other.CompactHoppity; import blade.addon.features.other.DianaNotifier; import blade.addon.features.other.KickedTimer; @@ -37,7 +38,6 @@ import blade.addon.features.other.PracticeSS; import blade.addon.features.other.RagDisplay; import blade.addon.features.other.SelectedPet; import blade.addon.utils.Commands; -import blade.addon.utils.Debug; import blade.addon.utils.Keybinds; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; @@ -46,6 +46,7 @@ import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.components.Components; import blade.addon.utils.config.values.Buttons; import blade.addon.utils.data.PartyUtil; +import blade.addon.utils.debug.Debug; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; @@ -106,5 +107,6 @@ public class Bladeaddons implements ModInitializer { DropAnimation.init(); MimicHighlight.init(); SheepHighlight.init(); + Notifications.init(); } } \ No newline at end of file @@ -1,9 +1,8 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; -import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.detection.Detection; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import net.minecraft.client.MinecraftClient; @@ -61,7 +60,7 @@ public class HidePlayers { } public static boolean shouldHidePlayers(PlayerEntity player) { - if (!Location.inDungeon() || !Detection.isARealPlayer(player) || Misc.isClientPlayer(player)) return false; + if (!Location.inDungeon() || !EntityUtil.isARealPlayer(player) || EntityUtil.isClientPlayer(player)) return false; if (testHideAtLeap()) { return true; @@ -1,6 +1,6 @@ package blade.addon.features.dungeon; -import blade.addon.utils.Debug; +import blade.addon.utils.debug.Debug; import blade.addon.utils.Misc; import blade.addon.utils.dungeon.DungeonClass; import net.minecraft.client.MinecraftClient; @@ -5,6 +5,7 @@ import blade.addon.utils.Misc; import blade.addon.utils.Waypoint; import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; @@ -115,7 +116,7 @@ public class BossWaypoints { } private static ActionResult onBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) { - if (!isInValidArea() || !Misc.isClientPlayer(playerEntity)) return ActionResult.PASS; + if (!isInValidArea() || !EntityUtil.isClientPlayer(playerEntity)) return ActionResult.PASS; if (hand == Hand.OFF_HAND) return ActionResult.PASS; BlockPos pos = blockHitResult.getBlockPos(); @@ -4,6 +4,7 @@ import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -50,7 +51,7 @@ public class CrystalSpawn { matcher = RELIC_PICK_UP.matcher(text.getString()); if (matcher.find()) { String name = matcher.group(1); - if (Misc.isClientPlayer(name)) { + if (EntityUtil.isClientPlayer(name)) { pickupTime = System.currentTimeMillis(); pickedUp = true; } @@ -4,12 +4,16 @@ import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; +import blade.addon.utils.data.ItemUtil; +import blade.addon.utils.debug.Debug; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; @@ -19,9 +23,9 @@ import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.item.ItemStack; import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -34,7 +38,7 @@ import java.util.regex.Pattern; public class RelicTimer { - enum Relic { + public enum Relic { GREEN(new Box(49, 7, 44, 50, 8, 45), 0xff55ff55, "§cRed"), RED(new Box(51, 7, 42, 52, 8, 43), 0xffff5555, "§aGreen"), PURPLE(new Box(54, 7, 41, 55, 8, 42), 0xffff55ff, "§5Purple"), @@ -53,6 +57,8 @@ public class RelicTimer { } } + private static boolean ignoreChecks = false; + private static final int GREEN_COLOR = 0xff00ff00; private static final int RED_COLOR = 0xffff0000; @@ -82,26 +88,22 @@ public class RelicTimer { Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { - tick = Floor7.relicSpawnTicks; - pickedupRelic = null; - for (Relic relic : Relic.values()) { - relic.placedTime = 0; - } + reset(); } - return false; }); Events.ON_PHASE_CHANGE.register(() -> { if (Phase.inP5()) { phaseStartTime = System.currentTimeMillis(); + tick = Floor7.relicSpawnTicks; } return false; }); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !Phase.inP5() || !Floor7.enableRelicPlaceTime) return; - + if (!Location.inDungeon() || !Phase.inP5()) return; + Debug.sendDebugMessage(Text.literal("Debug: ").append(message)); String str = message.getString().replaceAll("§.", ""); Matcher matcher = PATTERN.matcher(str); if (matcher.find()) { @@ -112,48 +114,61 @@ public class RelicTimer { if (player == null) return; if (name.equals(player.getName().getString())) { pickedupRelic = Relic.valueOf(relicString.toUpperCase()); + Debug.sendDebugMessage(Text.literal("Picked up relic " + relicString)); } } }); - Events.ON_ENTITY_SPAWNED.register((entity, world) -> { - if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes) return false; + ClientTickEvents.END_WORLD_TICK.register(world -> { + if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes) return; - if (entity instanceof ArmorStandEntity armorStand) { - ItemStack helmet = armorStand.getEquippedStack(EquipmentSlot.HEAD); - Text text = helmet.getName(); - if (text == null) return false; - String name = text.getString(); - if (!name.contains("Relic")) return false; + Iterable<Entity> entities = world.getEntities(); + if (allRelicsPlaced()) return; - double ax = armorStand.getX(); - double az = armorStand.getZ(); + for (Entity entity : entities) { + if (entity instanceof ArmorStandEntity armorStand) { + if (!EntityUtil.isWearing(armorStand, EquipmentSlot.HEAD, "Relic")) return; - for (Relic relic : Relic.values()) { - if (Misc.getDistance(relic.box.maxX, ax, relic.box.maxZ, az) < 1) { - relic.placedTime = System.currentTimeMillis(); - break; - } - } + double ax = armorStand.getX(); + double az = armorStand.getZ(); - if (allRelicsPlaced()) { for (Relic relic : Relic.values()) { - long time = relic.placedTime - phaseStartTime; - Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + Constants.DECIMAL_FORMAT.format(time) + "s&a.")); + if (relic.placedTime != 0 && Misc.getDistance(relic.box.maxX, ax, relic.box.maxZ, az) < 1) { + relic.placedTime = System.currentTimeMillis(); + break; + } } } } - return false; + + if (allRelicsPlaced()) { + for (Relic relic : Relic.values()) { + long time = relic.placedTime - phaseStartTime; + Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + Constants.DECIMAL_FORMAT.format(time) + "s&a.")); + } + } }); + Events.ON_BLOCK_INTERACTION.register((result, itemStack) -> { - if (!Location.inDungeon() || !Phase.inP5() || pickedupRelic == null) return false; + if (!ignoreChecks) { + if ((!Location.inDungeon() || !Phase.inP5())) return false; + } + + if (pickedupRelic == null) return false; + BlockPos pos = result.getBlockPos(); - Text name = itemStack.getCustomName(); - if (name == null) return false; - if (!name.getString().contains("Relic")) return false; + if (!ItemUtil.itemHasName(itemStack, "Relic")) { + if (Floor7.blockIncorrectRelicPlace) { + Debug.sendDebugMessage(Text.literal("Item: " + itemStack.getName())); + Misc.addChatMessage(Text.literal("Blocked a weird click")); + return true; + } else { + return false; + } + } if (pos.getX() == pickedupRelic.box.minX && (pos.getY() == pickedupRelic.box.minY || pos.getY() == pickedupRelic.box.minY - 1) && pos.getZ() == pickedupRelic.box.minZ) { if (Floor7.enableRelicPlaceTime) { @@ -204,9 +219,12 @@ public class RelicTimer { } - public static void testRelicGUI() { - forceGUI = true; + private static void reset() { tick = Floor7.relicSpawnTicks; + pickedupRelic = null; + for (Relic relic : Relic.values()) { + relic.placedTime = 0; + } } private static boolean allRelicsPlaced() { @@ -216,6 +234,27 @@ public class RelicTimer { return true; } + public static void testRelicGUI() { + forceGUI = true; + tick = Floor7.relicSpawnTicks; + } + + public static boolean testSetRelic(String name) { + try { + pickedupRelic = RelicTimer.Relic.valueOf(name); + Misc.addChatMessage(Text.literal("Relic is now: " + name)); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + public static void testIgnoreChecks() { + ignoreChecks = !ignoreChecks; + Misc.addChatMessage(Text.literal("Ignore relic checks: ").append(Misc.getStatusText(ignoreChecks))); + + } + public static boolean display() { return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && !Floor7.replaceWithProgressBar; } @@ -242,8 +281,7 @@ public class RelicTimer { if (i < tick) { if (tick > 2) message.append("§a|"); else message.append("§c|"); - } - else message.append("§7|"); + } else message.append("§7|"); } message.append("§8]"); } else { @@ -1,15 +1,19 @@ package blade.addon.features.dungeon.f7.location; +import blade.addon.utils.Constants; import blade.addon.utils.Location; -import blade.addon.utils.Misc; import blade.addon.utils.Scheduler; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; +import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Style; import net.minecraft.text.Text; import java.util.regex.Matcher; @@ -29,10 +33,10 @@ public class LocationNotifier { if (!matcher.find()) return false; String action = matcher.group(1); - if (Floor7.dontNotifiyForYourself && Misc.isClientPlayer(username)) return false; - String screenNotification = (username + " is " + action + message.substring(action.length()) + "!").replaceAll("§.", ""); - if (PositionMessages.hasBeenSent(screenNotification)) return false; - startNotification(screenNotification); + if (Floor7.dontNotifiyForYourself && EntityUtil.isClientPlayer(username)) return false; + String location =message.substring(action.length()) .replaceAll("§.", ""); + if (PositionMessages.hasBeenSent(location)) return false; + startNotification(username, " is " + action + location + "!"); return false; }); @@ -40,8 +44,13 @@ public class LocationNotifier { ClientTickEvents.END_CLIENT_TICK.register(client -> ticks = Math.max(ticks - 1, 0)); } - public static void startNotification(String message) { - notification = Text.literal("§6"+message); + public static void startNotification(String username, String message) { + int color = Constants.GOLD; + if (Dungeons.useClassColors) { + color = DungeonClass.getColor(username); + } + + notification = Text.literal(username).withColor(color).append(Text.literal("§6" + message).setStyle(Style.EMPTY)); ticks = Floor7.notificationDuration; for (int i = 0; i < Floor7.notificationRepetitions; i++) { @@ -1,6 +1,6 @@ package blade.addon.features.dungeon.f7.location; -import blade.addon.utils.Debug; +import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; @@ -2,7 +2,7 @@ package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; -import blade.addon.utils.detection.Detection; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; @@ -65,7 +65,7 @@ public class LeapNotification { List<Entity> entities = world.getOtherEntities(player, box); int currentCount = 0; for (Entity entity : entities) { - if (Detection.isARealPlayer(entity)) { + if (EntityUtil.isARealPlayer(entity)) { currentCount++; } } @@ -1,8 +1,10 @@ package blade.addon.features.dungeon.f7.terms; +import blade.addon.utils.Constants; import blade.addon.utils.Location; -import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; @@ -10,6 +12,8 @@ import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.MutableText; +import net.minecraft.text.Style; import net.minecraft.text.Text; import java.util.concurrent.CopyOnWriteArrayList; @@ -39,7 +43,7 @@ public class MelodyWarning { melodyStarted = true; name = username; furthestProgress = progress; - ownUsername = Misc.isClientPlayer(username); + ownUsername = EntityUtil.isClientPlayer(username); if (!names.contains(username)) { names.add(username); } @@ -84,7 +88,17 @@ public class MelodyWarning { DungeonClass dungeonClass = DungeonClass.getClass(name); int num = Math.min(furthestProgress / 25, 3); - Text text = Text.literal("§5§l" + (dungeonClass != null ? dungeonClass.name() : name != null? name: "Someone") + " §r§dhas melody! " + num + "/4"); + + int color = Constants.DARK_PURPLE; + if (Dungeons.useClassColors) { + color = DungeonClass.getColor(name); + } + + + MutableText nameText = Text.literal(dungeonClass != null ? dungeonClass.name() : name != null? name: "Someone").setStyle(Style.EMPTY.withColor(color).withBold(true)); + MutableText infoText = Text.literal(" §r§dhas melody! " + num + "/4").setStyle(Style.EMPTY); + + Text text = nameText.append(infoText); RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, text, x, y, component.getWidth()); } @@ -1,8 +1,8 @@ package blade.addon.features.dungeon.f7.terms; -import blade.addon.utils.Misc; import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -25,7 +25,7 @@ public class Pre4Notifier { Events.ON_TERMINAL.register((name, action, objective, current, total) -> { if (!Floor7.notifyPre4Completion) return true; - if (objective.equals("device") && Misc.isClientPlayer(name) && atDev()) { + if (objective.equals("device") && EntityUtil.isClientPlayer(name) && atDev()) { completedTime = System.currentTimeMillis(); showNotification = true; Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); @@ -3,6 +3,7 @@ package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; @@ -24,7 +25,7 @@ public class TitleHider { Matcher matcher = TERMINALS_DONE_PATTERN.matcher(string); if (matcher.find()) { String name = matcher.group(1); - if (Misc.isClientPlayer(name)) { + if (EntityUtil.isClientPlayer(name)) { Misc.forceTitle(Text.empty(), packet.text()); } //end of section msg is handled by the Section class currently @@ -2,6 +2,7 @@ package blade.addon.features.highlight; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.data.EntityUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; @@ -315,7 +316,7 @@ public class MobHighlight { private static boolean isARealPlayer(Entity entity) { if (entity instanceof PlayerEntity player) { - if (Misc.isClientPlayer(player)) return true; + if (EntityUtil.isClientPlayer(player)) return true; ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); if (networkHandler == null) return false; @@ -1,7 +1,7 @@ package blade.addon.features.item; import blade.addon.utils.Constants; -import blade.addon.utils.Debug; +import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.config.FolderUtility; @@ -113,7 +113,7 @@ public class ProtectItem { Slot slot = slots.get(49); ItemStack stack = slot.getStack(); Text itemName = stack.getName(); - if (itemName != null && itemName.getString().contains("Sell Item") || Misc.containsLore(stack, "Click to buyback!")) { + if (itemName != null && itemName.getString().contains("Sell Item") || ItemUtil.containsLore(stack, "Click to buyback!")) { Misc.addChatMessage(Text.literal("Protected ").append(item.getName()).append(" From being sold")); return true; } @@ -0,0 +1,120 @@ +package blade.addon.features.notifications; + +import blade.addon.utils.Misc; +import blade.addon.utils.debug.Debug; +import config.practical.data.SoundData; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; + +import java.util.regex.PatternSyntaxException; + +public class Notification { + + private String matchString, notificationString, command; + private boolean useRegex, sendCommand; + private int ticks; + private final SoundData sound; + + public Notification() { + this.matchString = ""; + this.notificationString = ""; + this.command = ""; + this.useRegex = false; + this.sendCommand = false; + this.ticks = 20; + this.sound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); + } + + public Notification(String matchString, String notificationString, String command, boolean useRegex, boolean sendCommand, int ticks, SoundData sound) { + this.matchString = matchString; + this.notificationString = notificationString; + this.command = command; + this.useRegex = useRegex; + this.sendCommand = sendCommand; + this.ticks = ticks; + this.sound = sound; + } + + public String getMatchString() { + return matchString; + } + + public String getNotificationString() { + return notificationString; + } + + public int getTicks() { + return ticks; + } + + public String getCommand() { + return command; + } + + public boolean sendCommand() { + return sendCommand; + } + + public SoundData getSound() { + return sound; + } + + public boolean useRegex() { + return useRegex; + } + + + public void setMatchString(String matchString) { + this.matchString = matchString; + } + + public void setNotificationString(String notificationString) { + this.notificationString = notificationString; + } + + public void setCommand(String command) { + this.command = command; + } + + public void setTicks(int ticks) { + this.ticks = ticks; + } + + public void setSendCommand(boolean sendCommand) { + this.sendCommand = sendCommand; + } + + public void setUseRegex(boolean useRegex) { + this.useRegex = useRegex; + } + + public void testMessage(String message) { + if (useRegex) { + try { + if (!message.matches(matchString)) return; + } catch (PatternSyntaxException e) { + return; + } + } else if (!message.equals(matchString)) return; + + Debug.sendDebugMessage(Text.literal("Debug: " + notificationString)); + Notifications.setNotification(this); + Misc.sendSound(sound); + if (sendCommand) { + Misc.executeCommand(command); + } + } + + @Override + public String toString() { + return "Notification{" + + "matchString='" + matchString + '\'' + + ", notificationString='" + notificationString + '\'' + + ", command='" + command + '\'' + + ", useRegex=" + useRegex + + ", sendCommand=" + sendCommand + + ", ticks=" + ticks + + ", sound=" + sound + + '}'; + } +} @@ -0,0 +1,55 @@ +package blade.addon.features.notifications; + +import config.practical.ConfigScroll; +import config.practical.utilities.Constants; +import config.practical.widgets.ConfigBool; +import config.practical.widgets.ConfigString; +import config.practical.widgets.sliders.ConfigInt; +import config.practical.widgets.sound.ConfigSound; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.util.Window; +import net.minecraft.text.Text; + +public class NotificationEditScreen extends Screen { + + private final Screen parent; + private final ConfigScroll scroll; + private final Notification notification; + + + protected NotificationEditScreen(Notification notification) { + super(Text.empty()); + + MinecraftClient client = MinecraftClient.getInstance(); + parent = client.currentScreen; + Window window = client.getWindow(); + scroll = new ConfigScroll(0, 30, window.getScaledWidth(), window.getScaledHeight(), Constants.WIDGET_WIDTH); + this.notification = notification; + } + + private void initScrollWidgets() { + scroll.children().clear(); + scroll.add(new ConfigString(Text.literal("Trigger on message"), notification::getMatchString, notification::setMatchString, false)); + scroll.add(new ConfigString(Text.literal("Notification message"), notification::getNotificationString, notification::setNotificationString)); + scroll.add(new ConfigBool(Text.literal("Use regex"), notification::useRegex, notification::setUseRegex)); + scroll.add(new ConfigInt(Text.literal("Duration in ticks"), notification::getTicks, notification::setTicks, 1, 10, 40)); + scroll.add(new ConfigSound(Text.literal("Sound"), notification.getSound(), 2, 2, true)); + scroll.add(new ConfigBool(Text.literal("Send command"), notification::sendCommand, notification::setSendCommand)); + scroll.add(new ConfigString(Text.literal("Command"), notification::getCommand, notification::setCommand)); + scroll.update(); + } + + @Override + protected void init() { + super.init(); + this.addDrawableChild(scroll); + initScrollWidgets(); + } + + @Override + public void close() { + assert this.client != null; + this.client.setScreen(this.parent); + } +} @@ -0,0 +1,84 @@ +package blade.addon.features.notifications; + +import config.practical.utilities.Constants; +import config.practical.utilities.DrawHelper; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.Click; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.text.Text; + +class NotificationEntry extends ClickableWidget { + + private static final int PADDING = 5; + private static final int TEXT_SPACE = 100; + private static final int MAX_TEXT_WIDTH = 75; + private static final int BUTTON_WIDTH = 60; + + + private final NotificationList parent ; + private final Notification notification; + + public NotificationEntry(NotificationList parent, Notification notification) { + super(0, 0, Constants.WIDGET_WIDTH, 30, Text.empty()); + this.parent = parent; + this.notification = notification; + } + + @Override + protected void renderWidget(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + int x = getX(); + int y = getY(); + int width = getWidth(); + int height = getHeight(); + DrawHelper.drawBackground(context, x, y, width, height); + + MinecraftClient mc = MinecraftClient.getInstance(); + TextRenderer textRenderer = mc.textRenderer; + + drawText(context, textRenderer, notification.getMatchString(), x + PADDING, y); + drawText(context, textRenderer, notification.getNotificationString(), x + PADDING * 2 + TEXT_SPACE, y); + + int buttonWidth = 60; + String remove = "Remove"; + textRenderer.trimToWidth(remove, TEXT_SPACE - 2); + DrawHelper.drawBackground(context, x + width - buttonWidth - PADDING, y + 4, buttonWidth, height - 8); + context.drawText(textRenderer, remove, x + width - buttonWidth, y + (30 - Constants.TEXT_HEIGHT) / 2, 0xffffffff, true); + } + + private void drawText(DrawContext context, TextRenderer textRenderer, String string, int x, int y) { + + Text text; + if (string.isEmpty()) { + text = Text.literal("Empty"); + } else { + text = Text.literal(textRenderer.trimToWidth(string, MAX_TEXT_WIDTH - 2)); + } + + int textY = (30 - Constants.TEXT_HEIGHT) / 2 + y; + + context.enableScissor(x, y, x + MAX_TEXT_WIDTH - 1, y + height); + context.drawText(textRenderer, text, x + 1, textY, 0xffffffff, true); + context.disableScissor(); + } + + @Override + public void onClick(Click click, boolean doubled) { + double x = click.x(); + double y = click.y(); + + if (x >= getX() + width - BUTTON_WIDTH - PADDING && x <= getX() + width + BUTTON_WIDTH && y >= getY() + 4 && y <= getY() + height - 4) { + parent.removeNotification(notification); + return; + } + + MinecraftClient.getInstance().setScreen(new NotificationEditScreen(notification)); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } +} @@ -0,0 +1,89 @@ +package blade.addon.features.notifications; + +import config.practical.ConfigScroll; +import config.practical.utilities.Constants; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.util.Window; +import net.minecraft.text.Text; +import org.joml.Matrix3x2fStack; + +import java.util.List; + +public class NotificationList extends Screen { + + private static final int TITLE_COLOR = 0xffffffff; + private static final float TITLE_SCALAR = 1.5f; + private static final int TITLE_Y_OFFSET = 20; + + private static final int BUTTON_HEIGHT = 30; + + private final Screen parent; + private final ConfigScroll scroll; + private final ButtonWidget addNotification; + + public NotificationList() { + super(Text.literal("Notifications")); + + MinecraftClient client = MinecraftClient.getInstance(); + parent = client.currentScreen; + Window window = client.getWindow(); + + scroll = new ConfigScroll(0, BUTTON_HEIGHT + TITLE_Y_OFFSET + 16, window.getScaledWidth(), window.getScaledHeight() - BUTTON_HEIGHT, Constants.WIDGET_WIDTH); + addNotification = ButtonWidget.builder(Text.literal("Add notification"), this::addNotification).position((window.getScaledWidth() - Constants.WIDGET_WIDTH) / 2, TITLE_Y_OFFSET + 16).width(100).build(); + } + + @Override + protected void init() { + super.init(); + this.addDrawableChild(scroll); + this.addDrawableChild(addNotification); + updateList(); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + super.render(context, mouseX, mouseY, deltaTicks); + + float centerX = (MinecraftClient.getInstance().getWindow().getScaledWidth() - (this.textRenderer.getWidth(this.title) * TITLE_SCALAR)) / 2; + Matrix3x2fStack stack = context.getMatrices(); + stack.pushMatrix(); + stack.translate(centerX, TITLE_Y_OFFSET); + stack.scale(TITLE_SCALAR, TITLE_SCALAR); + context.drawText(this.textRenderer, this.title, 0, 0, TITLE_COLOR, true); + stack.popMatrix(); + } + + @Override + public void close() { + assert this.client != null; + Notifications.save(); + this.client.setScreen(this.parent); + } + + private void updateList() { + scroll.children().clear(); + + List<Notification> notifications = Notifications.getNotifications(); + for (Notification notification : notifications) { + NotificationEntry entry = new NotificationEntry(this, notification); + scroll.add(entry); + } + + scroll.update(); + scroll.setScrollY(0); + } + + private void addNotification(ButtonWidget buttonWidget) { + Notification notification = new Notification(); + Notifications.addNotification(notification); + updateList(); + } + + public void removeNotification(Notification notification) { + Notifications.removeNotification(notification); + updateList(); + } +} @@ -0,0 +1,160 @@ +package blade.addon.features.notifications; + +import blade.addon.utils.config.FolderUtility; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import config.practical.data.SoundData; +import config.practical.hud.HUDComponent; +import config.practical.manager.ConfigValue; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class Notifications { + + private static final String filePath = FolderUtility.CONFIG_PATH + FolderUtility.NOTIFICATIONS_NAME; + private static final String WAYPOINTS_NAME = "waypoints"; + + @ConfigValue + public static CopyOnWriteArrayList<Notification> notifications; + + private static double tick = 0; + private static String message; + + public static void init() { + notifications = new CopyOnWriteArrayList<>(); + load(); + System.out.println("Noti: " + notifications); + Events.ON_GAME_MESSAGE.register(text -> { + String message = text.getString(); + for (Notification notification : notifications) { + notification.testMessage(message); + } + + return false; + }); + + ClientTickEvents.END_CLIENT_TICK.register(event -> { + tick = Math.max(tick - 1, 0); + }); + } + + public static void addNotification(Notification notification) { + if (notifications == null) return; + notifications.add(notification); + } + + public static void removeNotification(Notification notification) { + if (notifications == null) return; + notifications.remove(notification); + } + + public static List<Notification> getNotifications() { + return notifications; + } + + public static boolean display() { + return tick > 0; + } + + public static void render(HUDComponent component, DrawContext context) { + Text text = Text.literal(message != null ? message : "Some notification"); + RenderUtils.drawCenteredText(context, component, text); + } + + public static void setNotification(Notification notification) { + if (notifications == null) return; + tick = notification.getTicks(); + message = notification.getNotificationString(); + } + + public static void save() { + + JsonObject obj = new JsonObject(); + Gson gson = new Gson(); + + obj.add(WAYPOINTS_NAME, gson.toJsonTree(notifications)); + + JsonElement tree = gson.toJsonTree(obj); + try (FileWriter writer = new FileWriter(filePath)) { + writer.write(tree.toString()); + } catch (IOException ignored) { + + } + } + + public static void load() { + String jsonContent; + try { + jsonContent = new String(Files.readAllBytes(Paths.get(filePath))); + } catch (IOException ignored) { + return; + } + Gson gson = new Gson(); + JsonObject object = gson.fromJson(jsonContent, JsonObject.class); + JsonElement element = object.get(WAYPOINTS_NAME); + + if (!element.isJsonArray()) return; + JsonArray array = element.getAsJsonArray(); + + for (JsonElement notificationElement : array) { + JsonObject notification = notificationElement.getAsJsonObject(); + + try { + + if (!notification.has("matchString")) continue; + String matchString = notification.get("matchString").getAsString(); + + if (!notification.has("notificationString")) continue; + String notificationString = notification.get("notificationString").getAsString(); + + if (!notification.has("command")) continue; + String command = notification.get("command").getAsString(); + + if (!notification.has("useRegex")) continue; + boolean useRegex = notification.get("useRegex").getAsBoolean(); + + if (!notification.has("sendCommand")) continue; + boolean sendCommand = notification.get("sendCommand").getAsBoolean(); + + if (!notification.has("ticks")) continue; + int ticks = notification.get("ticks").getAsInt(); + + if (!notification.has("sound")) continue; + SoundData sound = loadSoundData(notification.get("sound")); + if (sound == null) continue; + + notifications.add(new Notification(matchString, notificationString, command, useRegex, sendCommand, ticks, sound)); + } catch (NumberFormatException e) { + System.out.println("msg: " + e.getMessage()); + } + } + } + + public static SoundData loadSoundData(JsonElement jsonElement) { + JsonObject soundData = jsonElement.getAsJsonObject(); + + if (!soundData.has("sound")) return null; + String sound = soundData.get("sound").getAsString(); + + if (!soundData.has("volume")) return null; + float volume = soundData.get("volume").getAsFloat(); + + if (!soundData.has("pitch")) return null; + float pitch = soundData.get("pitch").getAsFloat(); + + return new SoundData(Identifier.of(sound), volume, pitch); + } +} @@ -1,6 +1,6 @@ package blade.addon.features.other; -import blade.addon.utils.Debug; +import blade.addon.utils.debug.Debug; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.Scheduler; @@ -19,7 +19,7 @@ public class KickedTimer { String string = text.getString(); if (string == null) return false; - if (string.contains("You were kicked while joining that server!")) { + if (string.equals("You were kicked while joining that server!")) { kickedTime = System.currentTimeMillis(); isKicked = true; } @@ -11,17 +11,20 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.entity.passive.WolfSoundVariants; import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; +import net.minecraft.util.Identifier; public class RagDisplay { private static final SoundEvent SOUND = SoundEvents.WOLF_SOUNDS.get(WolfSoundVariants.Type.CLASSIC).deathSound().value(); + private static final SoundEvent OLD_RAG_SOUND = SoundEvent.of(Identifier.of(Constants.NAMESPACE, "wolf-howl")); private static final int TOTAL_TICKS = 200; private static int tick = 0; public static void init() { Events.ON_SOUND.register((soundEvent, volume, pitch) -> { - if (!ExtraOptions.enableRagaxeDisplay && !ExtraOptions.useCustomRagSound) return false; + if (!ExtraOptions.enableRagaxeDisplay && !ExtraOptions.useCustomRagSound && !ExtraOptions.useOldRagSound) + return false; if (soundEvent != SOUND) return false; if (volume != 1 && pitch != 1.4920635223388672) return false; if (!ItemUtil.isHolding("Ragnarock")) return false; @@ -30,7 +33,10 @@ public class RagDisplay { tick = TOTAL_TICKS; } - if (ExtraOptions.useCustomRagSound) { + if (ExtraOptions.useOldRagSound) { + Scheduler.scheduleSound(OLD_RAG_SOUND, 1, 1.4920635223388672f); + return true; + } else if (ExtraOptions.useCustomRagSound) { Scheduler.scheduleSound(ExtraOptions.ragSound); return true; } @@ -1,7 +1,7 @@ package blade.addon.features.other; import blade.addon.utils.Constants; -import blade.addon.utils.Debug; +import blade.addon.utils.debug.Debug; import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; @@ -1,13 +1,12 @@ package blade.addon.mixin; -import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.TextUtil; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Click; import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.client.gui.screen.ChatScreen; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.OrderedText; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Mixin; @@ -43,9 +42,9 @@ public class ChatScreenMixin extends Screen { if (visibleMessages == null || index < 0 || index >= visibleMessages.size()) return; ChatHudLine.Visible msg = visibleMessages.get(index); - string = orderedTextToString(msg.content()); + string = TextUtil.orderedTextToString(msg.content()); } else { - string = Misc.copyChat(hudInvoker, x, y); + string = copyChat(hudInvoker, x, y); } if (string == null) return; @@ -62,14 +61,38 @@ public class ChatScreenMixin extends Screen { } @Unique - private static String orderedTextToString(OrderedText text) { - StringBuilder builder = new StringBuilder(); + private static String copyChat(ChatHudInvoker hudInvoker, double x, double y) { + List<ChatHudLine.Visible> messages = hudInvoker.getVisibleMessages(); + int endIndex = hudInvoker.getLineIndex(x, y); + + if (messages == null || endIndex < 0 || endIndex >= messages.size()) return null; - text.accept((index, style, codePoint) -> { - builder.appendCodePoint(codePoint); - return true; - }); + int startIndex = endIndex; + + //find start of msg + for (int i = endIndex; i >= 0; i--) { + ChatHudLine.Visible chatHudLine = messages.get(i); + if (chatHudLine.endOfEntry()) { + startIndex = i; + break; + } + } + if (!messages.get(endIndex).endOfEntry()) { + //find end of msg + for (int i = endIndex + 1; i < messages.size(); i++) { + ChatHudLine.Visible chatHudLine = messages.get(i); + if (chatHudLine.endOfEntry()) { + endIndex = i - 1; + break; + } + } + } + StringBuilder builder = new StringBuilder(); + for (int i = endIndex; i >= startIndex; i--) { + ChatHudLine.Visible chatHudLine = messages.get(i); + TextUtil.acceptOrderedText(builder, chatHudLine.content()); + } return builder.toString(); } } @@ -1,10 +1,11 @@ package blade.addon.mixin; import blade.addon.features.dungeon.f7.terms.TitleHider; -import blade.addon.utils.Debug; +import blade.addon.utils.data.EntityUtil; +import blade.addon.utils.debug.Debug; import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; -import blade.addon.utils.detection.PlayerDataHolder; +import blade.addon.utils.interfaces.PlayerDataHolder; import blade.addon.utils.events.Events; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; @@ -16,6 +17,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.PlaySoundFromEntityS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; @@ -68,12 +70,31 @@ public class ClientPlayNetworkHandlerMixin { float pitch = packet.getPitch(); SoundEvent event = packet.getSound().value(); - if (pitch == 0.0 && volume == 8.0 && event == SoundEvents.ENTITY_ENDERMAN_TELEPORT && ExtraOptions.disableAbilityCooldownSound) { + if (ExtraOptions.disableAbilityCooldownSound && pitch == 0.0 && volume == 8.0 && event == SoundEvents.ENTITY_ENDERMAN_TELEPORT) { ci.cancel(); } + if (ExtraOptions.disableBonzoSound && volume == 1.0 && event == SoundEvents.ENTITY_GHAST_WARN) { + ci.cancel(); + } + + if (Debug.sendSound) { + Misc.addChatMessage(Text.literal("Sound: " + event.id() + " Volume: " + volume + " Pitch: " + pitch)); + } + + if (Events.ON_SOUND.invoke(soundEvent -> soundEvent.onSound(event, volume, pitch))) { + ci.cancel(); + } + } + + @Inject(method = "onPlaySoundFromEntity", at = @At(value = "HEAD"), cancellable = true) + private void onLocationSound(PlaySoundFromEntityS2CPacket packet, CallbackInfo ci) { + float volume = packet.getVolume(); + float pitch = packet.getPitch(); + SoundEvent event = packet.getSound().value(); + if (Debug.sendSound) { - Misc.addChatMessage(Text.literal("Sound: " + event.id())); + Misc.addChatMessage(Text.literal("Sound: " + event.id() + " Volume: " + volume + " Pitch: " + pitch)); } if (Events.ON_SOUND.invoke(soundEvent -> soundEvent.onSound(event, volume, pitch))) { @@ -87,7 +108,6 @@ public class ClientPlayNetworkHandlerMixin { } - @Inject(method = "onEntitySpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;playSpawnSound(Lnet/minecraft/entity/Entity;)V")) public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo ci, @Local Entity entity) { if (entity instanceof PlayerEntity player) { @@ -102,7 +122,7 @@ public class ClientPlayNetworkHandlerMixin { private static boolean isARealPlayer(Entity entity) { if (entity instanceof PlayerEntity player) { - if (Misc.isClientPlayer(player)) return true; + if (EntityUtil.isClientPlayer(player)) return true; ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); if (networkHandler == null) return false; @@ -1,8 +1,8 @@ package blade.addon.mixin; -import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.data.EntityUtil; import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.state.EntityRenderState; @@ -32,7 +32,7 @@ public class EntityRendererMixin<T extends Entity, S extends EntityRenderState> public void hideFire(T entity, S state, float tickProgress, CallbackInfo ci) { if (entity instanceof PlayerEntity player && ExtraOptions.hideFireInf5) { - if (Misc.isClientPlayer(player)) { + if (EntityUtil.isClientPlayer(player)) { state.onFire = false; } } @@ -2,7 +2,6 @@ package blade.addon.mixin; import blade.addon.features.item.DropAnimation; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.util.math.MatrixStack; @@ -13,7 +12,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(HeldItemRenderer.cl …… diff 过长已截断 …… |
Update README.md查看变更README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) @@ -3,5 +3,8 @@ A dungeons mod made to port dungeons features to the newer Minecraft versions. Huge thanks to Ohful for letting me port his amazing mods like Valley addons. +# Current Version +1.21.10 + # Dependencies -- Hypixel Mod API https://modrinth.com/mod/hypixel-mod-api \ No newline at end of file +- Hypixel Mod API https://modrinth.com/mod/hypixel-mod-api |
- added copy chat msg - did some refactoring - hopefully fixed title hider in terms - changed how player missing notifier works查看变更src/main/java/blade/addon/Bladeaddons.java | 3 +++ src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 3 ++- src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 10 +++++++++- src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 10 +--------- src/main/java/blade/addon/features/other/SelectedPet.java | 13 +++++++++---- src/main/java/blade/addon/mixin/ChatHudInvoker.java | 25 +++++++++++++++++++++++++ src/main/java/blade/addon/mixin/ChatScreenMixin.java | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/EntityRenderManagerMixin.java | 5 +++-- src/main/java/blade/addon/utils/Location.java | 1 - src/main/java/blade/addon/utils/Misc.java | 45 ++++++++++++++++++++++++++++++++++++++++++++- src/main/java/blade/addon/utils/config/Config.java | 14 ++++++++++++-- src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 --- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 18 ++++++++++++++++++ src/main/java/blade/addon/utils/data/PartyUtil.java | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/dungeon/Phase.java | 11 +++++++++-- src/main/java/blade/addon/utils/dungeon/Section.java | 5 +++++ src/main/resources/blade-addons.mixins.json | 2 ++ 17 files changed, 270 insertions(+), 26 deletions(-) @@ -45,6 +45,7 @@ import blade.addon.utils.config.Config; import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.components.Components; import blade.addon.utils.config.values.Buttons; +import blade.addon.utils.data.PartyUtil; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; @@ -66,6 +67,8 @@ public class Bladeaddons implements ModInitializer { Phase.init(); Section.init(); DungeonClass.init(); + PartyUtil.init(); + StormTickTimer.init(); GoldorTickTimer.init(); TermStartTimer.init(); @@ -5,6 +5,7 @@ import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; @@ -82,6 +83,6 @@ public class KeyNotifier { int y = component.getScaledY(); Text text = isBloodKey ? BLOOD_KEY : WITHER_KEY; - context.drawText(MinecraftClient.getInstance().textRenderer, text, x, y, 0xffffffff, true); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, text, x, y, component.getWidth(), 0xffffffff); } } @@ -3,6 +3,7 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.data.PartyUtil; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -33,12 +34,15 @@ public class RunStartValidator { private static boolean hasDupeClasses = false; private static boolean notEnoughPlayers = false; + private static boolean hasTicked = false; + public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return; Matcher matcher = STARTING_PATTERN.matcher(message.getString()); if (!matcher.find()) return; + hasTicked = true; if (validate()) { Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); @@ -47,6 +51,7 @@ public class RunStartValidator { Events.ON_LOCATION_CHANGE.register(location -> { if (Location.inDungeon()) { + PartyUtil.sendPacket(); reset(); } @@ -54,6 +59,8 @@ public class RunStartValidator { }); Events.ON_PLAYER_ENTRY.register(receivedEntry -> { + //will only check after the first game message in case of false positives + if (!hasTicked) return false; if (!Location.inDungeon() || Phase.runStarted() || (!Dungeons.detectDuplicateClass && !Dungeons.detectPlayerCount)) return false; validate(); return false; @@ -98,12 +105,13 @@ public class RunStartValidator { count += num; } - notEnoughPlayers = count < Dungeons.playersNeeded; + notEnoughPlayers = count < PartyUtil.getPlayerCount(); } private static void reset() { hasDupeClasses = false; notEnoughPlayers = false; + hasTicked = false; } private static HashMap<String, Integer> readScoreBoard(Scoreboard scoreboard) { @@ -26,16 +26,8 @@ public class TitleHider { String name = matcher.group(1); if (Misc.isClientPlayer(name)) { Misc.forceTitle(Text.empty(), packet.text()); - } else { - try { - int currentCompleted = Integer.parseInt(matcher.group(4)); - if (Section.shouldIncrement(currentCompleted)) { - Misc.forceTitle(Text.empty(), packet.text()); - - } - } catch (Exception ignored) { - } } + //end of section msg is handled by the Section class currently } else { Misc.forceTitle(Text.empty(), packet.text()); } @@ -2,6 +2,7 @@ package blade.addon.features.other; import blade.addon.utils.Constants; import blade.addon.utils.Debug; +import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; @@ -46,7 +47,7 @@ public class SelectedPet { String name = matcher.group(2).replace(" ✦", ""); Style style = getStyle(message, name); - summonPet(name, Text.literal(name).setStyle(style)); + summonPet(name, Text.literal(name).setStyle(style), false); return; } @@ -60,7 +61,7 @@ public class SelectedPet { textName = string.substring(index - COLOR_OFFSET, index) + textName; } - summonPet(name, Text.literal(textName)); + summonPet(name, Text.literal(textName), true); } }); @@ -79,7 +80,7 @@ public class SelectedPet { if (matcher.find()) { String petName = matcher.group(1).replace(" ✦", ""); Style style = getStyle(text, petName); - summonPet(petName, Text.literal(petName).setStyle(style)); + summonPet(petName, Text.literal(petName).setStyle(style), false); } return false; @@ -94,7 +95,7 @@ public class SelectedPet { } - private static void summonPet(String stringName, Text textName) { + private static void summonPet(String stringName, Text textName, boolean sendSound) { if (stringName.equals(currentPetString)) { return; } @@ -104,6 +105,10 @@ public class SelectedPet { Events.ON_PET.invoke(petEvent -> petEvent.onPet(currentPetString)); updateSprite(stringName); + + if (sendSound && ExtraOptions.sendOnPetSound) { + Scheduler.scheduleSound(ExtraOptions.petSound); + } } private static Style getStyle(Text text, String name) { @@ -0,0 +1,25 @@ +package blade.addon.mixin; + +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(ChatHud.class) +public interface ChatHudInvoker { + + @Invoker("toChatLineY") + double lineY(double y); + + @Invoker("toChatLineX") + double lineX(double X); + + @Invoker("getMessageLineIndex") + int getLineIndex(double chatLineX, double chatLineY); + + @Accessor("visibleMessages") + List<ChatHudLine.Visible> getVisibleMessages(); +} @@ -0,0 +1,75 @@ +package blade.addon.mixin; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Click; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.OrderedText; +import net.minecraft.text.Text; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(ChatScreen.class) +public class ChatScreenMixin extends Screen { + + protected ChatScreenMixin(Text title) { + super(title); + } + + @Inject(method = "mouseClicked", at = @At("HEAD")) + private static void mouseClicked(Click click, boolean doubled, CallbackInfoReturnable<Boolean> cir) { + if (!ExtraOptions.copyChat || click.button() != GLFW.GLFW_MOUSE_BUTTON_RIGHT) return; + + MinecraftClient mc = MinecraftClient.getInstance(); + ChatHudInvoker hudInvoker = (ChatHudInvoker) mc.inGameHud.getChatHud(); + if (hudInvoker == null) return; + + double x = hudInvoker.lineX(click.x()); + double y = hudInvoker.lineY(click.y()); + + String string; + if (ExtraOptions.copyLineOnly) { + int index = hudInvoker.getLineIndex(x, y); + List<ChatHudLine.Visible> visibleMessages = hudInvoker.getVisibleMessages(); + if (visibleMessages == null || index < 0 || index >= visibleMessages.size()) return; + + ChatHudLine.Visible msg = visibleMessages.get(index); + string = orderedTextToString(msg.content()); + } else { + string = Misc.copyChat(hudInvoker, x, y); + } + + if (string == null) return; + + if (ExtraOptions.removeColorCodes) { + string = string.replaceAll("§.", ""); + } + + if (ExtraOptions.replaceColorChars) { + string = string.replaceAll("§", "&"); + } + + mc.keyboard.setClipboard(string); + } + + @Unique + private static String orderedTextToString(OrderedText text) { + StringBuilder builder = new StringBuilder(); + + text.accept((index, style, codePoint) -> { + builder.appendCodePoint(codePoint); + return true; + }); + + return builder.toString(); + } +} @@ -29,8 +29,9 @@ public class EntityRenderManagerMixin { if (clientPlayer != null) { if (player.getId() == clientPlayer.getId()) return; } - cir.setReturnValue(!HidePlayers.shouldHidePlayers(player)); - + if (HidePlayers.shouldHidePlayers(player)) { + cir.setReturnValue(false); + } } if (!entity.isAlive() && ExtraOptions.hideDeadEntities) { @@ -40,7 +40,6 @@ public enum Location { instance.subscribeToEventPacket(ClientboundLocationPacket.class); - } public static boolean in(Location location) { @@ -1,9 +1,11 @@ package blade.addon.utils; +import blade.addon.mixin.ChatHudInvoker; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.interfaces.GameHud; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; @@ -103,11 +105,52 @@ public class Misc { return false; } - private static void forceMainThread(Runnable runnable) { + public static void forceMainThread(Runnable runnable) { if (INSTANCE.isOnThread()) { runnable.run(); } else { INSTANCE.executeSync(runnable); } } + + public static String copyChat(ChatHudInvoker hudInvoker, double x, double y) { + List<ChatHudLine.Visible> messages = hudInvoker.getVisibleMessages(); + int endIndex = hudInvoker.getLineIndex(x, y); + + if (messages == null || endIndex < 0 || endIndex >= messages.size()) return null; + + StringBuilder tempBuilder = new StringBuilder(); + + int startIndex = endIndex; + + //find start of msg + for (int i = endIndex; i >= 0; i--) { + ChatHudLine.Visible chatHudLine = messages.get(i); + if (chatHudLine.endOfEntry()) { + startIndex = i; + break; + } + } + + if (!messages.get(endIndex).endOfEntry()) { + //find end of msg + for (int i = endIndex + 1; i < messages.size(); i++) { + ChatHudLine.Visible chatHudLine = messages.get(i); + if (chatHudLine.endOfEntry()) { + endIndex = i - 1; + break; + } + } + } + StringBuilder builder = new StringBuilder(); + for (int i = endIndex; i >= startIndex; i--) { + ChatHudLine.Visible chatHudLine = messages.get(i); + + chatHudLine.content().accept((index, style, codePoint) -> { + builder.appendCodePoint(codePoint); + return true; + }); + } + return builder.toString(); + } } @@ -47,7 +47,6 @@ public class Config { start.add(new ConfigBool(Text.literal("Dupe class warning"), () -> Dungeons.detectDuplicateClass, bool -> Dungeons.detectDuplicateClass = bool)); start.add(new ConfigBool(Text.literal("Ignore dupe mage"), () -> Dungeons.ignoreDupeMage, bool -> Dungeons.ignoreDupeMage = bool)); start.add(new ConfigBool(Text.literal("Player count warning"), () -> Dungeons.detectPlayerCount, bool -> Dungeons.detectPlayerCount = bool)); - start.add(new ConfigInt(Text.literal("Players needed"), () -> Dungeons.playersNeeded, count -> Dungeons.playersNeeded = count, 1, 1, 5)); dungeons.add(start); ConfigSection invincibility = new ConfigSection(Text.literal("Invincibility Timer")); @@ -169,6 +168,8 @@ public class Config { splits.add(new ConfigBool(Text.literal("Include total time"), () -> Phase.includeTotalTime, bool -> Phase.includeTotalTime = bool)); splits.add(new ConfigBool(Text.literal("Send split in chat when over"), () -> Phase.sendSplitInChat, bool -> Phase.sendSplitInChat = bool)); splits.add(new ConfigOptions<>(Text.literal("Tick timer type"), Split.TimerType.values(), () -> Split.timerType, type -> Split.timerType = type)); + splits.add(new ConfigBool(Text.literal("Only show activated splits"), () -> Phase.onlyShowActivatedSplits, bool -> Phase.onlyShowActivatedSplits = bool)); + splits.add(new ConfigColor(Text.literal("Real time color (Inactive)"), () -> Split.realTimeColorInactive, color -> Split.realTimeColorInactive = color, "real-time-inactive", false)); splits.add(new ConfigColor(Text.literal("Real time color (Ongoing)"), () -> Split.realTimeColorOngoing, color -> Split.realTimeColorOngoing = color, "real-time-ongoing", false)); @@ -239,10 +240,19 @@ public class Config { extra.add(new ConfigBool(Text.literal("Compact hoppity messages"), () -> ExtraOptions.compactHoppityMsgs, bool -> ExtraOptions.compactHoppityMsgs = bool)); extra.add(new ConfigBool(Text.literal("Disable recipe book"), () -> ExtraOptions.disableRecipeBook, bool -> ExtraOptions.disableRecipeBook = bool)); + ConfigSection copyChat = new ConfigSection(Text.literal("Copy chat")); + copyChat.add(new ConfigBool(Text.literal("Copy with right click"), () -> ExtraOptions.copyChat, bool -> ExtraOptions.copyChat = bool)); + copyChat.add(new ConfigBool(Text.literal("remove color codes"), () -> ExtraOptions.removeColorCodes, bool -> ExtraOptions.removeColorCodes = bool)); + copyChat.add(new ConfigBool(Text.literal("replace format char with &"), () -> ExtraOptions.replaceColorChars, bool -> ExtraOptions.replaceColorChars = bool)); + copyChat.add(new ConfigBool(Text.literal("copy line only"), () -> ExtraOptions.copyLineOnly, bool -> ExtraOptions.copyLineOnly = bool)); + extra.add(copyChat); + ConfigSection pets = new ConfigSection(Text.literal("Pets")); - pets.add(new ConfigBool(Text.literal("Highlight selected pet"), () -> ExtraOptions.highlightSelectedPet, bool -> ExtraOptions.highlightSelectedPet = bool)); + pets.add(new ConfigBool(Text.literal("Highlight selected pet in menu"), () -> ExtraOptions.highlightSelectedPet, bool -> ExtraOptions.highlightSelectedPet = bool)); pets.add(new ConfigBool(Text.literal("Draw selected pet"), () -> ExtraOptions.drawPetHUD, bool -> ExtraOptions.drawPetHUD = bool)); pets.add(new ConfigBool(Text.literal("Draw the pets sprite"), () -> ExtraOptions.includePetSprite, bool -> ExtraOptions.includePetSprite = bool)); + pets.add(new ConfigBool(Text.literal("Send sound on petswap"), () -> ExtraOptions.sendOnPetSound, bool -> ExtraOptions.sendOnPetSound = bool)); + pets.add(new ConfigSound(Text.literal("Pet swap sound"), ExtraOptions.petSound)); extra.add(pets); ConfigSection diana = new ConfigSection(Text.literal("Diana notifications")); @@ -97,7 +97,4 @@ public class Dungeons { @ConfigValue public static boolean detectPlayerCount = false; - - @ConfigValue - public static int playersNeeded = 5; } @@ -92,4 +92,22 @@ public class ExtraOptions { @ConfigValue public static SoundData ragSound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); + + @ConfigValue + public static boolean sendOnPetSound = false; + + @ConfigValue + public static SoundData petSound = new SoundData(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); + + @ConfigValue + public static boolean copyChat = false; + + @ConfigValue + public static boolean removeColorCodes = false; + + @ConfigValue + public static boolean replaceColorChars = false; + + @ConfigValue + public static boolean copyLineOnly = false; } @@ -0,0 +1,53 @@ +package blade.addon.utils.data; + +import blade.addon.utils.Debug; +import net.hypixel.modapi.HypixelModAPI; +import net.hypixel.modapi.packet.impl.clientbound.ClientboundPartyInfoPacket; +import net.hypixel.modapi.packet.impl.serverbound.ServerboundPartyInfoPacket; + +import java.util.Map; +import java.util.UUID; + +public class PartyUtil { + + private static final int MIN_DELAY = 1000 * 60; + private static final HypixelModAPI INSTANCE = HypixelModAPI.getInstance(); + + private static long grabbedTime = 0; + private static Map<UUID, ClientboundPartyInfoPacket.PartyMember> memberMap; + private static boolean inParty; + + + public static void init() { + INSTANCE.createHandler(ClientboundPartyInfoPacket.class, packet -> { + Debug.LOGGER.info("Received party info packet"); + memberMap = packet.getMemberMap(); + inParty = packet.isInParty(); + }); + } + + public static void sendPacket() { + if (INSTANCE == null) { + throw new IllegalStateException("Instance not set"); + } + + if (System.currentTimeMillis() - grabbedTime < MIN_DELAY) return; + if (INSTANCE.sendPacket(new ServerboundPartyInfoPacket())) { + grabbedTime = System.currentTimeMillis(); + } else { + Debug.LOGGER.warn("Server bound party info packet lost"); + } + } + + public static int getPlayerCount() { + sendPacket(); + if (!inParty) return 0; + return memberMap.size(); + } + + public static boolean isInParty() { + sendPacket(); + return inParty; + } + +} @@ -47,6 +47,9 @@ public class Phase { @ConfigValue public static boolean sendSplitInChat = false; + @ConfigValue + public static boolean onlyShowActivatedSplits = false; + public static void init() { Events.ON_SERVER_TICK.register(() -> { if (currentSplits == null || runOver) return false; @@ -230,9 +233,13 @@ public class Phase { int splitCount = currentSplits.size(); if (!includeTotalTime) splitCount--; - for (int i = 0; i < splitCount; i++) { - currentSplits.get(i).drawSplit(drawContext, textRenderer, x, y + Constants.TEXT_HEIGHT * i, SPLIT_LENGTH); + int height = 0; + for (int i = 0; i < splitCount; i++) { + Split split = currentSplits.get(i); + if (Phase.onlyShowActivatedSplits && !(split.started() || split.ended())) continue; + split.drawSplit(drawContext, textRenderer, x, y + Constants.TEXT_HEIGHT * height, SPLIT_LENGTH); + height++; } } else { for (int i = 0; i < DUMMY_SIZE; i++) { @@ -14,6 +14,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import java.util.List; import java.util.regex.Matcher; @@ -74,6 +75,9 @@ public class Section { currentSection = 1; splits[0].start(); } else if (Phase.inGoldorTunnel()) { + if (TitleHider.shouldHideTitle()) { + Misc.forceTitle(Text.empty(), Text.literal("The Core entrance is opening!").formatted(Formatting.GREEN)); + } if (Debug.termInfo) { Misc.addChatMessage(Text.literal("Terminals ended")); } @@ -168,6 +172,7 @@ public class Section { if (shouldIncrement(currentCompleted)) { incrementSection(); + Misc.forceTitle(Text.empty(), message); } else { total = totalNeeded; completed = currentCompleted; @@ -19,6 +19,8 @@ "requireAnnotations": true }, "client": [ + "ChatHudInvoker", + "ChatScreenMixin", "ClientPlayerEntityMixin", "ClientPlayNetworkHandlerMixin", "EntityRendererMixin", |
| Merge pull request #2 from athenameow/new Updated SelectPet.java 查看变更src/main/java/blade/addon/features/other/SelectedPet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) |
Merge branch 'new' into new查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 35 +++++++++++++++++++++++++++ src/main/java/blade/addon/features/highlight/MimicHighlight.java | 1 + src/main/java/blade/addon/features/highlight/MobHighlight.java | 28 ++++++++++++---------- src/main/java/blade/addon/features/highlight/SheepHighlight.java | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 9 +++++++ src/main/java/blade/addon/mixin/EntityRenderManagerMixin.java | 9 +++++++ src/main/java/blade/addon/utils/Misc.java | 9 +++++++ src/main/java/blade/addon/utils/config/Config.java | 21 ++++++++++++---- src/main/java/blade/addon/utils/dungeon/Section.java | 34 +++++++++++++------------- src/main/java/blade/addon/utils/dungeon/Split.java | 4 ++-- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 1 - src/main/resources/blade-addons.mixins.json | 2 +- 13 files changed, 226 insertions(+), 39 deletions(-) |
- improved title hider查看变更src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 35 +++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 9 +++++++++ src/main/java/blade/addon/utils/dungeon/Section.java | 19 ++++++------------- 3 files changed, 50 insertions(+), 13 deletions(-) @@ -1,11 +1,46 @@ package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.dungeon.Section; +import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; +import net.minecraft.text.Text; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class TitleHider { + private static final Pattern TERMINALS_DONE_PATTERN = Pattern.compile("^(\\w+) (activated|completed) a (terminal|device|lever)! \\((\\d)/(\\d)\\)$"); + + public static void processSubtitle(SubtitleS2CPacket packet) { + if (!shouldHideTitle()) return; + if (Section.inSection(1) && Pre4Notifier.atDev()) return; + String string = packet.text().getString().replaceAll("§.", ""); + + + Matcher matcher = TERMINALS_DONE_PATTERN.matcher(string); + if (matcher.find()) { + String name = matcher.group(1); + if (Misc.isClientPlayer(name)) { + Misc.forceTitle(Text.empty(), packet.text()); + } else { + try { + int currentCompleted = Integer.parseInt(matcher.group(4)); + if (Section.shouldIncrement(currentCompleted)) { + Misc.forceTitle(Text.empty(), packet.text()); + + } + } catch (Exception ignored) { + } + } + } else { + Misc.forceTitle(Text.empty(), packet.text()); + } + } + public static boolean shouldHideTitle() { return Floor7.hideTerminalTitles && Phase.inP3() && Location.inDungeon(); } @@ -1,5 +1,6 @@ package blade.addon.mixin; +import blade.addon.features.dungeon.f7.terms.TitleHider; import blade.addon.utils.Debug; import blade.addon.utils.Misc; import blade.addon.utils.config.values.ExtraOptions; @@ -17,6 +18,7 @@ import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; +import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; import net.minecraft.network.packet.s2c.play.TeamS2CPacket; import net.minecraft.scoreboard.Team; import net.minecraft.sound.SoundEvent; @@ -79,6 +81,13 @@ public class ClientPlayNetworkHandlerMixin { } } + @Inject(method = "onSubtitle", at = @At("HEAD")) + public void onTitle(SubtitleS2CPacket packet, CallbackInfo ci) { + TitleHider.processSubtitle(packet); + } + + + @Inject(method = "onEntitySpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;playSpawnSound(Lnet/minecraft/entity/Entity;)V")) public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo ci, @Local Entity entity) { if (entity instanceof PlayerEntity player) { @@ -14,7 +14,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.List; import java.util.regex.Matcher; @@ -75,9 +74,6 @@ public class Section { currentSection = 1; splits[0].start(); } else if (Phase.inGoldorTunnel()) { - if (TitleHider.shouldHideTitle()) { - Misc.forceTitle(Text.empty(), Text.literal("The Core entrance is opening!").formatted(Formatting.GREEN)); - } if (Debug.termInfo) { Misc.addChatMessage(Text.literal("Terminals ended")); } @@ -170,18 +166,11 @@ public class Section { Events.ON_TERMINAL.invoke(terminalEvent -> terminalEvent.onComplete(name, action, objective, currentCompleted, totalNeeded)); - int recentlyCompleted = currentCompleted; - if ((recentlyCompleted == total && gateBlownUp) || (recentlyCompleted < completed)) { + if (shouldIncrement(currentCompleted)) { incrementSection(); - if (TitleHider.shouldHideTitle()) { - Misc.forceTitle(Text.empty(), message); - } } else { - if (Misc.isClientPlayer(name) && TitleHider.shouldHideTitle()) { - Misc.forceTitle(Text.empty(), message); - } total = totalNeeded; - completed = recentlyCompleted; + completed = currentCompleted; } if (Floor7.terminalTimeStamps) { @@ -255,6 +244,10 @@ public class Section { return false; } + public static boolean shouldIncrement(int recentlyCompleted) { + return (recentlyCompleted == total && gateBlownUp) || (recentlyCompleted < completed); + } + public static void render(HUDComponent component, DrawContext context) { int x = component.getScaledX(); int y = component.getScaledY(); |
- changed selectedpet regex to ones that work with some extra pet skins - sent by athenameow - added guided sheep hider and highlighter - fixed terminal time stamp - fixed some typos查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++ src/main/java/blade/addon/features/highlight/MimicHighlight.java | 1 + src/main/java/blade/addon/features/highlight/MobHighlight.java | 28 +++++++++++----------- src/main/java/blade/addon/features/highlight/SheepHighlight.java | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/other/SelectedPet.java | 6 ++--- src/main/java/blade/addon/mixin/EntityRenderManagerMixin.java | 9 ++++++++ src/main/java/blade/addon/utils/Misc.java | 9 ++++++++ src/main/java/blade/addon/utils/config/Config.java | 21 +++++++++++++---- src/main/java/blade/addon/utils/dungeon/Section.java | 15 ++++++++---- src/main/java/blade/addon/utils/dungeon/Split.java | 4 ++-- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 1 - src/main/resources/blade-addons.mixins.json | 2 +- 12 files changed, 179 insertions(+), 29 deletions(-) @@ -28,6 +28,7 @@ import blade.addon.features.dungeon.f7.terms.Pre4Notifier; import blade.addon.features.dungeon.f7.terms.TermStartTimer; import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; +import blade.addon.features.highlight.SheepHighlight; import blade.addon.features.item.DropAnimation; import blade.addon.features.other.CompactHoppity; import blade.addon.features.other.DianaNotifier; @@ -101,5 +102,6 @@ public class Bladeaddons implements ModInitializer { CompactHoppity.init(); DropAnimation.init(); MimicHighlight.init(); + SheepHighlight.init(); } } \ No newline at end of file @@ -83,6 +83,7 @@ public class MimicHighlight { MatrixStack.Entry entry = matrices.peek(); float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); + mimicList.forEach(blockEntity -> { Box renderBox = box.offset(blockEntity.getPos()); VertexRendering.drawBox(entry, outlineConsumer, renderBox, rgba[0], rgba[1], rgba[2], rgba[3]); @@ -36,7 +36,6 @@ import net.minecraft.item.Items; import net.minecraft.text.Text; import net.minecraft.text.TextColor; import net.minecraft.util.math.Box; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import java.util.ArrayList; @@ -93,6 +92,10 @@ public class MobHighlight { public static double witherExtraWidth = 0; @ConfigValue public static boolean highlightMimicChests = true; + @ConfigValue + public static boolean highlightSheep = false; + @ConfigValue + public static boolean hideSheep = false; @ConfigValue public static int outlineWidth = 4; @@ -113,6 +116,8 @@ public class MobHighlight { public static int witherFilledColor = 0x88222222; @ConfigValue public static int mimicFilledColor = 0xffffffff; + @ConfigValue + public static int sheepFilledColor = 0xffffffff; @ConfigValue public static int starOutlineColor = 0xff00ff00; @@ -130,6 +135,9 @@ public class MobHighlight { public static int witherOutlineColor = 0x88222222; @ConfigValue public static int mimicOutlineColor = 0xffffffff; + @ConfigValue + public static int sheepOutlineColor = 0xffffffff; + public static void init() { @@ -392,9 +400,9 @@ public class MobHighlight { return currentHighlight == HighlightType.BOTH || currentHighlight == HighlightType.OUTLINE; } - private static Box getBox(Entity entity, double x, double y, double z) { + private static Box getBox(Entity entity, Vec3d pos) { EntityDimensions dimension = entity.getDimensions(entity.getPose()); - Box box = dimension.getBoxAt(x, y, z); + Box box = dimension.getBoxAt(pos); if (entity instanceof WitherEntity) { box = box.expand(MobHighlight.witherExtraWidth, 0, MobHighlight.witherExtraWidth); @@ -434,11 +442,9 @@ public class MobHighlight { if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; - double x = MathHelper.lerp(tickProgress, entity.lastRenderX, entity.getX()); - double y = MathHelper.lerp(tickProgress, entity.lastRenderY, entity.getY()); - double z = MathHelper.lerp(tickProgress, entity.lastRenderZ, entity.getZ()); + Vec3d pos = Misc.getPos(entity, tickProgress); - Box box = getBox(entity, x, y, z); + Box box = getBox(entity, pos); int filledColor = MobHighlight.getFilledColor(entity); @@ -472,12 +478,8 @@ public class MobHighlight { if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; - double x = MathHelper.lerp(tickProgress, entity.lastRenderX, entity.getX()); - double y = MathHelper.lerp(tickProgress, entity.lastRenderY, entity.getY()); - double z = MathHelper.lerp(tickProgress, entity.lastRenderZ, entity.getZ()); - - Box box = getBox(entity, x, y, z); - + Vec3d pos = Misc.getPos(entity, tickProgress); + Box box = getBox(entity, pos); int outlineColor = MobHighlight.getOutlineColor(entity); float[] rgba = RenderUtils.toFloats(outlineColor); @@ -0,0 +1,110 @@ +package blade.addon.features.highlight; + +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderUtils; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.passive.SheepEntity; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class SheepHighlight { + + private static final ConcurrentLinkedQueue<SheepEntity> sheepList = new ConcurrentLinkedQueue<>(); + + public static void init() { + + Events.ON_ENTITY_TRACKED.register((entity, world) -> { + if (!Location.inDungeon()) return false; + if (entity instanceof SheepEntity sheep) { + sheepList.add(sheep); + } + return false; + }); + + Events.ON_LOCATION_CHANGE.register(location -> { + sheepList.clear(); + return false; + }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> sheepList.removeIf(SheepEntity::isRemoved)); + + WorldRenderEvents.AFTER_ENTITIES.register(SheepHighlight::renderFilled); + WorldRenderEvents.AFTER_ENTITIES.register(SheepHighlight::renderOutline); + } + + private static void renderFilled(WorldRenderContext context) { + if (!MobHighlight.highlightSheep) return; + if (!MobHighlight.renderFilled()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + float[] rgba = RenderUtils.toFloats(MobHighlight.sheepFilledColor); + sheepList.forEach(entity -> { + + Vec3d pos = Misc.getPos(entity, tickProgress); + + EntityDimensions dimension = entity.getDimensions(entity.getPose()); + Box box = dimension.getBoxAt(pos); + + VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + + private static void renderOutline(WorldRenderContext context) { + if (!MobHighlight.highlightSheep) return; + if (!MobHighlight.renderOutline()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); + + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + MatrixStack.Entry entry = matrices.peek(); + float[] rgba = RenderUtils.toFloats(MobHighlight.sheepOutlineColor); + + sheepList.forEach(entity -> { + + Vec3d pos = Misc.getPos(entity, tickProgress); + + EntityDimensions dimension = entity.getDimensions(entity.getPose()); + Box box = dimension.getBoxAt(pos); + + VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + +} @@ -22,9 +22,9 @@ public class SelectedPet { private static final int COLOR_OFFSET = 2; - private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (\\D+)"); - private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (\\D+)!$"); - private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl [0-9]+] (\\D+)! VIEW RULE$"); + private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (?:\\[[^]]+] )?(.+)"); + private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (?:\\[Lvl \\d+] )?(?:\\[[^]]+] )?(.+)!$"); + private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl \\d+] (?:\\[[^]]+] )?(.+)! VIEW RULE$"); private static final Text NO_PET = Text.literal("§cNo pet"); private static final String identifierPrefix = "pets/"; @@ -2,6 +2,8 @@ package blade.addon.mixin; import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.ItemHighlight; +import blade.addon.features.highlight.MobHighlight; +import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.MinecraftClient; @@ -10,6 +12,7 @@ import net.minecraft.client.render.Frustum; import net.minecraft.client.render.entity.EntityRenderManager; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; +import net.minecraft.entity.passive.SheepEntity; import net.minecraft.entity.player.PlayerEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -32,12 +35,18 @@ public class EntityRenderManagerMixin { if (!entity.isAlive() && ExtraOptions.hideDeadEntities) { cir.setReturnValue(false); + return; } if (entity instanceof ItemEntity item && Dungeons.highlightItems) { if (ItemHighlight.hideItem(item)) { cir.setReturnValue(false); + return; } } + + if (entity instanceof SheepEntity) { + if (Location.inDungeon() && MobHighlight.hideSheep) cir.setReturnValue(false); + } } } @@ -14,6 +14,8 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import java.util.List; @@ -40,6 +42,13 @@ public class Misc { return clientPlayer.getName().getString().equals(name); } + public static Vec3d getPos(Entity entity, double tickProgress) { + double x = MathHelper.lerp(tickProgress, entity.lastRenderX, entity.getX()); + double y = MathHelper.lerp(tickProgress, entity.lastRenderY, entity.getY()); + double z = MathHelper.lerp(tickProgress, entity.lastRenderZ, entity.getZ()); + return new Vec3d(x, y, z); + } + public static double getDistance(Entity e1, Entity e2) { return getDistance(e1.getX(), e1.getZ(), e2.getX(), e2.getZ()); } @@ -189,7 +189,6 @@ public class Config { highlight.add(new ConfigDouble(Text.literal("Extra Wither Width"), () -> MobHighlight.witherExtraWidth, num -> MobHighlight.witherExtraWidth = num, 0.1, 0, 1.5)); highlight.add(new ConfigInt(Text.literal("Outline Width"), () -> MobHighlight.outlineWidth, num -> MobHighlight.outlineWidth = num, 1, 1, 10)); highlight.add(new ConfigOptions<>(Text.literal("Highlight mode"), MobHighlight.HighlightType.values(), () -> MobHighlight.currentHighlight, type -> MobHighlight.currentHighlight = type)); - highlight.add(new ConfigBool(Text.literal("Highlight mimic chests"), () -> MobHighlight.highlightMimicChests, bool -> MobHighlight.highlightMimicChests = bool)); highlight.add(new ConfigColor(Text.literal("Star mob filled color"), () -> MobHighlight.starFilledColor, color -> MobHighlight.starFilledColor = color, "star-filled", true)); highlight.add(new ConfigColor(Text.literal("Star mob outline color"), () -> MobHighlight.starOutlineColor, color -> MobHighlight.starOutlineColor = color, "star-outline", true)); highlight.add(new ConfigColor(Text.literal("Tank mob filled color"), () -> MobHighlight.tankFilledColor, color -> MobHighlight.tankFilledColor = color, "tank-filled", true)); @@ -202,10 +201,22 @@ public class Config { highlight.add(new ConfigColor(Text.literal("Shadow Assassin outline color"), () -> MobHighlight.assassinOutlineColor, color -> MobHighlight.assassinOutlineColor = color, "assassin-outline", true)); highlight.add(new ConfigColor(Text.literal("Bat filled color"), () -> MobHighlight.batFilledColor, color -> MobHighlight.batFilledColor = color, "bat-filled", true)); highlight.add(new ConfigColor(Text.literal("Bat outline color"), () -> MobHighlight.batOutlineColor, color -> MobHighlight.batOutlineColor = color, "bat-outline", true)); - highlight.add(new ConfigColor(Text.literal("Wither color"), () -> MobHighlight.witherFilledColor, color -> MobHighlight.witherFilledColor = color, "wither-filled", true)); - highlight.add(new ConfigColor(Text.literal("Wither outline"), () -> MobHighlight.witherOutlineColor, color -> MobHighlight.witherOutlineColor = color, "wither-outline", true)); - highlight.add(new ConfigColor(Text.literal("Mimic color"), () -> MobHighlight.mimicFilledColor, color -> MobHighlight.mimicFilledColor = color, "mimic-filled", true)); - highlight.add(new ConfigColor(Text.literal("Mimic outline"), () -> MobHighlight.mimicOutlineColor, color -> MobHighlight.mimicOutlineColor = color, "mimic-outline", true)); + highlight.add(new ConfigColor(Text.literal("Wither filled color"), () -> MobHighlight.witherFilledColor, color -> MobHighlight.witherFilledColor = color, "wither-filled", true)); + highlight.add(new ConfigColor(Text.literal("Wither outline color"), () -> MobHighlight.witherOutlineColor, color -> MobHighlight.witherOutlineColor = color, "wither-outline", true)); + + ConfigSection mimic = new ConfigSection(Text.literal("Mimic")); + mimic.add(new ConfigBool(Text.literal("Highlight mimic chests"), () -> MobHighlight.highlightMimicChests, bool -> MobHighlight.highlightMimicChests = bool)); + mimic.add(new ConfigColor(Text.literal("Mimic filled color"), () -> MobHighlight.mimicFilledColor, color -> MobHighlight.mimicFilledColor = color, "mimic-filled", true)); + mimic.add(new ConfigColor(Text.literal("Mimic outline color"), () -> MobHighlight.mimicOutlineColor, color -> MobHighlight.mimicOutlineColor = color, "mimic-outline", true)); + highlight.add(mimic); + + ConfigSection sheep = new ConfigSection(Text.literal("Sheep")); + sheep.add(new ConfigBool(Text.literal("Highlight sheep in dungeon"), () -> MobHighlight.highlightSheep, bool -> MobHighlight.highlightSheep = bool)); + sheep.add(new ConfigBool(Text.literal("Hide sheep in dungeons"), () -> MobHighlight.hideSheep, bool -> MobHighlight.hideSheep = bool)); + sheep.add(new ConfigColor(Text.literal("Sheep filled color"), () -> MobHighlight.sheepFilledColor, color -> MobHighlight.sheepFilledColor = color, "sheep-filled", true)); + sheep.add(new ConfigColor(Text.literal("Sheep outline color"), () -> MobHighlight.sheepOutlineColor, color -> MobHighlight.sheepOutlineColor = color, "sheep-outline", true)); + highlight.add(sheep); + screen.addCategory(highlight); ConfigCategory extra = new ConfigCategory("Extra options"); @@ -16,6 +16,7 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -184,8 +185,13 @@ public class Section { } if (Floor7.terminalTimeStamps) { - Misc.addChatMessage(Text.literal(name + " §a" + action + " " + objective + "! (§c" + currentCompleted + "§a/ " + totalNeeded + ") §8(§7" + getSectionTime() + "s §8| §7" + Phase.getPhaseTime(TERM_PHASE_INDEX) + "s§8)")); - return true; + //have to do it like this because for some reason they have the color in the + //Style object and not in the string literal + List<Text> texts = message.getSiblings(); + if (!texts.isEmpty()) { + Misc.addChatMessage(Text.literal(name).setStyle(texts.getFirst().getStyle()).append(Text.literal(" §a" + action + " " + objective + "! (§c" + currentCompleted + "§a/" + totalNeeded + ") §8(§7" + getSectionTime() + "s §8| §7" + Phase.getPhaseTime(TERM_PHASE_INDEX) + "s§8)"))); + return true; + } } @@ -231,8 +237,9 @@ public class Section { } public static double getSectionTime() { - if (currentSection < 0 || currentSection >= splits.length) return -1; - return splits[currentSection].getRealTime(); + int index = currentSection - 1; + if (index < 0 || index >= splits.length) return -1; + return splits[index].getRealTime(); } public static boolean display() { @@ -159,9 +159,9 @@ public class Split { if (timerType == TimerType.DIFFRENCE) { double diff = realTime - tickTime; if (diff > 0) { - serverTime = "+" + Constants.DECIMAL_FORMAT.format(diff) + "s "; + serverTime = "+" + Constants.DECIMAL_FORMAT.format(diff) + "s"; } else { - serverTime = Constants.DECIMAL_FORMAT.format(diff) + "s "; + serverTime = Constants.DECIMAL_FORMAT.format(diff) + "s"; } } else { //default to tick timer @@ -45,5 +45,4 @@ public class RenderUtils { RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); } - } @@ -3,9 +3,9 @@ "package": "blade.addon.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ + "ChunkMixin", "ClientConnectionMixin", "ClientPlayNetworkHandlerMixin", - "ChunkMixin", "EntityMixin", "ItemStackMixin", "PlayerEntityMixin", |
| Updated SelectPet.java Fixed regex for certain skins with levels, e.g Golden Dragon with Ancient skin. 查看变更src/main/java/blade/addon/features/other/SelectedPet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) @@ -22,9 +22,9 @@ public class SelectedPet { private static final int COLOR_OFFSET = 2; - private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (\\D+)"); - private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (\\D+)!$"); - private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl [0-9]+] (\\D+)! VIEW RULE$"); + private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (?:\\[[^\\]]+\\] )?(.+)"); + private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (?:\\[Lvl \\d+] )?(?:\\[[^\\]]+\\] )?(.+)!$"); + private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl \\d+] (?:\\[[^\\]]+\\] )?(.+)! VIEW RULE$"); private static final Text NO_PET = Text.literal("§cNo pet"); private static final String identifierPrefix = "pets/"; |
a bunch of refactoring mostly for events查看变更src/main/java/blade/addon/Bladeaddons.java | 20 +++++----- src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 14 +++---- src/main/java/blade/addon/features/dungeon/ChestCounter.java | 21 ++++++----- src/main/java/blade/addon/features/dungeon/DeathTickTimer.java | 61 ------------------------------ src/main/java/blade/addon/features/dungeon/DupeClassChecker.java | 85 ----------------------------------------- src/main/java/blade/addon/features/dungeon/HidePlayers.java | 28 +++++++------- src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 48 +++++++---------------- src/main/java/blade/addon/features/dungeon/LeapMessage.java | 24 ++---------- src/main/java/blade/addon/features/dungeon/RunStartValidator.java | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 20 ++++------ src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 6 +-- src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 44 +++++++++------------- src/main/java/blade/addon/features/dungeon/f7/DistanceToLedge.java | 7 +--- src/main/java/blade/addon/features/dungeon/f7/DragSpawnTimer.java | 32 ++++++---------- src/main/java/blade/addon/features/dungeon/f7/PillarExplode.java | 24 ++++++------ src/main/java/blade/addon/features/dungeon/f7/PredevTimer.java | 2 + src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 25 ++++++------ src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 32 ++++------------ src/main/java/blade/addon/features/dungeon/f7/invincibility/InvincibilityTimer.java | 74 +++++++++--------------------------- src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskHighlight.java | 15 +------- src/main/java/blade/addon/features/dungeon/f7/location/LocationNotifier.java | 21 ++++------- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 11 ++---- src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 2 + src/main/java/blade/addon/features/dungeon/f7/terms/GoldorTickTimer.java | 21 ++--------- src/main/java/blade/addon/features/dungeon/f7/terms/MelodyWarning.java | 32 +++++++--------- src/main/java/blade/addon/features/dungeon/f7/terms/Pre4Notifier.java | 6 ++- src/main/java/blade/addon/features/dungeon/f7/terms/TermStartTimer.java | 10 ++--- src/main/java/blade/addon/features/highlight/MimicHighlight.java | 6 ++- src/main/java/blade/addon/features/highlight/MobHighlight.java | 5 ++- src/main/java/blade/addon/features/item/ProtectItem.java | 22 ++--------- src/main/java/blade/addon/features/other/CompactHoppity.java | 2 +- src/main/java/blade/addon/features/other/DianaNotifier.java | 6 ++- src/main/java/blade/addon/features/other/KickedTimer.java | 7 ++-- src/main/java/blade/addon/features/other/PracticeSS.java | 5 ++- src/main/java/blade/addon/features/other/RagDisplay.java | 24 ++++-------- src/main/java/blade/addon/features/other/SelectedPet.java | 24 +++++------- src/main/java/blade/addon/mixin/ClientConnectionMixin.java | 19 ++++------ src/main/java/blade/addon/mixin/ClientPlayNetworkHandlerMixin.java | 29 +++----------- src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 2 + src/main/java/blade/addon/mixin/MinecraftClientMixin.java | 2 +- src/main/java/blade/addon/mixin/PlayerInventoryMixin.java | 4 +- src/main/java/blade/addon/utils/Constants.java | 8 +++- src/main/java/blade/addon/utils/Keybinds.java | 22 +++++++++++ src/main/java/blade/addon/utils/Location.java | 4 +- src/main/java/blade/addon/utils/Misc.java | 30 +++++++++------ src/main/java/blade/addon/utils/config/Config.java | 5 ++- src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 8 ++-- src/main/java/blade/addon/utils/config/components/Components.java | 20 ++++------ src/main/java/blade/addon/utils/config/values/Dungeons.java | 18 ++++++--- src/main/java/blade/addon/utils/config/values/Floor7.java | 3 ++ src/main/java/blade/addon/utils/data/ItemUtil.java | 36 ++++++++++++++++++ src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 4 +- src/main/java/blade/addon/utils/dungeon/Phase.java | 37 +++++++++--------- src/main/java/blade/addon/utils/dungeon/Section.java | 80 ++++++++++++++++++++++++--------------- src/main/java/blade/addon/utils/events/CancelableEvent.java | 6 --- src/main/java/blade/addon/utils/events/CancelableEventHandler.java | 22 ----------- src/main/java/blade/addon/utils/events/CustomEvents.java | 22 ++++++++--- src/main/java/blade/addon/utils/events/EventHandler.java | 23 +++++++----- src/main/java/blade/addon/utils/events/Events.java | 6 +-- src/main/java/blade/addon/utils/events/interfaces/BlockEntityEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/CancelableMessageEvent.java | 8 ---- src/main/java/blade/addon/utils/events/interfaces/EntityEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/GameMessageEvent.java | 7 +--- src/main/java/blade/addon/utils/events/interfaces/LeapEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/LocationChangeEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/ParticleEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/PartyMessageEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/PetEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/PhaseEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/PlayerListEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/RunEndEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/ScoreBoardEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/SectionEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/ServerTickEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/SlotChangeEvent.java | 2 +- src/main/java/blade/addon/utils/events/interfaces/TerminalEvent.java | 2 +- src/main/java/blade/addon/utils/rendering/RenderUtils.java | 16 +++++++- src/main/java/blade/addon/utils/times/PersonalBest.java | 4 +- src/main/resources/assets/blade-addons/lang/en_us.json | 3 ++ 79 files changed, 641 insertions(+), 763 deletions(-) @@ -2,8 +2,7 @@ package blade.addon; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; -import blade.addon.features.dungeon.DeathTickTimer; -import blade.addon.features.dungeon.DupeClassChecker; +import blade.addon.features.dungeon.RunStartValidator; import blade.addon.features.dungeon.ExplosiveShot; import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.ItemHighlight; @@ -15,17 +14,17 @@ import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.CrystalSpawn; import blade.addon.features.dungeon.f7.DistanceToLedge; import blade.addon.features.dungeon.f7.DragSpawnTimer; -import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; -import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; -import blade.addon.features.dungeon.f7.terms.LeapNotification; -import blade.addon.features.dungeon.f7.location.LocationNotifier; -import blade.addon.features.dungeon.f7.terms.MelodyWarning; import blade.addon.features.dungeon.f7.PillarExplode; -import blade.addon.features.dungeon.f7.location.PositionMessages; -import blade.addon.features.dungeon.f7.terms.Pre4Notifier; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; +import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; +import blade.addon.features.dungeon.f7.location.LocationNotifier; +import blade.addon.features.dungeon.f7.location.PositionMessages; +import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; +import blade.addon.features.dungeon.f7.terms.LeapNotification; +import blade.addon.features.dungeon.f7.terms.MelodyWarning; +import blade.addon.features.dungeon.f7.terms.Pre4Notifier; import blade.addon.features.dungeon.f7.terms.TermStartTimer; import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; @@ -69,13 +68,12 @@ public class Bladeaddons implements ModInitializer { StormTickTimer.init(); GoldorTickTimer.init(); TermStartTimer.init(); - DeathTickTimer.init(); PositionMessages.init(); InvincibilityTimer.init(); WarpCooldown.init(); LeapMessage.init(); ExplosiveShot.init(); - DupeClassChecker.init(); + RunStartValidator.init(); HidePlayers.init(); CrystalSpawn.init(); KeyNotifier.init(); @@ -13,8 +13,6 @@ import java.util.regex.Pattern; public class AutoRequeue { - private static final Pattern DT_PATTERN = Pattern.compile("!dt"); - private static final Pattern UNDT_PATTERN = Pattern.compile("!undt"); private static final Pattern LEFT_PATTERN = Pattern.compile("has left the party.$"); private static final HashMap<String, String> playerHashMap = new HashMap<>(); @@ -25,19 +23,19 @@ public class AutoRequeue { public static void init() { Events.ON_PARTY_MESSAGE.register((username, message) -> { if (playerHashMap.containsKey(username)) { - Matcher matcher = UNDT_PATTERN.matcher(message); - if (matcher.find()) { + if (message.contains("!undt")) { playerHashMap.remove(username); Misc.addChatMessage(Text.literal("§aDowntime removed")); } } else { - Matcher matcher = DT_PATTERN.matcher(message); - if (matcher.find()) { + if (message.contains("!dt")) { playerHashMap.put(username, message); Misc.addChatMessage(Text.literal("§aDowntime added")); } } + return false; }); + ClientReceiveMessageEvents.GAME.register((message, overlay) -> { if (!Location.inDungeon() && !Dungeons.enableAutoRequeue) return; String string = message.getString(); @@ -48,7 +46,7 @@ public class AutoRequeue { }); Events.ON_RUN_END.register(() -> { - if (!Dungeons.enableAutoRequeue || someoneLeft) return; + if (!Dungeons.enableAutoRequeue || someoneLeft) return false; if (playerHashMap.isEmpty()) { Misc.executeCommand("instancerequeue"); @@ -58,11 +56,13 @@ public class AutoRequeue { } + return false; }); Events.ON_LOCATION_CHANGE.register(newLocation -> { playerHashMap.clear(); someoneLeft = false; + return false; }); } } @@ -1,13 +1,15 @@ package blade.addon.features.dungeon; +import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; @@ -27,12 +29,13 @@ public class ChestCounter { if (Location.in(Location.DUNGEON_HUB)) { hasUpdatedData = false; } + return false; }); Events.ON_PLAYER_ENTRY.register(receivedEntry -> { - if (receivedEntry == null || !Location.in(Location.DUNGEON_HUB)) return; + if (receivedEntry == null || !Location.in(Location.DUNGEON_HUB)) return false; Text text = receivedEntry.displayName(); - if (text == null) return; + if (text == null) return false; String string = text.getString(); Matcher matcher = PATTERN.matcher(string); @@ -44,17 +47,17 @@ public class ChestCounter { } catch (NumberFormatException ignored) { } } + return false; }); Events.ON_RUN_END.register(() -> { countedChests++; if (Dungeons.sendChestWarning && chestDisplayCount + countedChests >= Dungeons.chestWarningCount) { - ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player != null) { - player.playSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); - } - MinecraftClient.getInstance().inGameHud.setTitle(Text.literal("Chest count reached").withColor(0xffff0000)); + Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); + Misc.setTitle(Text.literal("§cChest count reached")); } + + return false; }); } @@ -70,7 +73,7 @@ public class ChestCounter { if (hasUpdatedData) { context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, Dungeons.chestCountColor , true); } else { - context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, 0xffff0000, true); + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, Constants.RED_COLOR, true); } } @@ -1,61 +0,0 @@ -package blade.addon.features.dungeon; - -import blade.addon.utils.Constants; -import blade.addon.utils.Location; -import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.events.Events; -import blade.addon.utils.rendering.RenderUtils; -import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.text.Text; -import net.minecraft.util.math.Vec3d; - -public class DeathTickTimer { - - private static final int TOTAL_DEATH_TICKS = 40; - private static Vec3d firstPosition; - - private static int tick = TOTAL_DEATH_TICKS; - - public static void init() { - Events.ON_SERVER_TICK.register(() -> { - if (Location.inDungeon()) { - tick--; - if (tick <= 0) tick = TOTAL_DEATH_TICKS; - } - }); - - Events.ON_LOCATION_CHANGE.register(newLocation -> { - if (Location.inDungeon()) { - tick = 0; - firstPosition = null; - } - }); - } - - public static void onTeleport(Vec3d position) { - if (Location.inDungeon()) { - if (firstPosition == null) { - firstPosition = position; - } - - else if (position.x == firstPosition.x && position.y == firstPosition.y && position.z == firstPosition.z) { - tick = TOTAL_DEATH_TICKS; - } - } - } - - public static boolean display() { - return Dungeons.enableDeathTickTimer && Location.inDungeon(); - } - - public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - double num = tick * Constants.TICK_DURATION; - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth()); - - } -} @@ -1,85 +0,0 @@ -package blade.addon.features.dungeon; - -import blade.addon.utils.Location; -import blade.addon.utils.config.values.Dungeons; -import blade.addon.utils.dungeon.Phase; -import blade.addon.utils.events.Events; -import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.Team; -import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - -import java.util.HashSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class DupeClassChecker { - - private static final Pattern STARTING_PATTERN = Pattern.compile("^Starting in \\d second(s)?"); - private static final Pattern CLASS_PATTERN = Pattern.compile("\\[[ABHMT]]"); - - private static final Text DISPLAY_TEXT = Text.literal("Duplicate Class Detected").formatted(Formatting.RED); - - private static boolean hasDuplicateClass = false; - - public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return; - - Matcher matcher = STARTING_PATTERN.matcher(message.getString()); - if (!matcher.find()) return; - - hasDuplicateClass = hasDuplicateClasses(); - }); - - Events.ON_LOCATION_CHANGE.register(location -> { - if (Location.inDungeon()) { - hasDuplicateClass = false; - } - }); - } - - private static boolean hasDuplicateClasses() { - - ClientWorld world = MinecraftClient.getInstance().world; - ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (world == null || player == null) return false; - - Scoreboard scoreboard = world.getScoreboard(); - HashSet<String> set = new HashSet<>(); - - for (Team team : scoreboard.getTeams()) { - String teamStr = team.getPrefix().getString() + team.getSuffix().getString(); - Matcher matcher = CLASS_PATTERN.matcher(teamStr); - if (matcher.find()) { - String dungeonClass = matcher.group(); - - if (set.contains(dungeonClass)) { - player.playSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); - return true; - } - - set.add(dungeonClass); - } - } - return false; - } - - public static boolean display() { - return Location.inDungeon() && hasDuplicateClass && !Phase.runStarted(); - } - - public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - context.drawText(MinecraftClient.getInstance().textRenderer, DISPLAY_TEXT, x, y, 0xffffffff, true); - } -} @@ -26,6 +26,7 @@ public class HidePlayers { Events.ON_LEAP.register(message -> { justLeapt = true; startTime = System.currentTimeMillis(); + return false; }); } @@ -48,11 +49,19 @@ public class HidePlayers { return SS_POSITION.distanceTo(player.getEntityPos()) <= DISTANCE; } - public static boolean shouldHidePlayers(PlayerEntity player) { - if (!Location.inDungeon()) return false; + public static boolean testHideInRange(PlayerEntity player) { + if (!Dungeons.hidePlayersInRange) return false; + ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; + if (clientPlayer == null) return false; - if (!Detection.isARealPlayer(player)) return false; - if (Misc.isClientPlayer(player)) return false; + double distance = player.getEntityPos().distanceTo(clientPlayer.getEntityPos()); + if (!Double.isFinite(distance) || !Double.isFinite(Dungeons.hidePlayerRange)) return false; + return distance <= Dungeons.hidePlayerRange; + + } + + public static boolean shouldHidePlayers(PlayerEntity player) { + if (!Location.inDungeon() || !Detection.isARealPlayer(player) || Misc.isClientPlayer(player)) return false; if (testHideAtLeap()) { return true; @@ -62,16 +71,7 @@ public class HidePlayers { return true; } - if (Dungeons.hidePlayersInRange) { - ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; - if (clientPlayer == null) return false; - - double distance = player.getEntityPos().distanceTo(clientPlayer.getEntityPos()); - if (!Double.isFinite(distance) || !Double.isFinite(Dungeons.hidePlayerRange)) return false; - return distance <= Dungeons.hidePlayerRange; - } - - return false; + return testHideInRange(player); } @@ -1,27 +1,24 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.sound.SoundEvents; -import net.minecraft.text.Style; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.regex.Matcher; import java.util.regex.Pattern; public class KeyNotifier { - private final static Text BLOOD_KEY = Text.literal("Blood Key Dropped").setStyle(Style.EMPTY.withBold(true).withColor(Formatting.RED)); - private final static Text WITHER_KEY = Text.literal("Wither Key Dropped").setStyle(Style.EMPTY.withBold(true).withColor(Formatting.GRAY)); + private final static Text BLOOD_KEY = Text.literal("§l§cBlood Key Dropped"); + private final static Text WITHER_KEY = Text.literal("§l§7Wither Key Dropped"); private final static Pattern KEY_ENTITY_PATTERN = Pattern.compile("(Wither|Blood) Key"); private final static Pattern AUTOMATIC_PICKUP_PATTERN = Pattern.compile("A (Wither|Blood) Key was picked up!"); @@ -29,27 +26,24 @@ public class KeyNotifier { private static boolean hasKey = false; private static boolean isBloodKey = false; - private static boolean sentSound = false; public static void init() { Events.ON_ENTITY_TRACKED.register((entity, world) -> { - if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return; - if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return; + if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return false; + if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return false; Text text = entity.getCustomName(); - if (text == null) return; + if (text == null) return false; Matcher matcher = KEY_ENTITY_PATTERN.matcher(text.getString()); if (matcher.find()) { - String str = matcher.group(1); - - if (str.contains("Blood")) { - isBloodKey = true; - } - + isBloodKey = matcher.group(1).matches("Blood"); hasKey = true; + Scheduler.scheduleSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); } + + return false; }); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { @@ -60,7 +54,6 @@ public class KeyNotifier { if (matcher.find()) { hasKey = false; isBloodKey = false; - sentSound = false; return; } @@ -68,7 +61,6 @@ public class KeyNotifier { if (matcher.find()) { hasKey = false; isBloodKey = false; - sentSound = false; } }); @@ -76,19 +68,9 @@ public class KeyNotifier { if (Location.inDungeon()) { isBloodKey = false; hasKey = false; - sentSound = false; } + return false; }); - - ClientTickEvents.END_CLIENT_TICK.register((client) -> { - if (hasKey && !sentSound) { - ClientPlayerEntity player = client.player; - if (player == null) return; - player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 2, 0.5f); - sentSound = true; - } - }); - } public static boolean display() { @@ -99,11 +81,7 @@ public class KeyNotifier { int x = component.getScaledX(); int y = component.getScaledY(); - if (isBloodKey) { - context.drawText(MinecraftClient.getInstance().textRenderer, BLOOD_KEY, x, y, 0xffffffff, true); - } else { - context.drawText(MinecraftClient.getInstance().textRenderer, WITHER_KEY, x, y, 0xffffffff, true); - } - + Text text = isBloodKey ? BLOOD_KEY : WITHER_KEY; + context.drawText(MinecraftClient.getInstance().textRenderer, text, x, y, 0xffffffff, true); } } @@ -1,40 +1,22 @@ package blade.addon.features.dungeon; -import blade.addon.utils.Location; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - public class LeapMessage { private static final int INDEX_REMOVAL = 9; - private static final Pattern SEARCH_PATTERN = Pattern.compile("^You have teleported to .*!$"); public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (Location.inDungeon()) { - String string = message.getString(); - - Matcher matcher = SEARCH_PATTERN.matcher(string); - if (!matcher.find()) return; - - if (Events.ON_LEAP.hasListeners()) { - Events.ON_LEAP.listeners.forEach(leapEvent -> leapEvent.onLeap(message)); - } - } - }); - Events.ON_LEAP.register(message -> { - if (!Dungeons.enableLeapMessages) return; + if (!Dungeons.enableLeapMessages) return false; ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); - if (networkHandler == null) return; + if (networkHandler == null) return false; networkHandler.sendChatCommand("pc " + message.getString().substring(INDEX_REMOVAL)); + return false; }); } @@ -0,0 +1,140 @@ +package blade.addon.features.dungeon; + +import blade.addon.utils.Location; +import blade.addon.utils.Scheduler; +import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.scoreboard.Scoreboard; +import net.minecraft.scoreboard.Team; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RunStartValidator { + + private static final Pattern STARTING_PATTERN = Pattern.compile("^Starting in \\d second(s)?"); + private static final Pattern CLASS_PATTERN = Pattern.compile("\\[([ABHMT])]"); + + private static final Text DUPE_CLASS_TEXT = Text.literal("§cDuplicate Class Detected"); + private static final Text PLAYER_COUNT_TEXT = Text.literal("§cNot enough players"); + + private static boolean hasDupeClasses = false; + private static boolean notEnoughPlayers = false; + + public static void init() { + ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return; + + Matcher matcher = STARTING_PATTERN.matcher(message.getString()); + if (!matcher.find()) return; + + if (validate()) { + Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); + } + }); + + Events.ON_LOCATION_CHANGE.register(location -> { + if (Location.inDungeon()) { + reset(); + } + + return false; + }); + + Events.ON_PLAYER_ENTRY.register(receivedEntry -> { + if (!Location.inDungeon() || Phase.runStarted() || (!Dungeons.detectDuplicateClass && !Dungeons.detectPlayerCount)) return false; + validate(); + return false; + }); + } + + private static boolean validate() { + ClientWorld world = MinecraftClient.getInstance().world; + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (world == null || player == null) return false; + + Scoreboard scoreboard = world.getScoreboard(); + HashMap<String, Integer> map = readScoreBoard(scoreboard); + + checkPlayerCount(map); + checkDuplicateClasses(map); + return hasDupeClasses || notEnoughPlayers; + } + + private static void checkDuplicateClasses(HashMap<String, Integer> map) { + for (Map.Entry<String, Integer> entry : map.entrySet()) { + String clazz = entry.getKey(); + Integer count = entry.getValue(); + if (clazz.equals("M") && Dungeons.ignoreDupeMage) continue; + + if (count > 1) { + hasDupeClasses = true; + return; + } + } + + hasDupeClasses = false; + } + + private static void checkPlayerCount(HashMap<String, Integer> map) { + if (!Dungeons.detectPlayerCount) { + notEnoughPlayers = false; + return; + } + int count = 0; + for (int num : map.values()) { + count += num; + } + + notEnoughPlayers = count < Dungeons.playersNeeded; + } + + private static void reset() { + hasDupeClasses = false; + notEnoughPlayers = false; + } + + private static HashMap<String, Integer> readScoreBoard(Scoreboard scoreboard) { + HashMap<String, Integer> map = new HashMap<>(); + + for (Team team : scoreboard.getTeams()) { + String teamStr = team.getPrefix().getString() + team.getSuffix().getString(); + Matcher matcher = CLASS_PATTERN.matcher(teamStr); + if (!matcher.find()) continue; + + String clazz = matcher.group(1); + Integer count = map.get(clazz); + if (count == null) count = 0; + map.put(clazz, count + 1); + } + return map; + } + + public static boolean display() { + return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers); + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + if (hasDupeClasses) { + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, DUPE_CLASS_TEXT, x, y, component.getWidth()); + } else if (notEnoughPlayers) { + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, PLAYER_COUNT_TEXT, x, y, component.getWidth()); + } else { + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal("§cSome warning text"), x, y, component.getWidth()); + } + } +} @@ -24,33 +24,29 @@ public class SecretSpawnTimer { public static void init() { Events.ON_TEAM.register(text -> { - if (!Location.inDungeon() || !Dungeons.enableSecretSpawnTimer) return; - + if (!Location.inDungeon() || !Dungeons.enableSecretSpawnTimer) return false; Matcher matcher = PATTERN.matcher(text); if (matcher.find()) { tick = TICKS_PER_SECOND; } + return false; }); - Events.ON_SERVER_TICK.register(() -> tick = Math.max(tick - 1, 0)); + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + return false; + }); } public static boolean display() { - return Location.inDungeon() && Dungeons.enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(); + return Location.inDungeon() && Dungeons.enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(); } public static void render(HUDComponent component, DrawContext context) { int x = component.getScaledX(); int y = component.getScaledY(); - int color; - if (tick > 10) { - color = Constants.GREEN_COLOR; - } else if (tick > 5) { - color = Constants.ORANGE_COLOR; - } else { - color = Constants.RED_COLOR; - } + int color = tick > 10 ? Constants.GREEN_COLOR : tick > 5 ? Constants.ORANGE_COLOR : Constants.RED_COLOR; RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(tick + ""), x, y, component.getWidth(), color); @@ -7,7 +7,6 @@ import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -48,9 +47,6 @@ public class WarpCooldown { int y = component.getScaledY(); double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); - - Text text = Text.literal("Warp Cooldown: ").formatted(Formatting.DARK_PURPLE).append(Text.literal(Constants.DECIMAL_FORMAT.format(timeRemaining)).formatted(Formatting.WHITE)); - - context.drawText(MinecraftClient.getInstance().textRenderer, text, x, y, 0xffffffff, true); + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("§5Warp Cooldown: §f" + Constants.DECIMAL_FORMAT.format(timeRemaining)), x, y, 0xffffffff, true); } } @@ -14,7 +14,6 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.decoration.EndCrystalEntity; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,18 +33,18 @@ public class CrystalSpawn { public static void init() { Events.ON_GAME_MESSAGE.register(text -> { - if (!Location.inDungeon() || !Phase.inP1() || !Floor7.enableCrystalSpawnTime) return; + if (!Location.inDungeon() || !Phase.inP1() || !Floor7.enableCrystalSpawnTime) return false; Matcher matcher = PATTERN_1.matcher(text.getString()); if (matcher.find()) { tick = TICK_SPAWN; - return; + return false; } matcher = PATTERN_2.matcher(text.getString()); if (matcher.find()) { tick = TICK_SPAWN; - return; + return false; } matcher = RELIC_PICK_UP.matcher(text.getString()); @@ -57,37 +56,35 @@ public class CrystalSpawn { } } - + return false; + }); + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + return false; }); - Events.ON_SERVER_TICK.register(() -> tick = Math.max(tick - 1, 0)); Events.ON_LOCATION_CHANGE.register(newLocation -> { - if (Location.inDungeon()) { - tick = 0; - pickedUp = false; - } + tick = 0; + pickedUp = false; + return false; }); Events.ON_ENTITY_SPAWNED.register((entity, world) -> { - if (!pickedUp || !Location.inDungeon() || !Floor7.enableCrystalSpawnTime || !Phase.inP1()) return; + if (!pickedUp || !Location.inDungeon() || !Floor7.enableCrystalSpawnTime || !Phase.inP1()) return false; + if (entity instanceof EndCrystalEntity crystal) { ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player == null) return; + if (player == null) return false; - double px = player.getX(); - double cx = crystal.getX(); - double pz = player.getZ(); - double cz = crystal.getZ(); + double distance = Misc.getDistance(player, crystal); - double distance = Misc.getDistance(px, pz, cx, cz); - - if (distance < 5 && crystal.getY() == 224.375) { + if (distance < 6 && crystal.getY() == 224.375) { PersonalBests.crystalTime.testNewTime(Text.literal("§aCrystal placed in "), pickupTime); pickedUp = false; } } - + return false; }); } @@ -96,11 +93,6 @@ public class CrystalSpawn { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - double num = tick * Constants.TICK_DURATION; - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)).formatted(Formatting.LIGHT_PURPLE), x, y, component.getWidth()); + RenderUtils.drawTimer(component, context, tick, Constants.LIGHT_PURPLE); } } @@ -1,6 +1,5 @@ package blade.addon.features.dungeon.f7; -import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; @@ -10,7 +9,6 @@ import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.text.Text; import net.minecraft.util.math.Box; public class DistanceToLedge { @@ -42,9 +40,6 @@ public class DistanceToLedge { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(getDistance())), x, y, component.getWidth()); + RenderUtils.drawTimer(component, context, getDistance(), 0xffffffff); } } @@ -1,13 +1,11 @@ package blade.addon.features.dungeon.f7; -import blade.addon.utils.Constants; import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.particle.ParticleTypes; import net.minecraft.sound.SoundEvents; @@ -59,14 +57,14 @@ public class DragSpawnTimer { public static void init() { Events.ON_PARTICLE.register((x, y, z, effect) -> { - if (effect.getType() != ParticleTypes.ENCHANT) return; + if (effect.getType() != ParticleTypes.ENCHANT) return false; Dragon detectedDragon = getDragon(x, y, z); - if (detectedDragon == Dragon.NONE) return; + if (detectedDragon == Dragon.NONE) return false; //the dupe check is to stop purple from just breaking it when it spawns if (currentDragon == Dragon.NONE) { - if ((prevDragon == detectedDragon && dupeTick > 0)) return; + if ((prevDragon == detectedDragon && dupeTick > 0)) return false; currentDragon = detectedDragon; prevDragon = currentDragon; dupeTick = DUPE_DELAY; @@ -80,6 +78,8 @@ public class DragSpawnTimer { dupeTick = DUPE_DELAY * 2; hasDoneSplit = true; } + + return false; }); Events.ON_SERVER_TICK.register(() -> { @@ -92,9 +92,13 @@ public class DragSpawnTimer { if (tick == 0 && currentDragon != Dragon.NONE) { currentDragon = Dragon.NONE; } + return false; }); - Events.ON_LOCATION_CHANGE.register(newLocation -> reset()); + Events.ON_LOCATION_CHANGE.register(newLocation -> { + reset(); + return false; + }); } private static void reset() { @@ -106,27 +110,19 @@ public class DragSpawnTimer { //checks are from valley addons private static Dragon getDragon(double x, double y, double z) { - // check if correct height if (y >= 14 && y <= 19) { - // check if red/green if (x >= 27 && x <= 32) { - // check if red if (z == 59) { return Dragon.RED; - // check if green } else if (z == 94) { return Dragon.GREEN; } - // check if blue/orange } else if (x >= 79 && x <= 85) { - // check if blue if (z == 94) { return Dragon.BLUE; - // check if orange } else if (z == 56) { return Dragon.ORANGE; } - // check if purple } else if (x == 56) { return Dragon.PURPLE; } @@ -156,12 +152,6 @@ public class DragSpawnTimer { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - double num = tick * Constants.TICK_DURATION; - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth(), currentDragon.color); - + RenderUtils.drawTimer(component, context, tick, currentDragon.color); } } @@ -21,19 +21,24 @@ public class PillarExplode { public static void init() { Events.ON_GAME_MESSAGE.register(text -> { - if (!Floor7.notifyStormCrush && !Floor7.timePillarExplosion) return; - if (!Location.inDungeon() || !Phase.inP2()) return; + if (!Floor7.notifyStormCrush && !Floor7.timePillarExplosion) return false; + if (!Location.inDungeon() || !Phase.inP2()) return false; String string = text.getString(); - if (string == null) return; + if (string == null) return false; if (string.equals("[BOSS] Storm: Oof") || string.equals("[BOSS] Storm: Ouch, that hurt!")) { tick = TOTAL_TICKS; Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); } + + return false; }); - Events.ON_SERVER_TICK.register(() -> tick = Math.max(tick - 1, 0)); + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + return false; + }); } public static boolean displayTimer() { @@ -41,15 +46,8 @@ public class PillarExplode { } public static void renderTimer(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - Formatting formatting = (tick < 6 ? Formatting.GREEN : Formatting.RED); - - double num = tick * Constants.TICK_DURATION; - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num).formatted(formatting)), x, y, component.getWidth()); - + int color = tick < 6 ? Constants.GREEN_COLOR : Constants.RED_COLOR; + RenderUtils.drawTimer(component, context, tick, color); } public static boolean display() { @@ -26,6 +26,7 @@ public class PredevTimer { } else if (Phase.inP3()) { shouldTrack = false; } + return false; }); Events.ON_LOCATION_CHANGE.register(newLocation -> shouldTrack = false); @@ -45,6 +46,7 @@ public class PredevTimer { at3rdDev = false; shouldTrack = false; } + return false; }); } @@ -69,13 +69,15 @@ public class RelicTimer { public static void init() { Events.ON_SERVER_TICK.register(() -> { if (!forceGUI) { - if (!Location.inDungeon() || !Phase.inP5()) return; + if (!Location.inDungeon() || !Phase.inP5()) return false; } tick = Math.max(tick - 1, -1); if (tick == -1) { forceGUI = false; } + + return false; }); Events.ON_LOCATION_CHANGE.register(newLocation -> { @@ -86,12 +88,15 @@ public class RelicTimer { relic.placedTime = 0; } } + + return false; }); Events.ON_PHASE_CHANGE.register(() -> { if (Phase.inP5()) { phaseStartTime = System.currentTimeMillis(); } + return false; }); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { @@ -112,15 +117,15 @@ public class RelicTimer { }); Events.ON_ENTITY_SPAWNED.register((entity, world) -> { - if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes) return; + if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes) return false; if (entity instanceof ArmorStandEntity armorStand) { ItemStack helmet = armorStand.getEquippedStack(EquipmentSlot.HEAD); Text text = helmet.getName(); - if (text == null) return; + if (text == null) return false; String name = text.getString(); - if (!name.contains("Relic")) return; + if (!name.contains("Relic")) return false; double ax = armorStand.getX(); double az = armorStand.getZ(); @@ -139,7 +144,7 @@ public class RelicTimer { } } } - + return false; }); Events.ON_BLOCK_INTERACTION.register((result, itemStack) -> { @@ -216,15 +221,8 @@ public class RelicTimer { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - int color = tick > 7 ? GREEN_COLOR : RED_COLOR; - - double num = tick * Constants.TICK_DURATION; - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); - + RenderUtils.drawTimer(component, context, tick, color); } public static boolean displayProgressBar() { @@ -237,7 +235,6 @@ public class RelicTimer { int y = component.getScaledY(); //from valleyAddons - StringBuilder message = new StringBuilder("§8["); if (Floor7.useValleyBar) { @@ -4,17 +4,14 @@ import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; -import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -40,6 +37,7 @@ public class StormTickTimer { if (tick == WARN_TICK && Floor7.notifyUsedSpiritMask && DungeonClass.isClass(DungeonClass.MAGE) && InvincibilityTimer.spiritMaskUsed()) { Misc.setTitle(Text.literal("Leap to arch")); } + return false; }); Events.ON_LOCATION_CHANGE.register(newLocation -> { @@ -48,26 +46,21 @@ public class StormTickTimer { deathTime = 0; deathStartDisplayTime = 0; } + return false; }); Events.ON_GAME_MESSAGE.register(text -> { - if (!Location.inDungeon() || !Phase.inP2() || !Floor7.enableStormDeathTime) return; + if (!Location.inDungeon() || !Phase.inP2() || !Floor7.enableStormDeathTime) return false; Matcher matcher = PATTERN.matcher(text.getString()); if (matcher.find()) { deathTime = (tick * Constants.TICK_DURATION); deathStartDisplayTime = System.currentTimeMillis(); - - //prob dosent need to schedule it but threads are scary - Scheduler.scheduleTask(() -> Misc.addChatMessage( - Text.literal("Storm died at: ").formatted(Formatting.GREEN) - .append(Text.literal(Constants.DECIMAL_FORMAT.format(deathTime) + "s").formatted(Formatting.YELLOW)) - .append(Text.literal(".").formatted(Formatting.GREEN)) - ), 1); - + Misc.addChatMessage(Text.literal("§aStorm died at: §e" + Constants.DECIMAL_FORMAT.format(deathTime) + "s§a.")); } + return false; }); } @@ -81,18 +74,11 @@ public class StormTickTimer { } public static void render(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - double num = tick * Constants.TICK_DURATION; - if (Floor7.tickDownStormTickTimer) { num = CRUSH_TICK * Constants.TICK_DURATION - num; - } - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth(), Floor7.stormTickTimerColor); - + RenderUtils.drawTimer(component, context, num, Floor7.stormTickTimerColor); } public static boolean displayDeathTime() { @@ -100,10 +86,6 @@ public class StormTickTimer { } public static void renderDeathTime(HUDComponent component, DrawContext context) { - int x = component.getScaledX(); - int y = component.getScaledY(); - - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(deathTime)).formatted(Formatting.DARK_PURPLE), x, y, component.getWidth()); - + RenderUtils.drawTimer(component, context, deathTime, Constants.DARK_PURPLE); } } @@ -14,7 +14,6 @@ import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import java.util.regex.Matcher; @@ -29,10 +28,6 @@ public class InvincibilityTimer { private static final Identifier SPIRIT_SPRITE = Identifier.of(Constants.NAMESPACE, "spirit-mask"); private static final Identifier PHOENIX_SPRITE = Identifier.of(Constants.NAMESPACE, "phoenix"); - private static final int GREEN_COLOR = 0x8800FF00; - private static final int YELLOW_COLOR = 0x88FFFF00; - private static final int RED_COLOR = 0x88FF0000; - private static final int SPRITE_SIZE = TEXT_HEIGHT; private static final Pattern BONZO_PATTERN = Pattern.compile("^Your (?:\\S+ )?Bonzo's Mask saved your life!$"); @@ -78,6 +73,7 @@ public class InvincibilityTimer { spiritMaskTicks = 0; phoenixTicks = 0; } + return false; }); Events.ON_PET.register(name -> phoenixOn = name.equals("Phoenix")); @@ -90,23 +86,23 @@ public class InvincibilityTimer { }); } - private static void tick() { + private static boolean tick() { bonzoMaskTicks = Math.max(0, bonzoMaskTicks - 1); spiritMaskTicks = Math.max(0, spiritMaskTicks - 1); phoenixTicks = Math.max(0, phoenixTicks - 1); + return false; } - private static void detectHelmet(int slot, ItemStack item) { - if (slot != HEAD_SLOT || !Location.inDungeon()) return; - Text text = item.getCustomName(); - if (text == null) return; - String string = text.getString(); + private static boolean detectHelmet(int slot, ItemStack item) { + if (slot != HEAD_SLOT || !Location.inDungeon()) return false; + String string = item.getName().getString(); Matcher matcher = BONZO_ON_HEAD_PATTERN.matcher(string); bonzoMaskOn = matcher.find(); matcher = SPIRIT_ON_HEAD_PATTERN.matcher(string); spiritMaskOn = matcher.find(); + return false; } private static void parseMessage(Text message) { @@ -134,37 +130,15 @@ public class InvincibilityTimer { } private static Text formatTimer(int ticks) { - return Text.literal("(").formatted(Formatting.DARK_GRAY) - .append(Text.literal(Constants.DECIMAL_FORMAT.format(ticks * Constants.TICK_DURATION)).formatted(Formatting.GRAY)) - .append(Text.literal(")").formatted(Formatting.DARK_GRAY)); - } - - - private static Text getBonzoText() { - if (bonzoMaskTicks > 0) { - return Text.literal("Bonzo's Mask ").formatted(Formatting.RED).append(formatTimer(bonzoMaskTicks)); - } else { - Formatting format = bonzoMaskOn ? Formatting.YELLOW : Formatting.GREEN; - return Text.literal("Bonzo's Mask ").formatted(format); - } - } - - private static Text getSpiritText() { - if (spiritMaskTicks > 0) { - return Text.literal("Spirit Mask ").formatted(Formatting.RED).append(formatTimer(spiritMaskTicks)); - - } else { - Formatting format = spiritMaskOn ? Formatting.YELLOW : Formatting.GREEN; - return Text.literal("Spirit Mask ").formatted(format); - } + return Text.literal("§8(§7" + Constants.DECIMAL_FORMAT.format(ticks * Constants.TICK_DURATION) + "§8)"); } - private static Text getPhoenixText() { - if (phoenixTicks > 0) { - return Text.literal("Phoenix ").formatted(Formatting.RED).append(formatTimer(phoenixTicks)); + private static Text getText(int ticks, boolean isOn, String string) { + if (ticks > 0) { + return Text.literal("§c" + string).append(formatTimer(ticks)); } else { - Formatting format = phoenixOn ? Formatting.YELLOW : Formatting.GREEN; - return Text.literal("Phoenix ").formatted(format); + String color = isOn ? "§e" : "§a"; + return Text.literal(color + string); } } @@ -177,22 +151,9 @@ public class InvincibilityTimer { } private static void drawSprite(DrawContext context, Identifier identifier, int x, int y, boolean isOn, int ticks, Text timerText) { - - int color; - - if (ticks > 0) { - color = RED_COLOR; - } else if (isOn) { - color = YELLOW_COLOR; - } else { - color = GREEN_COLOR; - } - - + int color = (ticks > 0? Constants.RED_COLOR: isOn? Constants.YELLOW_COLOR: Constants.GREEN_COLOR); context.fill(x, y, x + SPRITE_SIZE, y + SPRITE_SIZE, color); - context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, identifier, x, y, SPRITE_SIZE, SPRITE_SIZE, 0xffffffff); - if (ticks > 0) { context.drawText(MinecraftClient.getInstance().textRenderer, timerText, x + TEXT_HEIGHT * 2, y, 0xffffffff, true); } @@ -235,11 +196,10 @@ public class InvincibilityTimer { drawSprite(context, BONZO_SPRITE, x, y, bonzoMaskOn, bonzoMaskTicks, formatTimer(bonzoMaskTicks)); drawSprite(context, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, spiritMaskOn, spiritMaskTicks, formatTimer(spiritMaskTicks)); drawSprite(context, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); - } else { - context.drawText(MinecraftClient.getInstance().textRend …… diff 过长已截断 …… |
- hopefully fixed msgs some times crashing the game查看变更src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 10 +++------- src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 7 +------ src/main/java/blade/addon/utils/Misc.java | 9 ++++++++- src/main/java/blade/addon/utils/Scheduler.java | 1 - src/main/java/blade/addon/utils/dungeon/Phase.java | 5 ++--- 5 files changed, 14 insertions(+), 18 deletions(-) @@ -5,10 +5,7 @@ import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.hud.ChatHud; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.HashMap; import java.util.regex.Matcher; @@ -31,13 +28,13 @@ public class AutoRequeue { Matcher matcher = UNDT_PATTERN.matcher(message); if (matcher.find()) { playerHashMap.remove(username); - Misc.addChatMessage(Text.literal("Downtime removed").formatted(Formatting.GREEN)); + Misc.addChatMessage(Text.literal("§aDowntime removed")); } } else { Matcher matcher = DT_PATTERN.matcher(message); if (matcher.find()) { playerHashMap.put(username, message); - Misc.addChatMessage(Text.literal("Downtime added").formatted(Formatting.GREEN)); + Misc.addChatMessage(Text.literal("§aDowntime added")); } } }); @@ -57,8 +54,7 @@ public class AutoRequeue { Misc.executeCommand("instancerequeue"); } else { Misc.addChatMessage(Text.literal("Downtime reasons:")); - ChatHud chathud = MinecraftClient.getInstance().inGameHud.getChatHud(); - playerHashMap.forEach((name, string) -> chathud.addMessage(Text.literal(name + "> " + string))); + playerHashMap.forEach((name, string) -> Misc.addChatMessage((Text.literal(name + "> " + string)))); } @@ -6,7 +6,6 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.text.DecimalFormat; import java.util.regex.Matcher; @@ -38,11 +37,7 @@ public class ExplosiveShot { double damagePerEntity = amountNum / countNum; - Misc.addChatMessage( - Text.literal("Explosive shot did ").formatted(Formatting.GREEN) - .append(Text.literal(FORMAT.format(damagePerEntity)).formatted(Formatting.YELLOW)) - .append(Text.literal(" damage per enemy.").formatted(Formatting.GREEN)) - ); + Misc.addChatMessage(Text.literal("§aExplosive shot did §e" + FORMAT.format(damagePerEntity) +"§a damage per enemy.")); } catch (NumberFormatException ignored) { } @@ -3,6 +3,7 @@ package blade.addon.utils; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.interfaces.GameHud; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.ChatHud; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; @@ -46,7 +47,13 @@ public class Misc { public static void addChatMessage(Text text) { try { InGameHud gameHud = INSTANCE.inGameHud; - gameHud.getChatHud().addMessage(Text.literal(ExtraOptions.textPrefix).append(text)); + ChatHud hud = gameHud.getChatHud(); + if (INSTANCE.isOnThread()) { + hud.addMessage(Text.literal(ExtraOptions.textPrefix).append(text)); + } else { + INSTANCE.executeSync(() -> hud.addMessage(Text.literal(ExtraOptions.textPrefix).append(text))); + } + } catch (IndexOutOfBoundsException ignored) { Debug.LOGGER.error("Chat message failed to get added"); } @@ -7,7 +7,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.sound.SoundEvent; -import net.minecraft.sound.SoundEvents; import java.util.concurrent.CopyOnWriteArrayList; @@ -12,7 +12,6 @@ import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.text.Text; -import net.minecraft.util.Formatting; import java.util.ArrayList; import java.util.HashMap; @@ -147,14 +146,14 @@ public class Phase { runOver = true; currentPhase = currentSplits.size(); - Misc.addChatMessage(Text.literal("Splits: ").formatted(Formatting.GREEN)); + Misc.addChatMessage(Text.literal("§aSplits: ")); for (Split split : currentSplits) { split.end(); Misc.addChatMessage(split.createNameText().append(split.createTimeText())); } if (!currentSplits.isEmpty()) { double time = currentSplits.getLast().getTimeDiffrence(); - Text timeLost = Text.literal("Approximately ").formatted(Formatting.GREEN).append(net.minecraft.text.Text.literal(Constants.DECIMAL_FORMAT.format(time) + "s ").formatted(Formatting.YELLOW)).append(net.minecraft.text.Text.literal("lost to lag.").formatted(Formatting.GREEN)); + Text timeLost = Text.literal("§aApproximately §e" + Constants.DECIMAL_FORMAT.format(time) + "s §alost to lag."); Misc.addChatMessage(timeLost); } |
- ported to 1.21.10查看变更gradle.properties | 16 +++++------
gradle/wrapper/gradle-wrapper.properties | 2 +-
src/main/java/blade/addon/Bladeaddons.java | 10 ++++---
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 7 +++--
src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 29 ++++++++++----------
src/main/java/blade/addon/features/dungeon/LeapOrder.java | 9 ++++---
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 43 ++++++++++++++---------------
src/main/java/blade/addon/features/dungeon/f7/DistanceToLedge.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 23 +++++++---------
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 28 +++++++++----------
src/main/java/blade/addon/features/dungeon/f7/terms/LeapNotification.java | 2 +-
src/main/java/blade/addon/features/highlight/MimicHighlight.java | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/highlight/MobHighlight.java | 60 ++++++++++++++++++++---------------------
src/main/java/blade/addon/features/other/InventoryButton.java | 6 ++---
src/main/java/blade/addon/features/other/PracticeSS.java | 30 +++++++++------------
src/main/java/blade/addon/mixin/BlockEntityRenderMixin.java | 43 -----------------------------
src/main/java/blade/addon/mixin/ChunkMixin.java | 20 ++++++++++++++
src/main/java/blade/addon/mixin/{ServerTickMixin.java => ClientConnectionMixin.java} | 2 +-
src/main/java/blade/addon/mixin/{NetworkMixin.java => ClientPlayNetworkHandlerMixin.java} | 13 ++++++---
src/main/java/blade/addon/mixin/{RenderMixin.java => EntityRenderManagerMixin.java} | 6 ++---
src/main/java/blade/addon/mixin/EntityRendererMixin.java | 22 ++++++++++++---
src/main/java/blade/addon/mixin/FireMixin.java | 26 ------------------
src/main/java/blade/addon/mixin/InventoryScreenMixin.java | 13 +++------
src/main/java/blade/addon/mixin/{InventoryMixin.java => PlayerInventoryMixin.java} | 4 +--
src/main/java/blade/addon/mixin/PositionMixin.java | 21 ---------------
src/main/java/blade/addon/mixin/{ArrowMixin.java => StuckArrowsFeatureRendererMixin.java} | 2 +-
src/main/java/blade/addon/utils/Constants.java | 2 +-
src/main/java/blade/addon/utils/Keybinds.java | 11 ++++----
src/main/java/blade/addon/utils/config/Config.java | 2 +-
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 13 ++++++++-
src/main/java/blade/addon/utils/events/Events.java | 3 +++
src/main/java/blade/addon/utils/events/interfaces/BlockEntityEvent.java | 9 +++++++
src/main/resources/blade-addons.mixins.json | 16 +++++------
34 files changed, 323 insertions(+), 266 deletions(-)@@ -7,19 +7,19 @@ org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.8 -yarn_mappings=1.21.8+build.1 -loader_version=0.17.3 -loom_version=1.13-SNAPSHOT +minecraft_version=1.21.10 +yarn_mappings=1.21.10+build.3 +loader_version=0.18.4 +loom_version=1.14-SNAPSHOT # Mod Properties -mod_version=2.2.6 +mod_version=2.3.0 maven_group=blade.addon archives_base_name=blade-addons # Dependencies -fabric_version=0.136.0+1.21.8 +fabric_version=0.138.4+1.21.10 # I love dependencies sometimes breaking -practical_config=1.3.7 -modmenu_version = 15.0.0 +practical_config=74a456703958c0a6381956ccf9be4a5e8dd7d84f +modmenu_version = 16.0.0-rc.2 hypixel_api_version = 1.0.1 \ No newline at end of file @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME @@ -27,6 +27,7 @@ import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; import blade.addon.features.dungeon.f7.terms.TermStartTimer; +import blade.addon.features.highlight.MimicHighlight; import blade.addon.features.highlight.MobHighlight; import blade.addon.features.item.DropAnimation; import blade.addon.features.other.CompactHoppity; @@ -51,17 +52,17 @@ import blade.addon.utils.events.CustomEvents; import net.fabricmc.api.ModInitializer; public class Bladeaddons implements ModInitializer { - @Override - public void onInitialize() { + @Override + public void onInitialize() { FolderUtility.init(); Components.init(); Buttons.init(); Config.manager.load(); - Keybinds.init(); + Keybinds.init(); CustomEvents.init(); Commands.init(); Debug.init(); - Location.init(); + Location.init(); Phase.init(); Section.init(); DungeonClass.init(); @@ -101,5 +102,6 @@ public class Bladeaddons implements ModInitializer { PracticeSS.init(); CompactHoppity.init(); DropAnimation.init(); + MimicHighlight.init(); } } \ No newline at end of file @@ -45,7 +45,7 @@ public class HidePlayers { if (!Dungeons.hideAtSS || !Phase.inBoss()) return false; if (Dungeons.hideBeforeTermsOnly && Phase.inP3()) return false; - return SS_POSITION.distanceTo(player.getPos()) <= DISTANCE; + return SS_POSITION.distanceTo(player.getEntityPos()) <= DISTANCE; } public static boolean shouldHidePlayers(PlayerEntity player) { @@ -65,7 +65,10 @@ public class HidePlayers { if (Dungeons.hidePlayersInRange) { ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; if (clientPlayer == null) return false; - return player.getPos().distanceTo(clientPlayer.getPos()) <= Dungeons.hidePlayerRange; + + double distance = player.getEntityPos().distanceTo(clientPlayer.getEntityPos()); + if (!Double.isFinite(distance) || !Double.isFinite(Dungeons.hidePlayerRange)) return false; + return distance <= Dungeons.hidePlayerRange; } return false; @@ -8,10 +8,9 @@ import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; @@ -58,21 +57,21 @@ public class ItemHighlight { } }); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(worldRenderContext -> { + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(context -> { if (!Dungeons.highlightItems) return; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); - - VertexConsumerProvider consumers = worldRenderContext.consumers(); + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer buffer = consumers.getBuffer(RenderLayers.THROUGH_WALL_FILLED_LAYER); + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + trackedItems.forEach((itemEntity, integer) -> { - double tickProgress = worldRenderContext.tickCounter().getTickProgress(false); double x = MathHelper.lerp(tickProgress, itemEntity.lastRenderX, itemEntity.getX()); double y = MathHelper.lerp(tickProgress, itemEntity.lastRenderY, itemEntity.getY()); double z = MathHelper.lerp(tickProgress, itemEntity.lastRenderZ, itemEntity.getZ()); @@ -80,10 +79,10 @@ public class ItemHighlight { EntityDimensions dimension = itemEntity.getDimensions(itemEntity.getPose()); Box box = dimension.getBoxAt(x, y, z).expand(0.1).offset(0, 0.05, 0); float[] color = RenderUtils.toFloats(getColor(itemEntity)); - VertexRendering.drawFilledBox(matrixStack, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); + VertexRendering.drawFilledBox(matrices, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); }); - matrixStack.pop(); + matrices.pop(); }); } @@ -100,7 +99,7 @@ public class ItemHighlight { public static int getColor(ItemEntity item) { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player == null) return 0; - double distance = item.getPos().distanceTo(player.getPos()); + double distance = item.getEntityPos().distanceTo(player.getEntityPos()); if (distance > 20) { return 0; } else if (distance > 3.5) { @@ -1,9 +1,11 @@ package blade.addon.features.dungeon; +import blade.addon.utils.Debug; import blade.addon.utils.Misc; import blade.addon.utils.dungeon.DungeonClass; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.text.Text; @@ -30,12 +32,13 @@ public class LeapOrder { DungeonClass playersClass = null; ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player == null) { - Misc.addChatMessage(Text.literal("Player is somehow null")); + ClientWorld world = MinecraftClient.getInstance().world; + if (player == null || world == null) { + Debug.LOGGER.warn("Player or World is null"); return; } - Scoreboard scoreboard = player.getScoreboard(); + Scoreboard scoreboard = world.getScoreboard(); for (Team team : scoreboard.getTeams()) { String teamStr = team.getPrefix().getString() + team.getSuffix().getString(); Matcher matcher = PATTERN.matcher(teamStr); @@ -12,10 +12,9 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; @@ -138,49 +137,47 @@ public class BossWaypoints { return ActionResult.PASS; } - private static void renderThroughWall(WorldRenderContext worldRenderContext) { + private static void renderThroughWall(WorldRenderContext context) { if (!isInValidArea()) return; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); - VertexConsumerProvider consumers = worldRenderContext.consumers(); + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer consumer = consumers.getBuffer(RenderLayers.FILLED_LAYER); waypoints.forEach(waypoint -> { if (waypoint.isThroughWall()) { - waypoint.Render(consumer, matrixStack); + waypoint.Render(consumer, matrices); } }); - matrixStack.pop(); + matrices.pop(); } - private static void render(WorldRenderContext worldRenderContext) { + private static void render(WorldRenderContext context) { if (!isInValidArea()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); - VertexConsumerProvider consumers = worldRenderContext.consumers(); + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer consumer = consumers.getBuffer(RenderLayers.THROUGH_WALL_FILLED_LAYER); waypoints.forEach(waypoint -> { if (!waypoint.isThroughWall()) { - waypoint.Render(consumer, matrixStack); + waypoint.Render(consumer, matrices); } }); - matrixStack.pop(); + matrices.pop(); } @@ -32,7 +32,7 @@ public class DistanceToLedge { private static boolean isAtYellow() { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player == null) return false; - return YELLOW_PAD.contains(player.getPos()); + return YELLOW_PAD.contains(player.getEntityPos()); } public static boolean display() { @@ -11,11 +11,10 @@ import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; @@ -176,28 +175,26 @@ public class RelicTimer { return false; }); - WorldRenderEvents.BEFORE_DEBUG_RENDER.register(worldRenderContext -> { + WorldRenderEvents.BEFORE_DEBUG_RENDER.register(context -> { if (pickedupRelic == null || !Floor7.renderRelicHighlight) return; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); - - VertexConsumerProvider consumers = worldRenderContext.consumers(); + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer buffer = consumers.getBuffer(RenderLayers.FILLED_LAYER); Box box = pickedupRelic.box; float[] color = RenderUtils.toFloats(pickedupRelic.color); - VertexRendering.drawFilledBox(matrixStack, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); + VertexRendering.drawFilledBox(matrices, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, color[0], color[1], color[2], color[3]); - matrixStack.pop(); + matrices.pop(); }); } @@ -36,7 +36,7 @@ public class PositionMessage { public void tick(ClientPlayerEntity player) { if (sent) return; if (!inAValidSection()) return; - if (inRange(player.getPos())) { + if (inRange(player.getEntityPos())) { sent = true; if (Floor7.enablePositionalMessages) { player.networkHandler.sendChatCommand("pc " + message); @@ -7,11 +7,10 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; @@ -97,31 +96,30 @@ public class PositionMessages { } } - private static void render(WorldRenderContext worldRenderContext) { + private static void render(WorldRenderContext context) { if (!Location.inDungeon() || !Debug.renderPositions) return; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); - VertexConsumerProvider consumers = worldRenderContext.consumers(); + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer consumer = consumers.getBuffer(RenderLayers.OUTLINE_LAYER); + MatrixStack.Entry entry = matrices.peek(); for (PositionMessage positionMessage : positionMessages) { Box box = positionMessage.getBox(); - if (positionMessage.sent()) { - VertexRendering.drawBox(matrixStack, consumer, box, 0, 1, 0, 1); + VertexRendering.drawBox(entry, consumer, box, 0, 1, 0, 1); } else { - VertexRendering.drawBox(matrixStack, consumer, box, 1, 0, 0, 1); + VertexRendering.drawBox(entry, consumer, box, 1, 0, 0, 1); } } - matrixStack.pop(); + matrices.pop(); } } @@ -75,7 +75,7 @@ public class LeapNotification { } private static int getSpot(ClientPlayerEntity player) { - Vec3d pos = player.getPos(); + Vec3d pos = player.getEntityPos(); if (HEE2_BOX.contains(pos)) return 2; if (EE2_BOX.contains(pos)) return 2; else if (EE3_BOX.contains(pos)) return 3; @@ -0,0 +1,92 @@ +package blade.addon.features.highlight; + +import blade.addon.utils.Location; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderUtils; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.TrappedChestBlockEntity; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +import java.util.concurrent.ConcurrentLinkedQueue; + +public class MimicHighlight { + + private static final Box box = new Box(0.0625, 0, 0.0625, 0.9375, 0.875, 0.9375); + + private static final ConcurrentLinkedQueue<TrappedChestBlockEntity> mimicList = new ConcurrentLinkedQueue<>(); + + public static void init() { + + Events.ON_LOCATION_CHANGE.register(location -> { + mimicList.clear(); + }); + + Events.ON_BLOCK_ENTITY.register(blockEntity -> { + if (!Location.inDungeon()) return; + if (blockEntity instanceof TrappedChestBlockEntity mimic) { + mimicList.add(mimic); + } + }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> {mimicList.removeIf(BlockEntity::isRemoved);}); + + WorldRenderEvents.AFTER_ENTITIES.register(MimicHighlight::renderFilled); + WorldRenderEvents.AFTER_ENTITIES.register(MimicHighlight::renderOutline); + } + + private static void renderFilled(WorldRenderContext context) { + if (!MobHighlight.highlightMimicChests) return; + if (!MobHighlight.renderFilled()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + + float[] rgba = RenderUtils.toFloats(MobHighlight.mimicFilledColor); + mimicList.forEach(blockEntity -> { + Box renderBox = box.offset(blockEntity.getPos()); + VertexRendering.drawFilledBox(matrices, filledConsumer, renderBox.minX, renderBox.minY, renderBox.minZ, renderBox.maxX, renderBox.maxY, renderBox.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } + + private static void renderOutline(WorldRenderContext context) { + if (!MobHighlight.highlightMimicChests) return; + if (!MobHighlight.renderOutline()) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); + if (consumers == null) return; + VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(MobHighlight.outlineWidth)); + + MatrixStack.Entry entry = matrices.peek(); + float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); + mimicList.forEach(blockEntity -> { + Box renderBox = box.offset(blockEntity.getPos()); + VertexRendering.drawBox(entry, outlineConsumer, renderBox, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + matrices.pop(); + + } +} @@ -9,13 +9,12 @@ import blade.addon.utils.rendering.RenderUtils; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; @@ -254,7 +253,7 @@ public class MobHighlight { Entity closest = null; double smallestDistance = maxDistance; double maxY = armorStand.getY(); - Box boundingBox = Box.of(armorStand.getPos().subtract(0, 0.5, 0), 2, 3, 2); + Box boundingBox = Box.of(armorStand.getEntityPos().subtract(0, 0.5, 0), 2, 3, 2); ArrayList<Entity> meetsRequirements = new ArrayList<>(); @@ -273,7 +272,7 @@ public class MobHighlight { if (!requirements.test(current)) continue; if (current.getY() > maxY) continue; - double distance = armorStand.getPos().distanceTo(current.getPos()); + double distance = armorStand.getEntityPos().distanceTo(current.getEntityPos()); if (smallestDistance > distance) { closest = current; smallestDistance = distance; @@ -314,7 +313,7 @@ public class MobHighlight { //this is a hack which will fail if someone has a really old bugged ign that includes a space if (entry != null) { - String name = entry.getProfile().getName(); + String name = entry.getProfile().name(); return !name.isEmpty() && !name.contains(" "); } } @@ -413,25 +412,25 @@ public class MobHighlight { return box; } - private static void renderFilled(WorldRenderContext worldRenderContext) { + private static void renderFilled(WorldRenderContext context) { if (!mobHighlight || dontRenderHighlight) return; if (!renderFilled()) return; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); - - VertexConsumerProvider consumers = worldRenderContext.consumers(); + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + trackedMobs.forEach((entity, mobType) -> { if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; - double tickProgress = worldRenderContext.tickCounter().getTickProgress(false); double x = MathHelper.lerp(tickProgress, entity.lastRenderX, entity.getX()); double y = MathHelper.lerp(tickProgress, entity.lastRenderY, entity.getY()); double z = MathHelper.lerp(tickProgress, entity.lastRenderZ, entity.getZ()); @@ -441,34 +440,35 @@ public class MobHighlight { int filledColor = MobHighlight.getFilledColor(entity); float[] rgba = RenderUtils.toFloats(filledColor); - VertexRendering.drawFilledBox(matrixStack, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + VertexRendering.drawFilledBox(matrices, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); }); - matrixStack.pop(); + matrices.pop(); } - private static void renderOutline(WorldRenderContext worldRenderContext) { + private static void renderOutline(WorldRenderContext context) { if (!mobHighlight || dontRenderHighlight) return; if (!renderOutline()) return; - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); - - VertexConsumerProvider consumers = worldRenderContext.consumers(); + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); + + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(outlineWidth)); + double tickProgress = MinecraftClient.getInstance().getRenderTickCounter().getTickProgress(false); + + MatrixStack.Entry entry = matrices.peek(); trackedMobs.forEach((entity, mobType) -> { if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; - double tickProgress = worldRenderContext.tickCounter().getTickProgress(false); double x = MathHelper.lerp(tickProgress, entity.lastRenderX, entity.getX()); double y = MathHelper.lerp(tickProgress, entity.lastRenderY, entity.getY()); double z = MathHelper.lerp(tickProgress, entity.lastRenderZ, entity.getZ()); @@ -478,11 +478,11 @@ public class MobHighlight { int outlineColor = MobHighlight.getOutlineColor(entity); float[] rgba = RenderUtils.toFloats(outlineColor); - VertexRendering.drawBox(matrixStack, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); + VertexRendering.drawBox(entry, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); }); - matrixStack.pop(); + matrices.pop(); } } @@ -38,7 +38,7 @@ public class InventoryButton { context.drawText(textRenderer, "" + index, x + (SIZE - center) / 2 + 1, y + (SIZE - textRenderer.fontHeight) / 2 + 1, 0xffffffff, true); } - public void onClick(double mouseX, double mouseY, int button) { + public void onClick(double mouseX, double mouseY) { String str = command.get(); if (str == null ||str.isEmpty()) return; Misc.executeCommand(str); @@ -48,10 +48,10 @@ public class InventoryButton { return mouseX >= x && mouseX <= x + SIZE && mouseY >= y && mouseY <= y + SIZE; } - public static void parseClicks(double mouseX, double mouseY, int button) { + public static void parseClicks(double mouseX, double mouseY) { for (InventoryButton inventoryButton : inventoryButtons) { if (inventoryButton.inBounds(mouseX, mouseY)) { - inventoryButton.onClick(mouseX, mouseY, button); + inventoryButton.onClick(mouseX, mouseY); } } } @@ -9,13 +9,12 @@ import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; import blade.addon.utils.times.PersonalBests; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; @@ -340,18 +339,15 @@ public class PracticeSS { return endIndex - ticksLeft / getDelay(); } - private static void render(WorldRenderContext worldRenderContext) { + private static void render(WorldRenderContext context) { if (!started) return; + Vec3d camera = context.worldState().cameraRenderState.pos; + MatrixStack matrices = context.matrices(); + if (matrices == null) return; + matrices.push(); + matrices.translate(-camera.x, -camera.y, -camera.z); - Camera camera = worldRenderContext.camera(); - Vec3d cameraPos = camera.getPos(); - - MatrixStack matrixStack = worldRenderContext.matrixStack(); - if (matrixStack == null) return; - matrixStack.push(); - matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); - - VertexConsumerProvider consumers = worldRenderContext.consumers(); + VertexConsumerProvider consumers = context.consumers(); if (consumers == null) return; VertexConsumer buffer = consumers.getBuffer(RenderLayers.FILLED_LAYER); @@ -359,15 +355,15 @@ public class PracticeSS { if (showingPattern) { if (!ExtraOptions.realisticDelay || totalTicks - ticksLeft > START_WAIT_DURATION || endIndex != 2) { int lastIndex = getLastDisplayIndex(); - renderButtons(matrixStack, buffer, 0, lastIndex); - renderBackground(matrixStack, buffer, lastIndex - 1); + renderButtons(matrices, buffer, 0, lastIndex); + renderBackground(matrices, buffer, lastIndex - 1); } } else { - renderButtons(matrixStack, buffer, currentIndex, endIndex); + renderButtons(matrices, buffer, currentIndex, endIndex); } - matrixStack.pop(); + matrices.pop(); } private static void renderButtons(MatrixStack matrixStack, VertexConsumer buffer, int start, int end) { @@ -1,43 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.features.highlight.MobHighlight; -import blade.addon.utils.Location; -import blade.addon.utils.rendering.RenderLayers; -import blade.addon.utils.rendering.RenderUtils; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.TrappedChestBlockEntity; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexRendering; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.math.Box; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(BlockEntityRenderDispatcher.class) -public class BlockEntityRenderMixin { - - @Unique - private static final Box box = new Box(0.0625, 0, 0.0625, 0.9375, 0.875, 0.9375); - - @Inject(method = "render(Lnet/minecraft/block/entity/BlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;)V", at = @At("TAIL")) - private static<E extends BlockEntity> void render(E blockEntity, float tickProgress, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) { - if (blockEntity instanceof TrappedChestBlockEntity) { - if (!Location.inDungeon() || !MobHighlight.highlightMimicChests) return; - if (MobHighlight.renderFilled()) { - VertexConsumer buffer = vertexConsumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - float[] rgba = RenderUtils.toFloats(MobHighlight.mimicFilledColor); - VertexRendering.drawFilledBox(matrices, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - } - if (MobHighlight.renderOutline()) { - VertexConsumer buffer = vertexConsumers.getBuffer(RenderLayers.OUTLINE_ENTITY_LAYER); - float[] rgba = RenderUtils.toFloats(MobHighlight.mimicOutlineColor); - VertexRendering.drawBox(matrices, buffer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - } - } - } -} @@ -0,0 +1,20 @@ +package blade.addon.mixin; + +import blade.addon.utils.events.Events; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.world.chunk.WorldChunk; +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(WorldChunk.class) +public abstract class ChunkMixin { + + @Inject(method = "setBlockEntity", at=@At("HEAD")) + public void onBlockEntity(BlockEntity blockEntity, CallbackInfo ci) { + Events.ON_BLOCK_ENTITY.invoke(blockEntityEvent -> blockEntityEvent.on(blockEntity)); + + } + +} @@ -16,7 +16,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientConnection.class) -public class ServerTickMixin { +public class ClientConnectionMixin { @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), order=0, cancellable = true) private void channelRead0(ChannelHandlerContext channelHandlerContext, Packet<?> packet, CallbackInfo ci) { @@ -1,5 +1,6 @@ package blade.addon.mixin; +import blade.addon.features.dungeon.DeathTickTimer; import blade.addon.utils.Debug; import blade.addon.utils.Misc; import blade.addon.utils.Scheduler; @@ -18,6 +19,7 @@ import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; import net.minecraft.network.packet.s2c.play.TeamS2CPacket; import net.minecraft.scoreboard.Team; import net.minecraft.sound.SoundEvent; @@ -31,7 +33,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientPlayNetworkHandler.class) -public class NetworkMixin { +public class ClientPlayNetworkHandlerMixin { @Shadow @@ -68,7 +70,7 @@ public class NetworkMixin { } @Inject(method = "onPlaySound", at = @At(value = "HEAD"), cancellable = true) - private void onTeam(PlaySoundS2CPacket packet, CallbackInfo ci) { + private void onSound(PlaySoundS2CPacket packet, CallbackInfo ci) { float volume = packet.getVolume(); float pitch = packet.getPitch(); SoundEvent event = packet.getSound().value(); @@ -101,6 +103,11 @@ public class NetworkMixin { } + @Inject(method = "onPlayerPositionLook", at = @At("HEAD")) + private void onPlayerLook(PlayerPositionLookS2CPacket packet, CallbackInfo ci) { + DeathTickTimer.onTeleport(packet.change().position()); + } + @Unique private static boolean isARealPlayer(Entity entity) { if (entity instanceof PlayerEntity player) { @@ -114,7 +121,7 @@ public class NetworkMixin { //this is a hack which will fail if someone has a really old bugged ign that includes a space if (entry != null) { - String name = entry.getProfile().getName(); + String name = entry.getProfile().name(); return !name.isEmpty() && !name.contains(" "); } } @@ -7,7 +7,7 @@ import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.Frustum; -import net.minecraft.client.render.entity.EntityRenderDispatcher; +import net.minecraft.client.render.entity.EntityRenderManager; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; @@ -16,8 +16,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(EntityRenderDispatcher.class) -public class RenderMixin { +@Mixin(EntityRenderManager.class) +public class EntityRenderManagerMixin { @Inject(method = "shouldRender", at = @At("TAIL"), cancellable = true) private <E extends Entity> void shouldRender(E entity, Frustum frustum, double x, double y, double z, CallbackInfoReturnable<Boolean> cir) { @@ -1,10 +1,15 @@ package blade.addon.mixin; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; -import net.minecraft.client.render.VertexConsumerProvider; +import blade.addon.utils.config.values.ExtraOptions; +import net.minecraft.client.render.command.OrderedRenderCommandQueue; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.state.EntityRenderState; +import net.minecraft.client.render.state.CameraRenderState; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -12,13 +17,24 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityRenderer.class) -public class EntityRendererMixin<S extends EntityRenderState> { +public class EntityRendererMixin<T extends Entity, S extends EntityRenderState> { @Inject(method = "renderLabelIfPresent", at=@At("HEAD"), cancellable = true) - private void hideNameTag(S state, Text text, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo ci) { + private void hideNameTag(S state, MatrixStack matrices, OrderedRenderCommandQueue queue, CameraRenderState cameraRenderState, CallbackInfo ci) { + Text text = state.displayName; if (!Dungeons.hideBlazeNameTag || text == null) return; String string = text.getString(); if (string.contains("Blaze")) ci.cancel(); } + + @Inject(method = "updateRenderState", at = @At("TAIL")) + public void hideFire(T entity, S state, float tickProgress, CallbackInfo ci) { + + if (entity instanceof PlayerEntity player && ExtraOptions.hideFireInf5) { + if (Misc.isClientPlayer(player)) { + state.onFire = false; + } + } + } } @@ -1,26 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.utils.Misc; -import blade.addon.utils.config.values.ExtraOptions; -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.client.render.entity.state.EntityRenderState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -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(EntityRenderer.class) -public class FireMixin<T extends Entity, S extends EntityRenderState> { - - @Inject(method = "updateRenderState", at = @At("TAIL")) - public void test(T entity, S state, float tickProgress, CallbackInfo ci) { - - if (entity instanceof PlayerEntity player && ExtraOptions.hideFireInf5) { - if (Misc.isClientPlayer(player)) { - state.onFire = false; - } - } - } -} @@ -1,6 +1,7 @@ package blade.addon.mixin; import blade.addon.features.other.InventoryButton; +import net.minecraft.client.gui.Click; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.InventoryScreen; import net.minecraft.client.gui.screen.ingame.RecipeBookScreen; @@ -20,12 +21,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(InventoryScreen.class) public abstract class InventoryScreenMixin extends RecipeBookScreen<PlayerScreenHandler> { - @Shadow - private float mouseX; - - @Shadow - private float mouseY; - @Final @Shadow private StatusEffectsDisplay statusEffectsDisplay; @@ -46,9 +41,9 @@ public abstract class InventoryScreenMixin extends RecipeBookScreen<PlayerScreen } @Override - public boolean mouseClicked(double mouseX, double mouseY, int button) { - InventoryButton.parseClicks(mouseX - x, mouseY - y, button); - return super.mouseClicked(mouseX, mouseY, button); + public boolean mouseClicked(Click click, boolean doubled) { + InventoryButton.parseClicks(click.x() - x, click.y() - y); + return super.mouseClicked(click, doubled); } @Inject(method = "drawForeground", at = @At("HEAD"), cancellable = true) @@ -9,10 +9,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(PlayerInventory.class) -public class InventoryMixin { +public class PlayerInventoryMixin { @Inject(method = "setStack", at = @At("HEAD")) - private void channelRead0(int slot, ItemStack stack, CallbackInfo ci) { + private void setStack(int slot, ItemStack stack, CallbackInfo ci) { if (Events.ON_SLOT_CHANGE.hasListeners()) { Events.ON_SLOT_CHANGE.listeners.forEach(slotChangeEvent -> slotChangeEvent.onSlotChange(slot, stack)); } @@ -1,21 +0,0 @@ -package blade.addon.mixin; - -import blade.addon.features.dungeon.DeathTickTimer; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; -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(ClientPlayNetworkHandler.class) -public class PositionMixin { - - @Inject(method = "onPlayerPositionLook", at = @At("HEAD")) - private void channelRead0(PlayerPositionLookS2CPacket packet, CallbackInfo ci) { - DeathTickTimer.onTeleport(packet.change().position()); - } - - - -} @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(StuckArrowsFeatureRenderer.class) -public class ArrowMixin { +public class StuckArrowsFeatureRendererMixin { @Inject(method = "getObjectCount", at=@At("TAIL"), cancellable = true) public void shouldRender(CallbackInfoReturnable<Integer> cir) { @@ -10,7 +10,7 @@ public class Constants { public static final int TEXT_HEIGHT = 10; public static final int GREEN_COLOR = 0xff00ff00; - public static final int ORANGE_COLOR = 0xffDAA06D; + public static final int ORANGE_COLOR = 0xffffaa00; public static final int RED_COLOR = 0xffff0000; public static final int FAIL = 0; @@ -13,14 +13,13 @@ import net.minecraft.component.type.LoreComponent; import net.minecraft.component.type.NbtComponent; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; import org.lwjgl.glfw.GLFW; import java.util.List; public class Keybinds { - private static final String CATEGORY = Constants.NAMESPACE; - private static KeyBinding openConfig; private static KeyBinding getItemLore; private static KeyBinding getItemCustomData; @@ -28,23 +27,25 @@ public class Keybinds { public static void init() { + KeyBinding.Category category = KeyBinding.Category.create(Identifier.of(Constants.NAMESPACE)); + openConfig = KeyBindingHelper.registerKeyBinding(new KeyBinding( "opens Config", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_RIGHT_SHIFT, - CATEGORY)); + category)); getItemLore = KeyBindingHelper.registerKeyBinding(new KeyBinding( "Grabs the items lore", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - CATEGORY)); + category)); getItemCustomData = KeyBindingHelper.registerKeyBinding(new KeyBinding( "Grabs the items custom data", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_UNKNOWN, - CATEGORY)); + category)); ClientTickEvents.END_CLIENT_TICK.register(Keybinds::checkInputs); } @@ -61,7 +61,7 @@ public class Config { hidePlayers.add(new ConfigBool(Text.literal("Hide at SS"), () -> Dungeons.hideAtSS, bool -> Dungeons.hideAtSS = bool)); hidePlayers.add(new ConfigBool(Text.literal("SS only hides before terms"), () -> Dungeons.hideBeforeTermsOnly, bool -> Dungeons.hideBeforeTermsOnly = bool)); hidePlayers.add(new ConfigBool(Text.literal("Hide players in range"), () -> Dungeons.hidePlayersInRange, bool -> Dungeons.hidePlayersInRange = bool)); - hidePlayers.add(new ConfigDouble(Text.literal("Hiding range"), () -> Dungeons.hidePlayerRange, num -> Dungeons.hidePlayerRange = num, 0, 0, 7)); + hidePlayers.add(new ConfigDouble(Text.literal("Hiding range"), () -> Dungeons.hidePlayerRange, num -> Dungeons.hidePlayerRange = num, 1, 0, 7)); dungeons.add(hidePlayers); @@ -8,6 +8,7 @@ import blade.addon.utils.events.Events; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.text.Text; @@ -61,7 +62,8 @@ public enum DungeonClass { } private static void detectClasses() { - ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); + MinecraftClient client = MinecraftClient.getInstance(); + ClientPlayNetworkHandler networkHandler = client.getNetworkHandler(); if (networkHandler == null) return; Collection<PlayerListEntry> entryCollection = networkHandler.getPlayerList(); @@ -78,6 +80,15 @@ public enum DungeonClass { nameClassMap.put(name, className); } } + + //incase currentClass could not detect class before + if (currentClass == null) { + ClientPlayerEntity player = client.player; + if (player == null) return; + String name = player.getStringifiedName(); + currentClass = nameClassMap.get(name); + + } } public static DungeonClass getClass(String playerName) { @@ -1,5 +1,6 @@ package blade.addon.utils.events; +import blade.addon.utils.events.interfaces.BlockEntityEvent; import blade.addon.utils.events.interfaces.BlockInteractionEvent; import blade.addon.utils.events.interfaces.CancelableMessageEvent; import blade.addon.utils.events.interfaces.EntityEvent; @@ -44,5 +45,7 @@ public class Events { public static final CancelableEventHandler<PlaySoundEvent> ON_SOUND = new CancelableEventHandler<>(); + public static final EventHandler<BlockEntityEvent> ON_BLOCK_ENTITY = new EventHandler<>(); + } @@ -0,0 +1,9 @@ +package blade.addon.utils.events.interfaces; + +import net.minecraft.block.entity.BlockEntity; + +public interface BlockEntityEvent { + + void on(BlockEntity blockEntity); + +} @@ -3,13 +3,14 @@ "package": "blade.addon.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "ArrowMixin", + "ClientConnectionMixin", + "ClientPlayNetworkHandlerMixin", + "ChunkMixin", "EntityMixin", - "InventoryMixin", "ItemStackMixin", - "NetworkMixin", "PlayerEntityMixin", - "ServerTickMixin" + "PlayerInventoryMixin", + "StuckArrowsFeatureRendererMixin" ], "injectors": { "defaultRequire": 1 @@ -18,21 +19,18 @@ "requireAnnotations": true }, "client": [ - "BlockEntityRenderMixin", "ClientPlayerEntityMixin", + "ClientPlayNetworkHandlerMixin", "EntityRendererMixin", - "FireMixin", + "EntityRenderManagerMixin", "HandledScreenMixin", "HeldItemRendererMixin", "InGameHudMixin", "Invento …… diff 过长已截断 …… |
| - added selectable mobhighlight width - added distance to ledge on yellow pad only - added compact hoppity msg - added hide players in specific range - added disable drop animation in dungeons - added hide notification for yourself - added hide most titles in terminals phase - made so mimic toggle is separate from the global toggle - added disable recipe book - added inventory buttons (not finished) - added color option to chest count - disabled melody msg when its your own name - reworked positional messages and location notifier - added custom rag sound - added mask progress highlight - hopefully fixed realistic SS setting missing some ticks
- fixed practice ss saving times weirdly
- fixed predev timer still tracking after p2
- fixed prec drone not having a sprite
- fixed pillar explosion timer and storm crush notification being reversed
- fixed terminal events only being processed if terminalsplits are on
- fixed progress bar not being like valleys (added a toggle)
- fixed pre4 notifier triggering on all devices
- fixed item protection not always working in sell menus
NOTE: sounds from at msg will be reset sadly with how im changing the way i save it but will make it easier to change sound 查看变更gradle.properties | 5 +-
src/main/java/blade/addon/Bladeaddons.java | 22 +++++---
src/main/java/blade/addon/features/dungeon/ChestCounter.java | 2 +-
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 20 ++++++--
src/main/java/blade/addon/features/dungeon/f7/DistanceToLedge.java | 9 ++++
src/main/java/blade/addon/features/dungeon/f7/PillarExplode.java | 8 +--
src/main/java/blade/addon/features/dungeon/f7/PositionMessages.java | 40 ---------------
src/main/java/blade/addon/features/dungeon/f7/PredevTimer.java | 14 ++---
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 26 +++++++---
src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 1 +
src/main/java/blade/addon/features/dungeon/f7/{ => invincibility}/InvincibilityTimer.java | 17 ++++--
src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskHighlight.java | 51 ++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskHolder.java | 12 +++++
src/main/java/blade/addon/features/dungeon/f7/invincibility/MaskType.java | 5 ++
src/main/java/blade/addon/features/dungeon/f7/{ => location}/LocationNotifier.java | 16 ++++--
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessage.java | 69 +++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/location/PositionMessages.java | 127 +++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/{ => terms}/GoldorTickTimer.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/{ => terms}/LeapNotification.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/{ => terms}/MelodyWarning.java | 16 +++++-
src/main/java/blade/addon/features/dungeon/f7/{ => terms}/Pre4Notifier.java | 7 +--
src/main/java/blade/addon/features/dungeon/f7/{ => terms}/TermStartTimer.java | 2 +-
src/main/java/blade/addon/features/dungeon/f7/terms/TitleHider.java | 13 +++++
src/main/java/blade/addon/features/highlight/MobHighlight.java | 5 +-
src/main/java/blade/addon/features/item/DropAnimation.java | 58 +++++++++++++++++++++
src/main/java/blade/addon/features/item/ProtectItem.java | 2 +-
src/main/java/blade/addon/features/other/CompactHoppity.java | 49 ++++++++++++++++++
src/main/java/blade/addon/features/other/InventoryButton.java | 64 +++++++++++++++++++++++
src/main/java/blade/addon/features/other/PracticeSS.java | 142 +++++++++++++++++++++++++++++++--------------------
src/main/java/blade/addon/features/other/RagDisplay.java | 19 +++++--
src/main/java/blade/addon/mixin/BlockEntityRenderMixin.java | 2 +-
src/main/java/blade/addon/mixin/ClientPlayerEntityMixin.java | 12 ++++-
src/main/java/blade/addon/mixin/HandledScreenMixin.java | 6 +++
src/main/java/blade/addon/mixin/HeldItemRendererMixin.java | 64 +++++++++++++++++++++++
src/main/java/blade/addon/mixin/InGameHudMixin.java | 49 ++++++++++++++++--
src/main/java/blade/addon/mixin/InventoryScreenMixin.java | 59 +++++++++++++++++++++
src/main/java/blade/addon/mixin/ItemStackMixin.java | 24 ++++++++-
src/main/java/blade/addon/mixin/MinecraftClientMixin.java | 7 +++
src/main/java/blade/addon/mixin/NetworkMixin.java | 11 +---
src/main/java/blade/addon/mixin/RecipeBookScreenMixin.java | 18 +++++++
src/main/java/blade/addon/mixin/RecipeBookWidgetMixin.java | 36 +++++++++++++
src/main/java/blade/addon/mixin/ServerTickMixin.java | 8 ++-
src/main/java/blade/addon/utils/Commands.java | 23 ++++++++-
src/main/java/blade/addon/utils/Debug.java | 17 +++++-
src/main/java/blade/addon/utils/JsonUtility.java | 57 ---------------------
src/main/java/blade/addon/utils/Misc.java | 41 ++++++++++++---
src/main/java/blade/addon/utils/Scheduler.java | 11 ++++
src/main/java/blade/addon/utils/config/Config.java | 44 ++++++++++++----
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 4 +-
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 4 +-
src/main/java/blade/addon/utils/config/components/Components.java | 14 ++---
src/main/java/blade/addon/utils/config/values/Buttons.java | 50 ++++++++++++++++++
src/main/java/blade/addon/utils/config/values/Dungeons.java | 17 +++++-
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 18 +++++++
src/main/java/blade/addon/utils/config/values/Floor7.java | 22 +++++---
src/main/java/blade/addon/utils/dungeon/Phase.java | 11 ++--
src/main/java/blade/addon/utils/dungeon/PositionMessage.java | 46 -----------------
src/main/java/blade/addon/utils/dungeon/Section.java | 52 ++++++++++++++++---
src/main/java/blade/addon/utils/events/Events.java | 14 +++--
src/main/java/blade/addon/utils/events/interfaces/CancelableMessageEvent.java | 8 +++
src/main/java/blade/addon/utils/events/interfaces/PlaySoundEvent.java | 2 +-
src/main/java/blade/addon/utils/interfaces/GameHud.java | 7 +++
src/main/java/blade/addon/utils/rendering/RenderLayers.java | 27 ++++++++++
src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 6 +++
src/main/java/blade/addon/utils/times/PersonalBests.java | 4 +-
.../assets/blade-addons/textures/gui/sprites/pets/{flying-fish-mythic.png => flying-fish.png} | Bin
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/precursor-drone.png | Bin 0 -> 2685 bytes
src/main/resources/blade-addons.mixins.json | 4 ++
src/main/resources/data/positions.json | 81 -----------------------------
69 files changed, 1297 insertions(+), 408 deletions(-)@@ -13,12 +13,13 @@ loader_version=0.17.3 loom_version=1.13-SNAPSHOT # Mod Properties -mod_version=2.2.5 +mod_version=2.2.6 maven_group=blade.addon archives_base_name=blade-addons # Dependencies fabric_version=0.136.0+1.21.8 -practical_config=1.3.5 +# I love dependencies sometimes breaking +practical_config=1.3.7 modmenu_version = 15.0.0 hypixel_api_version = 1.0.1 \ No newline at end of file @@ -15,19 +15,21 @@ import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.CrystalSpawn; import blade.addon.features.dungeon.f7.DistanceToLedge; import blade.addon.features.dungeon.f7.DragSpawnTimer; -import blade.addon.features.dungeon.f7.GoldorTickTimer; -import blade.addon.features.dungeon.f7.InvincibilityTimer; -import blade.addon.features.dungeon.f7.LeapNotification; -import blade.addon.features.dungeon.f7.LocationNotifier; -import blade.addon.features.dungeon.f7.MelodyWarning; +import blade.addon.features.dungeon.f7.terms.GoldorTickTimer; +import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; +import blade.addon.features.dungeon.f7.terms.LeapNotification; +import blade.addon.features.dungeon.f7.location.LocationNotifier; +import blade.addon.features.dungeon.f7.terms.MelodyWarning; import blade.addon.features.dungeon.f7.PillarExplode; -import blade.addon.features.dungeon.f7.PositionMessages; -import blade.addon.features.dungeon.f7.Pre4Notifier; +import blade.addon.features.dungeon.f7.location.PositionMessages; +import blade.addon.features.dungeon.f7.terms.Pre4Notifier; import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; -import blade.addon.features.dungeon.f7.TermStartTimer; +import blade.addon.features.dungeon.f7.terms.TermStartTimer; import blade.addon.features.highlight.MobHighlight; +import blade.addon.features.item.DropAnimation; +import blade.addon.features.other.CompactHoppity; import blade.addon.features.other.DianaNotifier; import blade.addon.features.other.KickedTimer; import blade.addon.features.other.PracticeSS; @@ -41,6 +43,7 @@ import blade.addon.utils.Scheduler; import blade.addon.utils.config.Config; import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.components.Components; +import blade.addon.utils.config.values.Buttons; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; @@ -52,6 +55,7 @@ public class Bladeaddons implements ModInitializer { public void onInitialize() { FolderUtility.init(); Components.init(); + Buttons.init(); Config.manager.load(); Keybinds.init(); CustomEvents.init(); @@ -95,5 +99,7 @@ public class Bladeaddons implements ModInitializer { RagDisplay.init(); LeapNotification.init(); PracticeSS.init(); + CompactHoppity.init(); + DropAnimation.init(); } } \ No newline at end of file @@ -68,7 +68,7 @@ public class ChestCounter { int y = component.getScaledY(); if (hasUpdatedData) { - context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, 0xffffffff, true); + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, Dungeons.chestCountColor , true); } else { context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, 0xffff0000, true); @@ -1,9 +1,13 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Dungeons; +import blade.addon.utils.detection.Detection; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.Vec3d; @@ -47,14 +51,24 @@ public class HidePlayers { public static boolean shouldHidePlayers(PlayerEntity player) { if (!Location.inDungeon()) return false; - //in case it's a mob instead of a player - if (player.getName().getString().contains(" ")) return false; + if (!Detection.isARealPlayer(player)) return false; + if (Misc.isClientPlayer(player)) return false; if (testHideAtLeap()) { return true; } - return testHideAtSS(player); + if (testHideAtSS(player)) { + return true; + } + + if (Dungeons.hidePlayersInRange) { + ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; + if (clientPlayer == null) return false; + return player.getPos().distanceTo(clientPlayer.getPos()) <= Dungeons.hidePlayerRange; + } + + return false; } @@ -11,9 +11,11 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.text.Text; +import net.minecraft.util.math.Box; public class DistanceToLedge { + private static final Box YELLOW_PAD = new Box(20, 163, 0, 58, 213, 107); private static final double MIN_X = 33.704; public static void init() { @@ -27,8 +29,15 @@ public class DistanceToLedge { return player.getX() - MIN_X; } + private static boolean isAtYellow() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return false; + return YELLOW_PAD.contains(player.getPos()); + } + public static boolean display() { if (!Floor7.displayDistanceToLedge || !Location.inDungeon()) return false; + if (Floor7.showDistanceAtYellowOnly && !isAtYellow()) return false; return Phase.inP2() && !Phase.stormDead() && (DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER)); } @@ -27,7 +27,7 @@ public class PillarExplode { String string = text.getString(); if (string == null) return; - if (string.equals("[BOSS] Storm: Oof") ||string.equals("[BOSS] Storm: Ouch, that hurt!")) { + if (string.equals("[BOSS] Storm: Oof") || string.equals("[BOSS] Storm: Ouch, that hurt!")) { tick = TOTAL_TICKS; Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); } @@ -37,14 +37,14 @@ public class PillarExplode { } public static boolean displayTimer() { - return Floor7.notifyStormCrush && tick > 0; + return Floor7.timePillarExplosion && tick > 0; } public static void renderTimer(HUDComponent component, DrawContext context) { int x = component.getScaledX(); int y = component.getScaledY(); - Formatting formatting = (tick < 6? Formatting.GREEN: Formatting.RED); + Formatting formatting = (tick < 6 ? Formatting.GREEN : Formatting.RED); double num = tick * Constants.TICK_DURATION; @@ -53,7 +53,7 @@ public class PillarExplode { } public static boolean display() { - return Floor7.timePillarExplosion && tick > 0; + return Floor7.notifyStormCrush && tick > 0; } public static void render(HUDComponent component, DrawContext context) { @@ -1,40 +0,0 @@ -package blade.addon.features.dungeon.f7; - -import blade.addon.utils.JsonUtility; -import blade.addon.utils.Location; -import blade.addon.utils.config.values.Floor7; -import blade.addon.utils.dungeon.Phase; -import blade.addon.utils.dungeon.PositionMessage; -import blade.addon.utils.events.Events; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; - -import java.util.ArrayList; - -public class PositionMessages { - - private static final ArrayList<PositionMessage> positionMessages = JsonUtility.readPositionalMessages("/data/positions.json"); - - public static void init() { - Events.ON_LOCATION_CHANGE.register(newLocation -> { - if (Location.inDungeon()) { - for (PositionMessage message : positionMessages) { - message.reset(); - } - } - }); - - ClientTickEvents.END_CLIENT_TICK.register(PositionMessages::tick); - } - - public static void tick(MinecraftClient client) { - if (!Location.inDungeon() || !Phase.inP3() || !Floor7.enablePositionalMessages) return; - ClientPlayerEntity player = client.player; - if (player == null) return; - - for (PositionMessage message : positionMessages) { - message.tick(player); - } - } -} @@ -14,7 +14,7 @@ public class PredevTimer { private static long bossEnterTime = 0; private static boolean at3rdDev = false; - private static boolean enteredBoss = false; + private static boolean shouldTrack = false; public static void init() { @@ -22,14 +22,16 @@ public class PredevTimer { if (Phase.inP1()) { bossEnterTime = System.currentTimeMillis(); at3rdDev = false; - enteredBoss = true; + shouldTrack = true; + } else if (Phase.inP3()) { + shouldTrack = false; } }); - Events.ON_LOCATION_CHANGE.register(newLocation -> enteredBoss = false); + Events.ON_LOCATION_CHANGE.register(newLocation -> shouldTrack = false); ClientTickEvents.END_CLIENT_TICK.register(client -> { - if (!enteredBoss || at3rdDev || (!Floor7.predevForAll && !DungeonClass.isClass(DungeonClass.HEALER))) return; + if (!shouldTrack || at3rdDev || (!Floor7.predevForAll && !DungeonClass.isClass(DungeonClass.HEALER))) return; ClientPlayerEntity player = client.player; if (player == null) return; if (Misc.getDistance(player.getX(), player.getZ(), 1, 77) <= 3) { @@ -38,10 +40,10 @@ public class PredevTimer { }); Events.ON_LEAP.register(message -> { - if (at3rdDev && enteredBoss && (DungeonClass.isClass(DungeonClass.HEALER) || Floor7.predevForAll)) { + if (at3rdDev && shouldTrack && (DungeonClass.isClass(DungeonClass.HEALER) || Floor7.predevForAll)) { PersonalBests.predevTime.testNewTime(Text.literal("§aPredev completed in "), bossEnterTime); at3rdDev = false; - enteredBoss = false; + shouldTrack = false; } }); @@ -240,16 +240,28 @@ public class RelicTimer { int y = component.getScaledY(); //from valleyAddons + StringBuilder message = new StringBuilder("§8["); - int diff = Floor7.relicSpawnTicks - tick; - for (int i = 0; i < Floor7.relicSpawnTicks; i++) { - if (i < diff) { - if (tick < 2) message.append("§a|"); - else message.append("§c|"); - } else message.append("§7|"); + if (Floor7.useValleyBar) { + for (int i = 0; i < Floor7.relicSpawnTicks; ++i) { + if (i < tick) { + if (tick > 2) message.append("§a|"); + else message.append("§c|"); + } + else message.append("§7|"); + } + message.append("§8]"); + } else { + int diff = Floor7.relicSpawnTicks - tick; + for (int i = 0; i < Floor7.relicSpawnTicks; i++) { + if (i < diff) { + if (tick < 2) message.append("§a|"); + else message.append("§c|"); + } else message.append("§7|"); + } + message.append("§8]"); } - message.append("§8]"); RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(message.toString()), x, y, component.getWidth(), 0xffffffff); @@ -1,5 +1,6 @@ package blade.addon.features.dungeon.f7; +import blade.addon.features.dungeon.f7.invincibility.InvincibilityTimer; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; @@ -1,5 +1,6 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.invincibility; +import blade.addon.features.dungeon.f7.terms.Pre4Notifier; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; @@ -114,19 +115,19 @@ public class InvincibilityTimer { Matcher matcher = BONZO_PATTERN.matcher(string); if (matcher.matches()) { bonzoMaskTicks = BONZO_MASK_COOLDOWN; - if (Dungeons.showProcTitle) { + if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { Misc.setTitle(Text.literal("Bonzo")); } } if (string.equals("Second Wind Activated! Your Spirit Mask saved your life!")) { spiritMaskTicks = SPIRIT_MASK_COOLDOWN; - if (Dungeons.showProcTitle) { + if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { Misc.setTitle(Text.literal("Spirit")); } } if (string.equals("Your Phoenix Pet saved you from certain death!")) { phoenixTicks = PHOENIX_COOLDOWN; - if (Dungeons.showProcTitle) { + if (Dungeons.showProcTitle && !Pre4Notifier.atDev()) { Misc.setTitle(Text.literal("Phoenix")); } } @@ -167,6 +168,14 @@ public class InvincibilityTimer { } } + public static double getBonzoProgress() { + return (double) bonzoMaskTicks / BONZO_MASK_COOLDOWN; + } + + public static double getSpiritProgress() { + return (double) spiritMaskTicks / SPIRIT_MASK_COOLDOWN; + } + private static void drawSprite(DrawContext context, Identifier identifier, int x, int y, boolean isOn, int ticks, Text timerText) { int color; @@ -0,0 +1,51 @@ +package blade.addon.features.dungeon.f7.invincibility; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; + +public class MaskHighlight { + + private static final int COLOR = 0xbb666666; + + public static void draw(DrawContext context, ItemStack stack, int x, int y) { + MaskHolder holder = (MaskHolder) (Object) stack; + assert holder != null; + + if (!holder.blade_addons$scannedMask()) { + MaskType mask = getMaskType(stack); + holder.blade_addons$setMask(mask); + } + + MaskType mask = holder.blade_addons$getMask(); + + int progress = 0; + switch (mask) { + case SPIRIT -> progress = (int) (InvincibilityTimer.getSpiritProgress() * 16); + case BONZO -> progress = (int) (InvincibilityTimer.getBonzoProgress() * 16); + } + if (progress == 0) return; + context.fill(x, y + 16 - progress, x + 16, y + 16, COLOR); + } + + public static MaskType getMaskType(ItemStack item) { + String id = getId(item); + if (id == null) return MaskType.NONE; + + if (id.contains("SPIRIT_MASK")) return MaskType.SPIRIT; + if (id.contains("BONZO_MASK")) return MaskType.BONZO; + return MaskType.NONE; + } + + public static String getId(ItemStack item) { + NbtComponent nbt = item.get(DataComponentTypes.CUSTOM_DATA); + if (nbt == null) return null; + + NbtCompound compound = nbt.copyNbt(); + + return compound.getString("id", null); + } + +} @@ -0,0 +1,12 @@ +package blade.addon.features.dungeon.f7.invincibility; + +public interface MaskHolder { + + MaskType maskType = null; + + boolean blade_addons$scannedMask(); + + void blade_addons$setMask(MaskType maskType); + + MaskType blade_addons$getMask(); +} @@ -0,0 +1,5 @@ +package blade.addon.features.dungeon.f7.invincibility; + +public enum MaskType { + BONZO, SPIRIT, NONE; +} @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.location; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; @@ -9,10 +9,9 @@ import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; -import net.minecraft.sound.SoundEvent; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Formatting; -import net.minecraft.util.Identifier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -31,8 +30,16 @@ public class LocationNotifier { if (!matcher.find()) return; String action = matcher.group(1); + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return; + Text name = player.getName(); + if (name == null) return; + if (Floor7.dontNotifiyForYourself && name.getString().equals(username)) return; String screenNotification = (username + " is " + action + message.substring(action.length()) + "!").replaceAll("§.", ""); + if (PositionMessages.hasBeenSent(screenNotification)) return; startNotification(screenNotification); + + }); ClientTickEvents.END_CLIENT_TICK.register(client -> ticks = Math.max(ticks - 1, 0)); @@ -43,8 +50,7 @@ public class LocationNotifier { ticks = Floor7.notificationDuration; for (int i = 0; i < Floor7.notificationRepetitions; i++) { - SoundEvent event = SoundEvent.of(Identifier.of(Floor7.notificationSound)); - Scheduler.scheduleSound(event, Floor7.notificationVolume, Floor7.notificationPitch, i + 1); + Scheduler.scheduleSound(Floor7.atLocationSound, i + 1); } } @@ -0,0 +1,69 @@ +package blade.addon.features.dungeon.f7.location; + +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Section; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +public class PositionMessage { + + private final String message, check; + private final Box box; + private boolean sent; + private final int[] sections; + + public PositionMessage(String message, String check, Box box, int[] sections) { + this.message = message; + this.check = check; + this.box = box; + this.sent = true; + this.sections = sections; + PositionMessages.positionMessages.add(this); + } + + private boolean inRange(Vec3d pos) { + return box.contains(pos); + } + + private boolean inAValidSection() { + for (int section : sections) { + if (Section.inSection(section)) return true; + } + return false; + } + + public void tick(ClientPlayerEntity player) { + if (sent) return; + if (!inAValidSection()) return; + if (inRange(player.getPos())) { + sent = true; + if (Floor7.enablePositionalMessages) { + player.networkHandler.sendChatCommand("pc " + message); + } + } + } + + public boolean hasBeenSent(String string) { + if (!string.toLowerCase().contains(check)) return false; + + if (sent) { + return true; + } else { + sent = true; + return false; + } + } + + public void setSent(boolean sent) { + this.sent = sent; + } + + public boolean sent() { + return sent; + } + + public Box getBox() { + return box; + } +} @@ -0,0 +1,127 @@ +package blade.addon.features.dungeon.f7.location; + +import blade.addon.utils.Debug; +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderLayers; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +import java.util.ArrayList; + +public class PositionMessages { + + static final ArrayList<PositionMessage> positionMessages = new ArrayList<>(); + + static PositionMessage SS = new PositionMessage("At SS!", "ss", new Box(107, 120, 93, 110, 121, 95), new int[]{0, 1}); + static PositionMessage EE2 = new PositionMessage("At EE2!", "ee2", new Box(57, 109, 130, 59, 110, 132), new int[]{1, 2}); + static PositionMessage HEE2 = new PositionMessage("At High EE2!", "ee2", new Box(59, 132, 138, 62, 133, 140), new int[]{1, 2}); + static PositionMessage EE3 = new PositionMessage("At EE3!", "ee3", new Box(1, 109, 103, 3, 110, 106), new int[]{2, 3}); + static PositionMessage CORE = new PositionMessage("At Core!", "core", new Box(53, 115, 51, 56, 116, 54), new int[]{2, 3, 4}); + static PositionMessage TUNNEL = new PositionMessage("Inside Goldor Tunnel!", "tunnel", new Box(52, 114, 55, 57, 116, 58), new int[]{4, 5}); + static PositionMessage SAFE_2 = new PositionMessage("At 2 Safespot!", "2 safespot", new Box(46, 109, 121.987, 49, 110, 121.988), new int[]{1, 2}); + static PositionMessage SAFE_3 = new PositionMessage("At 3 Safespot!", "3 safespot", new Box(18, 121, 91, 19, 126, 99), new int[]{2, 3}); + static PositionMessage SPLIT_2 = new PositionMessage("At Split ee2!", "split ee2", new Box(58, 119, 124, 60, 123, 126), new int[]{1, 2}); + static PositionMessage SAFE_2_HIGH = new PositionMessage("At High 2 Safespot!", "2 safespot", new Box(70, 127, 143.7, 57, 133, 146.7), new int[]{1, 2}); + + public static void init() { + ClientTickEvents.END_CLIENT_TICK.register(PositionMessages::tick); + WorldRenderEvents.BEFORE_ENTITIES.register(PositionMessages::render); + Events.ON_LOCATION_CHANGE.register(newLocation -> { + disableAll(); + }); + + Events.ON_PHASE_CHANGE.register(() -> { + if (Phase.inP2()) { + SS.setSent(false); + } else if (Phase.inTerminals()) { + EE2.setSent(false); + HEE2.setSent(false); + EE3.setSent(false); + CORE.setSent(false); + TUNNEL.setSent(false); + SAFE_2.setSent(false); + SAFE_3.setSent(false); + SPLIT_2.setSent(false); + SAFE_2_HIGH.setSent(false); + } else if (Phase.inGoldorTunnel()) { + EE2.setSent(true); + HEE2.setSent(true); + EE3.setSent(true); + CORE.setSent(true); + TUNNEL.setSent(true); + SAFE_2.setSent(true); + SAFE_3.setSent(true); + SPLIT_2.setSent(true); + SAFE_2_HIGH.setSent(true); + } + }); + + + } + + public static void tick(MinecraftClient client) { + if (!Location.inDungeon() || !Floor7.enablePositionalMessages) return; + ClientPlayerEntity player = client.player; + if (player == null) return; + + for (PositionMessage message : positionMessages) { + message.tick(player); + } + } + + public static boolean hasBeenSent(String message) { + for (PositionMessage positionMessage : positionMessages) { + if (positionMessage.hasBeenSent(message)) { + return true; + } + } + return false; + } + + public static void disableAll() { + for (PositionMessage positionMessage : positionMessages) { + positionMessage.setSent(true); + } + } + + private static void render(WorldRenderContext worldRenderContext) { + if (!Location.inDungeon() || !Debug.renderPositions) return; + + Camera camera = worldRenderContext.camera(); + Vec3d cameraPos = camera.getPos(); + MatrixStack matrixStack = worldRenderContext.matrixStack(); + if (matrixStack == null) return; + matrixStack.push(); + matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + + VertexConsumerProvider consumers = worldRenderContext.consumers(); + if (consumers == null) return; + VertexConsumer consumer = consumers.getBuffer(RenderLayers.OUTLINE_LAYER); + for (PositionMessage positionMessage : positionMessages) { + Box box = positionMessage.getBox(); + + if (positionMessage.sent()) { + VertexRendering.drawBox(matrixStack, consumer, box, 0, 1, 0, 1); + } else { + VertexRendering.drawBox(matrixStack, consumer, box, 1, 0, 0, 1); + } + } + + + matrixStack.pop(); + + } +} @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Constants; import blade.addon.utils.Location; @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Location; import blade.addon.utils.config.values.Floor7; @@ -9,6 +9,7 @@ import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.text.Text; import java.util.concurrent.CopyOnWriteArrayList; @@ -22,6 +23,7 @@ public class MelodyWarning { private static final CopyOnWriteArrayList<String> names = new CopyOnWriteArrayList<>(); private static boolean melodyStarted = false; + private static boolean ownUsername = false; private static String name; private static int furthestProgress = 0; @@ -37,6 +39,7 @@ public class MelodyWarning { melodyStarted = true; name = username; furthestProgress = progress; + ownUsername = isOwnUsername(username); if (!names.contains(username)) { names.add(username); } @@ -59,15 +62,24 @@ public class MelodyWarning { }); } + private static boolean isOwnUsername(String username) { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return false; + Text textName = player.getName(); + if (textName == null) return false; + return textName.getString().equals(username); + } + private static void reset() { names.clear(); furthestProgress = 0; name = ""; melodyStarted = false; + ownUsername = false; } public static boolean display() { - return melodyStarted && Floor7.notifiyMelody; + return melodyStarted && Floor7.notifiyMelody && !ownUsername; } public static void render(HUDComponent component, DrawContext context) { @@ -1,5 +1,6 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.terms; +import blade.addon.utils.Misc; import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; @@ -24,7 +25,7 @@ public class Pre4Notifier { Events.ON_TERMINAL.register((name, objective) -> { if (!Floor7.notifyPre4Completion) return; - if (objective.equals("device") && atDev()) { + if (objective.equals("device") && Misc.isClientPlayer(name) && atDev()) { completedTime = System.currentTimeMillis(); showNotification = true; Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); @@ -32,7 +33,7 @@ public class Pre4Notifier { }); } - private static boolean atDev() { + public static boolean atDev() { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player == null) return false; return (player.getX() >= 63 && player.getX() <= 64 && player.getY() == 127 && player.getZ() >= 35 && player.getZ() <= 36); @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon.f7; +package blade.addon.features.dungeon.f7.terms; import blade.addon.utils.Constants; import blade.addon.utils.Location; @@ -0,0 +1,13 @@ +package blade.addon.features.dungeon.f7.terms; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; + +public class TitleHider { + + public static boolean shouldHideTitle() { + return Floor7.hideTerminalTitles && Phase.inP3() && Location.inDungeon(); + } + +} @@ -95,6 +95,9 @@ public class MobHighlight { @ConfigValue public static boolean highlightMimicChests = true; + @ConfigValue + public static int outlineWidth = 4; + @ConfigValue public static int starFilledColor = 0xff00ff00; @ConfigValue @@ -458,7 +461,7 @@ public class MobHighlight { VertexConsumerProvider consumers = worldRenderContext.consumers(); if (consumers == null) return; - VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.OUTLINE_ENTITY_LAYER); + VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.getOutline(outlineWidth)); trackedMobs.forEach((entity, mobType) -> { @@ -0,0 +1,58 @@ +package blade.addon.features.item; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; + +public class DropAnimation { + + private static final int FIX_IN_TICKS = 20; + + private static int scheduledFix = 0; + private static ItemStack dropped; + private static int selectedSlot; + private static boolean cleared = false; + + public static void init() { + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (scheduledFix == 0) { + clearData(); + } else if (dropped != null){ + scheduledFix--; + } + }); + } + + public static void clearData() { + if (cleared) return; + setDroppedData(null, -1); + cleared = true; + } + + public static void setDroppedData(ItemStack itemStack, int slot) { + if (itemStack == null) { + dropped = null; + selectedSlot = -1; + return; + } + if (itemStack.getItem() == Items.AIR) return; + dropped = itemStack; + selectedSlot = slot; + scheduledFix = FIX_IN_TICKS; + cleared = false; + } + + public static ItemStack getPrevDroppedItem() { + return dropped; + } + + public static int getSelectedSlot() { + return selectedSlot; + } + + public static boolean shouldProceed() { + return Dungeons.disableDropAnimation && Location.inDungeon(); + } +} @@ -124,7 +124,7 @@ public class ProtectItem { Slot slot = slots.get(49); ItemStack stack = slot.getStack(); Text itemName = stack.getName(); - if (itemName != null && itemName.getString().contains("Sell Item")) { + if (itemName != null && itemName.getString().contains("Sell Item") || Misc.containsLore(stack, "Click to buyback!")) { Misc.addChatMessage(Text.literal("Protected ").append(item.getName()).append(" From being sold")); return true; } @@ -0,0 +1,49 @@ +package blade.addon.features.other; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import net.minecraft.text.Text; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CompactHoppity { + + private static final Pattern NAME_PATTERN = Pattern.compile("^§D§LHOPPITY'S HUNT §7You found (.+) §.\\(.+\\)!$"); + private static final Pattern INFO_PATTERN = Pattern.compile("^(§.§.)(DUPLICATE|NEW) RABBIT! (.+)"); + private static String formattedName = ""; + + public static void init() { + + Events.ON_CANCELABLE_GAME_MESSAGE.register(text -> { + if (!ExtraOptions.compactHoppityMsgs) return false; + + String string = text.getString(); + if (string.equals("HOPPITY'S HUNT You found a Hitman Egg!")) { + return true; + } + + Matcher matcher = NAME_PATTERN.matcher(string); + if (matcher.find()) { + formattedName = matcher.group(1); + return true; + } + + matcher = INFO_PATTERN.matcher(string); + if (matcher.find()) { + String styleInfo = matcher.group(1); + String statusInfo = matcher.group(2); + String chocolateAmount = matcher.group(3); + Misc.addChatMessage(Text.literal(styleInfo + statusInfo + " " + formattedName + " " + chocolateAmount)); + formattedName = ""; + return true; + } + + return false; + + }); + + } + +} @@ -0,0 +1,64 @@ +package blade.addon.features.other; + +import blade.addon.utils.Misc; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.function.Supplier; + +public class InventoryButton { + + private static final Identifier BUTTON_TEXTURE = Identifier.ofVanilla("widget/button"); + private static final int SIZE = 18; + private static final ArrayList<InventoryButton> inventoryButtons = new ArrayList<>(); + + private final int x; + private final int y; + private final int index; + private final Supplier<String> command; + + public InventoryButton(int x, int y, Supplier<String> command) { + this.x = x; + this.y = y; + this.command = command; + inventoryButtons.add(this); + this.index = inventoryButtons.size(); + } + + public void render(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + String str = command.get(); + if (str == null ||str.isEmpty()) return; + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, BUTTON_TEXTURE, x, y, SIZE, SIZE); + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + int center = textRenderer.getWidth("" + index); + context.drawText(textRenderer, "" + index, x + (SIZE - center) / 2 + 1, y + (SIZE - textRenderer.fontHeight) / 2 + 1, 0xffffffff, true); + } + + public void onClick(double mouseX, double mouseY, int button) { + String str = command.get(); + if (str == null ||str.isEmpty()) return; + Misc.executeCommand(str); + } + + public boolean inBounds(double mouseX, double mouseY) { + return mouseX >= x && mouseX <= x + SIZE && mouseY >= y && mouseY <= y + SIZE; + } + + public static void parseClicks(double mouseX, double mouseY, int button) { + for (InventoryButton inventoryButton : inventoryButtons) { + if (inventoryButton.inBounds(mouseX, mouseY)) { + inventoryButton.onClick(mouseX, mouseY, button); + } + } + } + + public static void renderAll(DrawContext context, int mouseX, int mouseY, float deltaTicks) { + for (InventoryButton button : inventoryButtons) { + button.render(context, mouseX, mouseY, deltaTicks); + } + } +} @@ -45,10 +45,12 @@ public class PracticeSS { private static final CopyOnWriteArrayList<BlockPos> buttons = new CopyOnWriteArrayList<>(); private static BlockPos startPos = null; + private static Direction direction = null; - private static final long SKIP_TIME = 500; - private static final int LAST_SHOWN_DURATION = 11; - private static final int UNLUCKY_DURATION = 35; + private static final long SKIP_TIME_MS = 500; + private static final int LAST_SHOWN_DURATION = 9; + private static final int UNLUCKY_DURATION = 36; + private static final int START_WAIT_DURATION = 6; private static boolean started = false; private static boolean showingPattern = false; @@ -57,6 +59,7 @@ public class PracticeSS { private static int endIndex = 4; private static int ticksLeft = 0; + private static int totalTicks = 0; private static long startTime = 0; @@ -68,8 +71,6 @@ public class PracticeSS { private static boolean wasLuckyButton = false; private static int ticksSinceLuckyButton = 0; - private static Direction direction = null; - public static void init() { Events.ON_BLOCK_INTERACTION.register((BlockHitResult result, ItemStack item) -> { @@ -83,53 +84,11 @@ public class PracticeSS { if (!isValidBlock(block)) return false; if (isStartButton(pos)) { - if (started && ExtraOptions.autoSkip) { - start(world, state, pos); - startPos = pos; - } else if (inSkipPhase || System.currentTimeMillis() - skippedTime < SKIP_TIME) { - clicks++; - if (clicks >= 2 && inSkipPhase) { - skipped = true; - skippedTime = System.currentTimeMillis(); - } - } else { - start(world, state, pos); - startPos = pos; - } + parseStartButton(world, state, pos); } if (started && !showingPattern) { - if (currentIndex == 1 && ticksSinceLuckyButton > 0) { - return ExtraOptions.blockUnluckyButtonClick; - } - - BlockPos nextButton = buttons.get(currentIndex); - if (samePosition(pos, nextButton)) { - currentIndex++; - - if (currentIndex == 5) { - if (ExtraOptions.realisticDelay) { - if (wasLuckyButton) { - PersonalBests.practiseSSRealisticLuckyTime.testNewTime(Text.literal("SS with Realistic Time (Lucky Button) Took: "), startTime); - } else { - PersonalBests.practiseSSRealisticTime.testNewTime(Text.literal("SS with Realistic Time Took: "), startTime); - } - - } else { - if (wasLuckyButton) { - PersonalBests.practiseSSLuckyTime.testNewTime(Text.literal("SS (Lucky Button) Took: "), startTime); - } else { - PersonalBests.practiseSSTime.testNewTime(Text.literal("SS Took: "), startTime); - } - - } - - - reset(); - } else if (currentIndex == endIndex) { - incStage(); - } - } + return parseNormalButton(pos); } return false; @@ -144,7 +103,7 @@ public class PracticeSS { } } - if (System.currentTimeMillis() - startTime > SKIP_TIME && inSkipPhase) { + if (System.currentTimeMillis() - startTime > SKIP_TIME_MS && inSkipPhase) { inSkipPhase = false; if (skipped) { @@ -163,6 +122,41 @@ public class PracticeSS { } + private static void parseStartButton(ClientWorld world, BlockState state, BlockPos pos) { + if (started && ExtraOptions.autoSkip) { + start(world, state, pos); + startPos = pos; + } else if (inSkipPhase || System.currentTimeMillis() - skippedTime < SKIP_TIME_MS) { + clicks++; + if (clicks >= 2 && inSkipPhase) { + skipped = true; + skippedTime = System.currentTimeMillis(); + } + } else { + start(world, state, pos); + startPos = pos; + } + } + + private static boolean parseNormalButton(BlockPos pos) { + if (currentIndex == 1 && ticksSinceLuckyButton > 0) { + return ExtraOptions.blockUnluckyButtonClick; + } + + BlockPos nextButton = buttons.get(currentIndex); + if (samePosition(pos, nextButton)) { + currentIndex++; + + if (currentIndex == 5) { + recordTime(); + } else if (currentIndex == endIndex) { + incStage(); + } + } + + return false; + } + private static void start(ClientWorld world, BlockState state, BlockPos pos) { reset(); direction = state.get(Properties.HORIZONTAL_FACING); @@ -247,6 +241,7 @@ public class PracticeSS { } private static boolean isStartButton(BlockPos pos) { + if (samePosition(pos, ExtraOptions.startButton)) return true; for (BlockPos startPos : START_POSES) { if (samePosition(pos, startPos)) return true; } @@ -255,9 +250,38 @@ public class PracticeSS { } private static boolean samePosition(BlockPos pos1, BlockPos pos2) { + if (pos1 == null || pos2 == null) return false; return pos1.getX() == pos2.getX() && pos1.getY() == pos2.getY() && pos1.getZ() == pos2.getZ(); } + private static void recordTime() { + if (ExtraOptions.realisticDelay) { + if (ExtraOptions.includeLuckyButton) { + if (wasLuckyButton) { + PersonalBests.practiseSSRealisticTime.testNewTime(Text.literal("SS with Realistic Time (Lucky Button) Took: "), startTime); + } else { + PersonalBests.practiseSSRealisticUnluckyTime.testNewTime(Text.literal("SS with Realistic Time Took: "), startTime); + } + } else { + PersonalBests.practiseSSRealisticTime.testNewTime(Text.literal("SS with Realistic Time Took: "), startTime); + } + + } else { + if (ExtraOptions.includeLuckyButton) { + if (wasLuckyButton) { + PersonalBests.practiseSSTime.testNewTime(Text.literal("SS (Lucky Button) Took: "), startTime); + } else { + PersonalBests.practiseSSUnluckyTime.testNewTime(Text.literal("SS Time Took: "), startTime); + } + } else { + PersonalBests.practiseSSTime.testNewTime(Text.literal("SS Took: "), startTime); + } + + } + + reset(); + } + private static void reset() { started = false; showingPattern = false; @@ -267,6 +291,7 @@ public class PracticeSS { ticksSinceLuckyButton = 0; wasLuckyButton = false; direction = null; + totalTicks = 0; } private static int getColor(int index) { @@ -289,7 +314,14 @@ public class PracticeSS { endIndex = stage; currentIndex = 0; - ticksLeft = getDelay() * endIndex + (ExtraOptions.realisticDelay ? stage != 2 ? LAST_SHOWN_DURATION : 4 : 0); + totalTicks = getDelay() * endIndex; + if (ExtraOptions.realisticDelay) { + totalTicks += LAST_SHOWN_DURATION; + if (stage != 2) { + totalTicks += START_WAIT_DURATION; + } + } + ticksLeft = totalTicks; showingPattern = true; } @@ -325,9 +357,11 @@ public class PracticeSS { if (showingPattern) { - int lastIndex = getLastDisplayIndex(); - renderButtons(matrixStack, buffer, 0, lastIndex); - renderBackground(matrixStack, buffer, lastIndex - 1); + if (!ExtraOptions.realisticDelay || totalTicks - ticksLeft > START_WAIT_DURATION || endIndex != 2) { + int lastIndex = getLastDisplayIndex(); + renderButtons(matrixStack, buffer, 0, lastIndex); + renderBackground(matrixStack, buffer, lastIndex - 1); + } } else { renderButtons(matrixStack, buffer, currentIndex, endIndex); } @@ -1,6 +1,7 @@ package blade.addon.features.other; import blade.addon.utils.Constants; +import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -23,16 +24,24 @@ public class RagDisplay { public static void init() { Events.ON_SOUND.register((soundEvent, volume, pitch) -> { - if (!ExtraOptions.enableRagaxeDisplay) return; - if (soundEvent != SOUND) return; - if (volume != 1 && pitch != 1.4920635223388672) return; + if (!ExtraOptions.enableRagaxeDisplay && !ExtraOptions.useCustomRagSound) return false; + if (soundEvent != SOUND) return false; + if (volume != 1 && pitch != 1.4920635223388672) return false; ClientPlayerEntity player = MinecraftClient.getInstance().player; - if (player == null) return; + if (player == null) return false; - if (player.getMainHandStack().getName().getString().contains("Ragnarock")) { + if (!player.getMainHandStack().getName().getString().contains("Ragnarock")) return false; + + if (ExtraOptions.enableRagaxeDisplay) { tick = TOTAL_TICKS; } + + if (ExtraOptions.useCustom …… diff 过长已截断 …… |
fixed small logic error with block unlucky button click查看变更src/main/java/blade/addon/features/other/PracticeSS.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -100,7 +100,7 @@ public class PracticeSS { if (started && !showingPattern) { if (currentIndex == 1 && ticksSinceLuckyButton > 0) { - return !ExtraOptions.blockUnluckyButtonClick; + return ExtraOptions.blockUnluckyButtonClick; } BlockPos nextButton = buttons.get(currentIndex); |
- added location notifier - added star count - add protect item /ba protectitem (unsure how good it is inside dungeons) - added pbs - added toggle scrollwheel for hotbar - fixed waypoints not saving if placed or removed by clicking on a block - added kicked timer - added pre4 completion notification - added hide titles on pre4 dev - added pillar explode timer - added storm crushed notification - added melody warning notification (like the valley one) - added ragnarock display - added leap notification - added an ss practice mode - added hide blaze nametags查看变更gradle.properties | 4 +-
src/main/java/blade/addon/Bladeaddons.java | 26 +++-
src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 44 +++----
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 5 +-
src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 54 +++++++-
src/main/java/blade/addon/features/dungeon/f7/DragSpawnTimer.java | 4 +-
src/main/java/blade/addon/features/dungeon/f7/LeapNotification.java | 102 +++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/LocationNotifier.java | 61 +++++++++
src/main/java/blade/addon/features/dungeon/f7/MelodyWarning.java | 84 +++++++++++++
src/main/java/blade/addon/features/dungeon/f7/PillarExplode.java | 65 ++++++++++
src/main/java/blade/addon/features/dungeon/f7/Pre4Notifier.java | 57 +++++++++
src/main/java/blade/addon/features/dungeon/f7/PredevTimer.java | 51 ++++++++
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 125 ++++++++++++++++---
src/main/java/blade/addon/features/{dungeon => highlight}/MobHighlight.java | 6 +-
src/main/java/blade/addon/features/item/ItemRarity.java | 4 +-
src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 18 +--
src/main/java/blade/addon/features/item/ProtectItem.java | 150 ++++++++++++++++++++++
src/main/java/blade/addon/features/item/ProtectedItemHolder.java | 14 +++
src/main/java/blade/addon/features/item/StarCountHighlight.java | 45 +++++++
src/main/java/blade/addon/features/item/StarCountHolder.java | 15 +++
src/main/java/blade/addon/features/other/KickedTimer.java | 45 +++++++
src/main/java/blade/addon/features/other/PracticeSS.java | 390 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/other/RagDisplay.java | 53 ++++++++
src/main/java/blade/addon/mixin/BlockEntityRenderMixin.java | 2 +-
src/main/java/blade/addon/mixin/ClientPlayerEntityMixin.java | 28 +++++
src/main/java/blade/addon/mixin/EntityRendererMixin.java | 24 ++++
src/main/java/blade/addon/mixin/HandledScreenMixin.java | 56 ++++++++-
src/main/java/blade/addon/mixin/InGameHudMixin.java | 21 +++-
src/main/java/blade/addon/mixin/ItemStackMixin.java | 48 +++++++-
src/main/java/blade/addon/mixin/MinecraftClientMixin.java | 8 +-
src/main/java/blade/addon/mixin/MouseMixin.java | 19 +++
src/main/java/blade/addon/mixin/NetworkMixin.java | 61 ++++++++-
src/main/java/blade/addon/mixin/PlayerEntityMixin.java | 23 ++++
src/main/java/blade/addon/mixin/ServerTickMixin.java | 1 -
src/main/java/blade/addon/utils/Commands.java | 19 ++-
src/main/java/blade/addon/utils/Constants.java | 1 +
src/main/java/blade/addon/utils/Debug.java | 20 ++-
src/main/java/blade/addon/utils/Keybinds.java | 27 ++++
src/main/java/blade/addon/utils/Location.java | 12 ++
src/main/java/blade/addon/utils/Misc.java | 10 ++
src/main/java/blade/addon/utils/Scheduler.java | 7 +-
src/main/java/blade/addon/utils/config/Config.java | 51 +++++++-
src/main/java/blade/addon/utils/config/FolderUtility.java | 32 +++++
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 18 ++-
src/main/java/blade/addon/utils/config/components/Components.java | 38 +++++-
src/main/java/blade/addon/utils/config/values/Dungeons.java | 6 +
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 39 ++++++
src/main/java/blade/addon/utils/config/values/Floor7.java | 45 +++++++
src/main/java/blade/addon/utils/detection/Detection.java | 17 +++
src/main/java/blade/addon/utils/detection/PlayerDataHolder.java | 11 ++
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 54 +++++++-
src/main/java/blade/addon/utils/dungeon/Phase.java | 7 ++
src/main/java/blade/addon/utils/dungeon/Section.java | 34 ++---
src/main/java/blade/addon/utils/events/CustomEvents.java | 43 +++++++
src/main/java/blade/addon/utils/events/Events.java | 13 +-
src/main/java/blade/addon/utils/events/interfaces/{EntityTrackEvent.java => EntityEvent.java} | 4 +-
src/main/java/blade/addon/utils/events/interfaces/PartyMessageEvent.java | 7 ++
src/main/java/blade/addon/utils/events/interfaces/PlaySoundEvent.java | 7 ++
src/main/java/blade/addon/utils/events/interfaces/SectionEvent.java | 5 +
src/main/java/blade/addon/utils/events/interfaces/TerminalEvent.java | 5 +
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 2 +
src/main/java/blade/addon/utils/times/PersonalBest.java | 60 +++++++++
src/main/java/blade/addon/utils/times/PersonalBests.java | 61 +++++++++
src/main/resources/assets/blade-addons/textures/gui/sprites/lock.png | Bin 0 -> 852 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/crow.png | Bin 0 -> 3882 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/rose-dragon.png | Bin 0 -> 4333 bytes
src/main/resources/blade-addons.mixins.json | 4 +
67 files changed, 2249 insertions(+), 123 deletions(-)@@ -13,12 +13,12 @@ loader_version=0.17.3 loom_version=1.13-SNAPSHOT # Mod Properties -mod_version=2.2.4 +mod_version=2.2.5 maven_group=blade.addon archives_base_name=blade-addons # Dependencies fabric_version=0.136.0+1.21.8 -practical_config=963fde881f048a8ffdcb1468ba076a7985d135c1 +practical_config=1.3.5 modmenu_version = 15.0.0 hypixel_api_version = 1.0.1 \ No newline at end of file @@ -1,6 +1,5 @@ package blade.addon; -import blade.addon.features.other.DianaNotifier; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; import blade.addon.features.dungeon.DeathTickTimer; @@ -10,7 +9,6 @@ import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.ItemHighlight; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.LeapMessage; -import blade.addon.features.dungeon.MobHighlight; import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.BossWaypoints; @@ -19,10 +17,21 @@ import blade.addon.features.dungeon.f7.DistanceToLedge; import blade.addon.features.dungeon.f7.DragSpawnTimer; import blade.addon.features.dungeon.f7.GoldorTickTimer; import blade.addon.features.dungeon.f7.InvincibilityTimer; +import blade.addon.features.dungeon.f7.LeapNotification; +import blade.addon.features.dungeon.f7.LocationNotifier; +import blade.addon.features.dungeon.f7.MelodyWarning; +import blade.addon.features.dungeon.f7.PillarExplode; import blade.addon.features.dungeon.f7.PositionMessages; +import blade.addon.features.dungeon.f7.Pre4Notifier; +import blade.addon.features.dungeon.f7.PredevTimer; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; import blade.addon.features.dungeon.f7.TermStartTimer; +import blade.addon.features.highlight.MobHighlight; +import blade.addon.features.other.DianaNotifier; +import blade.addon.features.other.KickedTimer; +import blade.addon.features.other.PracticeSS; +import blade.addon.features.other.RagDisplay; import blade.addon.features.other.SelectedPet; import blade.addon.utils.Commands; import blade.addon.utils.Debug; @@ -30,18 +39,22 @@ import blade.addon.utils.Keybinds; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; import blade.addon.utils.config.Config; +import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.components.Components; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; +import blade.addon.utils.events.CustomEvents; import net.fabricmc.api.ModInitializer; public class Bladeaddons implements ModInitializer { @Override public void onInitialize() { + FolderUtility.init(); Components.init(); Config.manager.load(); Keybinds.init(); + CustomEvents.init(); Commands.init(); Debug.init(); Location.init(); @@ -73,5 +86,14 @@ public class Bladeaddons implements ModInitializer { DianaNotifier.init(); DragSpawnTimer.init(); SelectedPet.init(); + LocationNotifier.init(); + PredevTimer.init(); + KickedTimer.init(); + Pre4Notifier.init(); + PillarExplode.init(); + MelodyWarning.init(); + RagDisplay.init(); + LeapNotification.init(); + PracticeSS.init(); } } \ No newline at end of file @@ -8,6 +8,7 @@ import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.ChatHud; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import java.util.HashMap; import java.util.regex.Matcher; @@ -15,51 +16,38 @@ import java.util.regex.Pattern; public class AutoRequeue { - private static final Pattern PATTERN = Pattern.compile("^§9Party §8>"); private static final Pattern DT_PATTERN = Pattern.compile("!dt"); private static final Pattern UNDT_PATTERN = Pattern.compile("!undt"); private static final Pattern LEFT_PATTERN = Pattern.compile("has left the party.$"); - private static final int MESSAGE_OFFSET = 2; - - private static final HashMap<String, Text> playerHashMap = new HashMap<>(); + private static final HashMap<String, String> playerHashMap = new HashMap<>(); private static boolean someoneLeft = false; public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() && !Dungeons.enableAutoRequeue) return; - String string = message.getString(); - Matcher matcher = LEFT_PATTERN.matcher(string); - if (matcher.find()) { - someoneLeft = true; - return; - } - - matcher = PATTERN.matcher(string); - - if (!matcher.find()) return; - - int startOfMessage = string.indexOf(":"); - - if (startOfMessage == -1 || startOfMessage + MESSAGE_OFFSET >= string.length()) return; - - String realMessage = string.substring(startOfMessage + MESSAGE_OFFSET); - String username = string.substring(0, startOfMessage - MESSAGE_OFFSET); - + Events.ON_PARTY_MESSAGE.register((username, message) -> { if (playerHashMap.containsKey(username)) { - matcher = UNDT_PATTERN.matcher(realMessage); + Matcher matcher = UNDT_PATTERN.matcher(message); if (matcher.find()) { playerHashMap.remove(username); + Misc.addChatMessage(Text.literal("Downtime removed").formatted(Formatting.GREEN)); } } else { - matcher = DT_PATTERN.matcher(realMessage); + Matcher matcher = DT_PATTERN.matcher(message); if (matcher.find()) { playerHashMap.put(username, message); + Misc.addChatMessage(Text.literal("Downtime added").formatted(Formatting.GREEN)); } } - + }); + ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + if (!Location.inDungeon() && !Dungeons.enableAutoRequeue) return; + String string = message.getString(); + Matcher matcher = LEFT_PATTERN.matcher(string); + if (matcher.find()) { + someoneLeft = true; + } }); Events.ON_RUN_END.register(() -> { @@ -70,7 +58,7 @@ public class AutoRequeue { } else { Misc.addChatMessage(Text.literal("Downtime reasons:")); ChatHud chathud = MinecraftClient.getInstance().inGameHud.getChatHud(); - playerHashMap.forEach((name, text) -> chathud.addMessage(text)); + playerHashMap.forEach((name, string) -> chathud.addMessage(Text.literal(name + "> " + string))); } @@ -1,9 +1,9 @@ package blade.addon.features.dungeon.f7; -import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.Waypoint; +import blade.addon.utils.config.FolderUtility; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderLayers; @@ -36,7 +36,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class BossWaypoints { - private static final String filePath = "./config/" + Constants.NAMESPACE + "-waypoints.json"; + private static final String filePath = FolderUtility.OLD_PATH + FolderUtility.WAYPOINTS_NAME; private static final String WAYPOINTS_NAME = "waypoints"; public static final CopyOnWriteArrayList<Waypoint> waypoints = new CopyOnWriteArrayList<>(); @@ -134,6 +134,7 @@ public class BossWaypoints { waypoints.remove(waypoint); } + save(); return ActionResult.PASS; } @@ -2,13 +2,17 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.decoration.EndCrystalEntity; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -19,6 +23,10 @@ public class CrystalSpawn { private static final Pattern PATTERN_1 = Pattern.compile("^\\[BOSS] Maxor: THAT BEAM! IT HURTS! IT HURTS!!$"); private static final Pattern PATTERN_2 = Pattern.compile("^\\[BOSS] Maxor: YOU TRICKED ME!$"); + private static final Pattern RELIC_PICK_UP = Pattern.compile("(\\w+) picked up an Energy Crystal!$"); + + private static long pickupTime = 0; + private static boolean pickedUp = false; private static final int TICK_SPAWN = 34; private static int tick = 0; @@ -29,28 +37,62 @@ public class CrystalSpawn { if (!Location.inDungeon() || !Phase.inP1() || !Floor7.enableCrystalSpawnTime) return; Matcher matcher = PATTERN_1.matcher(text.getString()); - if (!matcher.find()) { - matcher = PATTERN_2.matcher(text.getString()); + if (matcher.find()) { + tick = TICK_SPAWN; + return; + } - if (!matcher.find()) return; + matcher = PATTERN_2.matcher(text.getString()); + if (matcher.find()) { + tick = TICK_SPAWN; + return; } - tick = TICK_SPAWN; - }); + matcher = RELIC_PICK_UP.matcher(text.getString()); + if (matcher.find()) { + String name = matcher.group(1); + if (Misc.isClientPlayer(name)) { + pickupTime = System.currentTimeMillis(); + pickedUp = true; + } + } + }); Events.ON_SERVER_TICK.register(() -> tick = Math.max(tick - 1, 0)); Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { tick = 0; + pickedUp = false; } }); + Events.ON_ENTITY_SPAWNED.register((entity, world) -> { + if (!pickedUp || !Location.inDungeon() || !Floor7.enableCrystalSpawnTime || !Phase.inP1()) return; + if (entity instanceof EndCrystalEntity crystal) { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return; + + double px = player.getX(); + double cx = crystal.getX(); + double pz = player.getZ(); + double cz = crystal.getZ(); + + double distance = Misc.getDistance(px, pz, cx, cz); + + if (distance < 5 && crystal.getY() == 224.375) { + PersonalBests.crystalTime.testNewTime(Text.literal("§aCrystal placed in "), pickupTime); + pickedUp = false; + } + + } + + }); } public static boolean display() { - return tick > 0 && Location.inDungeon() && Floor7.enableCrystalSpawnTime; + return tick > 0 && Location.inDungeon() && Floor7.enableCrystalSpawnTime; } public static void render(HUDComponent component, DrawContext context) { @@ -59,7 +59,7 @@ public class DragSpawnTimer { public static void init() { Events.ON_PARTICLE.register((x, y, z, effect) -> { - if (effect.getType() != ParticleTypes.FLAME) return; + if (effect.getType() != ParticleTypes.ENCHANT) return; Dragon detectedDragon = getDragon(x, y, z); if (detectedDragon == Dragon.NONE) return; @@ -77,7 +77,7 @@ public class DragSpawnTimer { } else if (detectedDragon != currentDragon && !hasDoneSplit) { currentDragon = getPrio(detectedDragon, currentDragon); prevDragon = currentDragon; - dupeTick = DUPE_DELAY + 50; + dupeTick = DUPE_DELAY * 2; hasDoneSplit = true; } }); @@ -0,0 +1,102 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.detection.Detection; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.text.Text; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +/** + * Ported from valley with minimal changes + */ + +public class LeapNotification { + + private static final Box[] REGIONS = { + new Box(90, 106, 50, 111, 145, 123), + new Box(17, 106, 121, 108, 145, 143), + new Box(-2, 106, 51, 20, 145, 142), + new Box(-1, 26, 29, 191, 145, 58), + new Box(3, 5, 0, 128, 48, 140) + }; + + private static final Box EE2_BOX = new Box(57, 108, 130, 59, 110, 132); + private static final Box HEE2_BOX = new Box(59, 132, 138, 62, 133, 140); + private static final Box EE3_BOX = new Box(1, 108, 103, 3, 110, 105); + private static final Box CORE_BOX = new Box(53.5, 114, 49.5, 55.5, 116, 51.5); + private static final Box RELIC_BOX = new Box(51.5, 3, 73.5, 57.5, 8, 79.5); + + private static int count = 0; + private static int currentSpot = 0; + private static boolean inBounds = false; + + public static void init() { + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (!Floor7.leapNotifications || !Phase.isInFloor7() || !Location.inDungeon() || !Phase.inBoss()) { + inBounds = false; + return; + } + + ClientPlayerEntity player = client.player; + ClientWorld world = client.world; + + if (player == null || world == null) return; + currentSpot = getSpot(player); + if (currentSpot < 2) { + count = 0; + inBounds = false; + return; + } else { + inBounds = true; + } + Box box = REGIONS[currentSpot - 1]; + List<Entity> entities = world.getOtherEntities(player, box); + int currentCount = 0; + for (Entity entity : entities) { + if (Detection.isARealPlayer(entity)) { + currentCount++; + } + } + + count = currentCount; + }); + } + + private static int getSpot(ClientPlayerEntity player) { + Vec3d pos = player.getPos(); + if (HEE2_BOX.contains(pos)) return 2; + if (EE2_BOX.contains(pos)) return 2; + else if (EE3_BOX.contains(pos)) return 3; + else if (CORE_BOX.contains(pos)) return 4; + else if (RELIC_BOX.contains(pos) && !Phase.inP5()) return 5; + else return 0; + } + + public static boolean display() { + return Floor7.leapNotifications && inBounds; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + String start; + if (currentSpot == 3) start = (count > 2 ? "§9" : "§4"); + else start = (count > 3 ? "§9" : "§4"); + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(start + count + "§9/4 Players Leaped"), x, y, component.getWidth()); + + } +} @@ -0,0 +1,61 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Location; +import blade.addon.utils.Scheduler; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.sound.SoundEvent; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LocationNotifier { + + private static final Pattern PATTERN = Pattern.compile("^(At |Inside )"); + + private static Text notification = Text.literal("Username is At Location!").formatted(Formatting.GOLD); + private static int ticks = 0; + + public static void init() { + Events.ON_PARTY_MESSAGE.register((username, message) -> { + if (!Floor7.displayLocationNotification || !Location.inDungeon()) return; + Matcher matcher = PATTERN.matcher(message); + if (!matcher.find()) return; + String action = matcher.group(1); + + String screenNotification = (username + " is " + action + message.substring(action.length()) + "!").replaceAll("§.", ""); + startNotification(screenNotification); + }); + + ClientTickEvents.END_CLIENT_TICK.register(client -> ticks = Math.max(ticks - 1, 0)); + } + + public static void startNotification(String message) { + notification = Text.literal(message).formatted(Formatting.GOLD); + ticks = Floor7.notificationDuration; + + for (int i = 0; i < Floor7.notificationRepetitions; i++) { + SoundEvent event = SoundEvent.of(Identifier.of(Floor7.notificationSound)); + Scheduler.scheduleSound(event, Floor7.notificationVolume, Floor7.notificationPitch, i + 1); + } + } + + public static boolean display() { + return ticks > 0 && Floor7.displayLocationNotification; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, notification, x, y, component.getWidth()); + } +} @@ -0,0 +1,84 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; + +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MelodyWarning { + + private static final Pattern PATTERN = Pattern.compile("(\\d+)%"); + + private static final CopyOnWriteArrayList<String> names = new CopyOnWriteArrayList<>(); + + private static boolean melodyStarted = false; + private static String name; + private static int furthestProgress = 0; + + public static void init() { + Events.ON_PARTY_MESSAGE.register((username, message) -> { + if (!Floor7.notifiyMelody) return; + if (!Location.inDungeon() || !Phase.inTerminals()) return; + + Matcher matcher = PATTERN.matcher(message); + if (matcher.find()) { + int progress = Integer.parseInt(matcher.group(1)); + if (progress > furthestProgress) { + melodyStarted = true; + name = username; + furthestProgress = progress; + if (!names.contains(username)) { + names.add(username); + } + } + } + }); + + Events.ON_TERMINAL.register((username, objective) -> { + if (names.contains(username) && objective.equals("terminal")) { + reset(); + } + }); + + Events.ON_SECTION_CHANGE.register(MelodyWarning::reset); + + Events.ON_LOCATION_CHANGE.register(newLocation -> { + if (Location.inDungeon()) { + reset(); + } + }); + } + + private static void reset() { + names.clear(); + furthestProgress = 0; + name = ""; + melodyStarted = false; + } + + public static boolean display() { + return melodyStarted && Floor7.notifiyMelody; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + DungeonClass dungeonClass = DungeonClass.getClass(name); + int num = Math.min(furthestProgress / 25, 3); + Text text = Text.literal("§5§l" + (dungeonClass != null ? dungeonClass.name() : name != null? name: "Someone") + " §r§dhas melody! " + num + "/4"); + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, text, x, y, component.getWidth()); + } + +} @@ -0,0 +1,65 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.Scheduler; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +public class PillarExplode { + + private static final int TOTAL_TICKS = 20; + private static int tick = 0; + + public static void init() { + Events.ON_GAME_MESSAGE.register(text -> { + if (!Floor7.notifyStormCrush && !Floor7.timePillarExplosion) return; + if (!Location.inDungeon() || !Phase.inP2()) return; + + String string = text.getString(); + if (string == null) return; + + if (string.equals("[BOSS] Storm: Oof") ||string.equals("[BOSS] Storm: Ouch, that hurt!")) { + tick = TOTAL_TICKS; + Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); + } + }); + + Events.ON_SERVER_TICK.register(() -> tick = Math.max(tick - 1, 0)); + } + + public static boolean displayTimer() { + return Floor7.notifyStormCrush && tick > 0; + } + + public static void renderTimer(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + Formatting formatting = (tick < 6? Formatting.GREEN: Formatting.RED); + + double num = tick * Constants.TICK_DURATION; + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num).formatted(formatting)), x, y, component.getWidth()); + + } + + public static boolean display() { + return Floor7.timePillarExplosion && tick > 0; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal("§6||| §bStorm crushed! §6|||"), x, y, component.getWidth()); + + } +} @@ -0,0 +1,57 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Scheduler; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; + +public class Pre4Notifier { + + private static final long TOTAL_DURATION = 1500; + + private static long completedTime = 0; + private static boolean showNotification = false; + + + public static void init() { + Events.ON_TERMINAL.register((name, objective) -> { + if (!Floor7.notifyPre4Completion) return; + + if (objective.equals("device") && atDev()) { + completedTime = System.currentTimeMillis(); + showNotification = true; + Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 1, 1); + } + }); + } + + private static boolean atDev() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return false; + return (player.getX() >= 63 && player.getX() <= 64 && player.getY() == 127 && player.getZ() >= 35 && player.getZ() <= 36); + } + + public static boolean disableTitles() { + return Floor7.disableTitlesAtPre4 && atDev() && Phase.inTerminals(); + } + + public static boolean display() { + return showNotification; + } + + public static void render(HUDComponent component, DrawContext context) { + if (System.currentTimeMillis() - completedTime >= TOTAL_DURATION) showNotification = false; + + int x = component.getScaledX(); + int y = component.getScaledY(); + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal("§aDevice Completed!"), x, y, component.getWidth()); + } +} @@ -0,0 +1,51 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; +import blade.addon.utils.times.PersonalBests; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.text.Text; + +public class PredevTimer { + + private static long bossEnterTime = 0; + private static boolean at3rdDev = false; + private static boolean enteredBoss = false; + + public static void init() { + + Events.ON_PHASE_CHANGE.register(() -> { + if (Phase.inP1()) { + bossEnterTime = System.currentTimeMillis(); + at3rdDev = false; + enteredBoss = true; + } + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> enteredBoss = false); + + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (!enteredBoss || at3rdDev || (!Floor7.predevForAll && !DungeonClass.isClass(DungeonClass.HEALER))) return; + ClientPlayerEntity player = client.player; + if (player == null) return; + if (Misc.getDistance(player.getX(), player.getZ(), 1, 77) <= 3) { + at3rdDev = true; + } + }); + + Events.ON_LEAP.register(message -> { + if (at3rdDev && enteredBoss && (DungeonClass.isClass(DungeonClass.HEALER) || Floor7.predevForAll)) { + PersonalBests.predevTime.testNewTime(Text.literal("§aPredev completed in "), bossEnterTime); + at3rdDev = false; + enteredBoss = false; + } + }); + + } + + +} @@ -8,6 +8,7 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.times.PersonalBests; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; @@ -19,6 +20,10 @@ import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.decoration.ArmorStandEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; @@ -31,18 +36,21 @@ import java.util.regex.Pattern; public class RelicTimer { enum Relic { - GREEN(new Box(49, 7, 44, 50, 8, 45), 0xff55ff55), - RED(new Box(51, 7, 42, 52, 8, 43), 0xffff5555), - PURPLE(new Box(54, 7, 41, 55, 8, 42), 0xffff55ff), - ORANGE(new Box(57, 7, 42, 58, 8, 43), 0xffffaa00), - BLUE(new Box(59, 7, 44, 60, 8, 45), 0xff55ffff); + GREEN(new Box(49, 7, 44, 50, 8, 45), 0xff55ff55, "§cRed"), + RED(new Box(51, 7, 42, 52, 8, 43), 0xffff5555, "§aGreen"), + PURPLE(new Box(54, 7, 41, 55, 8, 42), 0xffff55ff, "§5Purple"), + ORANGE(new Box(57, 7, 42, 58, 8, 43), 0xffffaa00, "§6Orange"), + BLUE(new Box(59, 7, 44, 60, 8, 45), 0xff55ffff, "§bBlue"); final Box box; final int color; + final String name; + long placedTime = 0; - Relic(Box box, int color) { + Relic(Box box, int color, String name) { this.box = box; this.color = color; + this.name = name; } } @@ -51,27 +59,39 @@ public class RelicTimer { private static final Pattern PATTERN = Pattern.compile("^(.+) picked the Corrupted (Red|Purple|Orange|Green|Blue) Relic!$"); - private static long pickupTime; + private static long phaseStartTime; private static Relic pickedupRelic = null; private static int tick = Floor7.relicSpawnTicks; + //only here to test the relic progress bar + private static boolean forceGUI = false; + public static void init() { Events.ON_SERVER_TICK.register(() -> { - if (!Location.inDungeon() || !Phase.inP5()) return; - tick = Math.max(tick - 1, 0); + if (!forceGUI) { + if (!Location.inDungeon() || !Phase.inP5()) return; + } + tick = Math.max(tick - 1, -1); + + if (tick == -1) { + forceGUI = false; + } }); Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { tick = Floor7.relicSpawnTicks; pickedupRelic = null; + for (Relic relic : Relic.values()) { + relic.placedTime = 0; + } } }); Events.ON_PHASE_CHANGE.register(() -> { if (Phase.inP5()) { - pickupTime = System.currentTimeMillis(); + phaseStartTime = System.currentTimeMillis(); } }); @@ -92,6 +112,37 @@ public class RelicTimer { } }); + Events.ON_ENTITY_SPAWNED.register((entity, world) -> { + if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes) return; + + + if (entity instanceof ArmorStandEntity armorStand) { + ItemStack helmet = armorStand.getEquippedStack(EquipmentSlot.HEAD); + Text text = helmet.getName(); + if (text == null) return; + String name = text.getString(); + if (!name.contains("Relic")) return; + + double ax = armorStand.getX(); + double az = armorStand.getZ(); + + for (Relic relic : Relic.values()) { + if (Misc.getDistance(relic.box.maxX, ax, relic.box.maxZ, az) < 1) { + relic.placedTime = System.currentTimeMillis(); + break; + } + } + + if (allRelicsPlaced()) { + for (Relic relic : Relic.values()) { + long time = relic.placedTime - phaseStartTime; + Misc.addChatMessage(Text.literal(relic.name + " &aRelic placed in &e" + Constants.DECIMAL_FORMAT.format(time) + "s&a.")); + } + } + } + + }); + Events.ON_BLOCK_INTERACTION.register((result, itemStack) -> { if (!Location.inDungeon() || !Phase.inP5() || pickedupRelic == null) return false; BlockPos pos = result.getBlockPos(); @@ -102,11 +153,18 @@ public class RelicTimer { if (pos.getX() == pickedupRelic.box.minX && (pos.getY() == pickedupRelic.box.minY || pos.getY() == pickedupRelic.box.minY - 1) && pos.getZ() == pickedupRelic.box.minZ) { if (Floor7.enableRelicPlaceTime) { - double diff = (System.currentTimeMillis() - pickupTime) / 1000.0; - Misc.addChatMessage(Text.literal("The ").formatted(Formatting.GREEN) + MutableText text = Text.literal("The ").formatted(Formatting.GREEN) .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) - .append(" relic was placed in ").formatted(Formatting.GREEN) - .append(Text.literal(Constants.DECIMAL_FORMAT.format(diff) + "s.").formatted(Formatting.YELLOW))); + .append(" relic was placed in ").formatted(Formatting.GREEN); + + switch (pickedupRelic) { + case RED -> PersonalBests.redRelicTime.testNewTime(text, phaseStartTime); + case ORANGE -> PersonalBests.orangeRelicTime.testNewTime(text, phaseStartTime); + case BLUE -> PersonalBests.blueRelicTime.testNewTime(text, phaseStartTime); + case GREEN -> PersonalBests.greenRelicTime.testNewTime(text, phaseStartTime); + case PURPLE -> PersonalBests.purpleRelicTime.testNewTime(text, phaseStartTime); + } + } pickedupRelic = null; } else { @@ -144,8 +202,20 @@ public class RelicTimer { } + public static void testRelicGUI() { + forceGUI = true; + tick = Floor7.relicSpawnTicks; + } + + private static boolean allRelicsPlaced() { + for (Relic relic : Relic.values()) { + if (relic.placedTime == 0) return false; + } + return true; + } + public static boolean display() { - return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > 0; + return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && !Floor7.replaceWithProgressBar; } public static void render(HUDComponent component, DrawContext context) { @@ -159,4 +229,29 @@ public class RelicTimer { RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); } + + public static boolean displayProgressBar() { + if (forceGUI) return true; + return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > -1 && Floor7.replaceWithProgressBar; + } + + public static void renderProgressBar(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + //from valleyAddons + StringBuilder message = new StringBuilder("§8["); + + int diff = Floor7.relicSpawnTicks - tick; + for (int i = 0; i < Floor7.relicSpawnTicks; i++) { + if (i < diff) { + if (tick < 2) message.append("§a|"); + else message.append("§c|"); + } else message.append("§7|"); + } + message.append("§8]"); + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(message.toString()), x, y, component.getWidth(), 0xffffffff); + + } } @@ -1,4 +1,4 @@ -package blade.addon.features.dungeon; +package blade.addon.features.highlight; import blade.addon.utils.Location; import blade.addon.utils.Misc; @@ -337,8 +337,8 @@ public class MobHighlight { private static boolean isMiniBoss(Entity entity) { if (entity instanceof PlayerEntity player) { - ItemStack leggings = player.getInventory().getStack(39); - int id = Item.getRawId(leggings.getItem()); + ItemStack helmet = player.getInventory().getStack(39); + int id = Item.getRawId(helmet.getItem()); return id == DIAMOND_HELMET_ID || id == PLAYER_HEAD_ID; } @@ -2,7 +2,7 @@ package blade.addon.features.item; public enum ItemRarity { NONE(0x0), - COMMON(0x88ffffff), + COMMON(0x99dddddd), UNCOMMON(0x8842ab42), RARE(0x884c4cd0), EPIC(0x88671067), @@ -14,7 +14,7 @@ public enum ItemRarity { ULTIMATE(0x88a10202), ADMIN(0x88aa0000); - private int color; + private final int color; public int getColor() { return this.color; @@ -31,18 +31,18 @@ public class ItemRarityHighlight { List<Text> lines = lore.lines(); if (lines.isEmpty()) return ItemRarity.NONE; - Text line = lines.getLast(); - if (line == null) return ItemRarity.NONE; - String string = line.getString(); - String[] rarityStrings = string.split(" "); + for (Text line: lines.reversed()) { + String string = line.getString(); + String[] rarityStrings = string.split(" "); - for (String testString: rarityStrings) { - try { - ItemRarity rarity = ItemRarity.valueOf(testString); - return rarity; - } catch (IllegalArgumentException ignored) { + for (String testString: rarityStrings) { + try { + ItemRarity rarity = ItemRarity.valueOf(testString); + return rarity; + } catch (IllegalArgumentException ignored) { + } } } return ItemRarity.NONE; @@ -0,0 +1,150 @@ +package blade.addon.features.item; + +import blade.addon.utils.Constants; +import blade.addon.utils.Debug; +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.config.FolderUtility; +import blade.addon.utils.dungeon.Phase; +import config.practical.manager.ConfigManager; +import config.practical.manager.ConfigValue; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.collection.DefaultedList; + +import java.util.HashSet; +import java.util.List; + +public class ProtectItem { + + private static final Identifier SPRITE = Identifier.of(Constants.NAMESPACE, "lock"); + + public static final ConfigManager itemManager = new ConfigManager(FolderUtility.OLD_PATH + FolderUtility.PROTECT_ITEMS_NAME, + List.of(ProtectItem.class)); + + @ConfigValue + public static HashSet<String> protectedItems = new HashSet<>(); + + public static void protectSelected() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) { + Debug.LOGGER.warn("Cant find client player to protect item"); + return; + } + + ItemStack item = player.getInventory().getSelectedStack(); + String uuid = getUuid(item); + if (uuid == null) { + Misc.addChatMessage(Text.literal("Cant protect this item, it does not have a uuid")); + return; + } + ProtectedItemHolder holder = (ProtectedItemHolder) (Object) item; + if (protectedItems.contains(uuid)) { + protectedItems.remove(uuid); + holder.blade_addons$setProtected(false); + Misc.addChatMessage(Text.literal("Item ").append(item.getName()).append(" is NOT protected anymore")); + } else { + protectedItems.add(uuid); + holder.blade_addons$setProtected(true); + Misc.addChatMessage(Text.literal("Item ").append(item.getName()).append(" is protected")); + } + + itemManager.save(); + } + + public static boolean protect(ItemStack stack) { + + String uuid = getUuid(stack); + + //TODO: add smth for non uuid items + if (uuid == null) { + return false; + } + + return protectedItems.contains(uuid); + } + + public static String getUuid(ItemStack item) { + NbtComponent nbt = item.get(DataComponentTypes.CUSTOM_DATA); + if (nbt == null) return null; + + NbtCompound compound = nbt.copyNbt(); + + return compound.getString("uuid", null); + } + + public static void draw(DrawContext context, ItemStack stack, int x, int y) { + ProtectedItemHolder holder = (ProtectedItemHolder) (Object) stack; + assert holder != null; + + if (!holder.blade_addons$hasScannedProtection()) { + String uuid = getUuid(stack); + if (uuid == null) return; + holder.blade_addons$setProtected(protectedItems.contains(uuid)); + } + + if (!holder.blade_addons$isProtected()) return; + + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, SPRITE, x, y, 16, 16, 0x99ffffff); + } + + public static boolean blockGUI(HandledScreen screen, ItemStack item) { + if (!protect(item)) return false; + + + Text title = screen.getTitle(); + if (title == null) return false; + String name = title.getString(); + + if (name.contains("Auction")) { + Misc.addChatMessage(Text.literal("Protected ").append(item.getName()).append(" From being auctioned")); + return true; + } + + if (name.contains("Salvage")) { + Misc.addChatMessage(Text.literal("Protected ").append(item.getName()).append(" From being salvaged")); + return true; + } + + ScreenHandler handler = screen.getScreenHandler(); + DefaultedList<Slot> slots = handler.slots; + + if (slots.size() > 49) { + Slot slot = slots.get(49); + ItemStack stack = slot.getStack(); + Text itemName = stack.getName(); + if (itemName != null && itemName.getString().contains("Sell Item")) { + Misc.addChatMessage(Text.literal("Protected ").append(item.getName()).append(" From being sold")); + return true; + } + + slot = slots.get(4); + stack = slot.getStack(); + itemName = stack.getName(); + if (itemName != null && itemName.getString().contains("⇦ Your stuff")) { + Misc.addChatMessage(Text.literal("Protected ").append(item.getName()).append(" From being traded")); + return true; + } + + } + + System.out.println(slots.size()); + + return false; + } + + public static boolean isInADungeon() { + return Location.inDungeon() && Phase.runStarted() && !Phase.runOver() && Location.hasRecivedLocation(); + } +} @@ -0,0 +1,14 @@ +package blade.addon.features.item; + +public interface ProtectedItemHolder { + + boolean scannedProtected = false; + + boolean isItemProtected = false; + + boolean blade_addons$hasScannedProtection(); + + void blade_addons$setProtected(boolean value); + + boolean blade_addons$isProtected(); +} @@ -0,0 +1,45 @@ +package blade.addon.features.item; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; + +public class StarCountHighlight { + + public static void draw(DrawContext context, ItemStack stack, int x, int y) { + StarCountHolder holder = (StarCountHolder) (Object) stack; + assert holder != null; + + if (!holder.blade_addons$hasScannedStars()) { + holder.blade_addons$setStarCount(getStarCount(stack)); + } + + int starCount = holder.blade_addons$getStarCount(); + if (starCount == 0) return; + + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + String starText = "" + starCount; + context.drawText(MinecraftClient.getInstance().textRenderer, starText, x + 17 - textRenderer.getWidth(starText), y + 18 - textRenderer.fontHeight, 0xffffffff, true); + } + + public static int getStarCount(ItemStack item) { + NbtComponent nbt = item.get(DataComponentTypes.CUSTOM_DATA); + if (nbt == null) return 0; + + NbtCompound compound = nbt.copyNbt(); + + int starCount = compound.getInt("upgrade_level", 0); + if (starCount == 0) { + //the old star system they used to use. + // Some items don't have the new data so this is a fallback + starCount = compound.getInt("dungeon_item_level", 0); + } + + return starCount; + } +} @@ -0,0 +1,15 @@ +package blade.addon.features.item; + +public interface StarCountHolder { + + boolean scannedStars = false; + + int starCount = 0; + + boolean blade_addons$hasScannedStars(); + + void blade_addons$setStarCount(int count); + + int blade_addons$getStarCount(); +} + @@ -0,0 +1,45 @@ +package blade.addon.features.other; + +import blade.addon.utils.Constants; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +public class KickedTimer { + + private static boolean isKicked = false; + private static long kickedTime = 0; + + public static void init() { + Events.ON_GAME_MESSAGE.register(text -> { + if (!ExtraOptions.enableKickedTimer) return; + String string = text.getString(); + if (string == null) return; + + if (string.contains("You were kicked while joining that server!")) { + kickedTime = System.currentTimeMillis(); + isKicked = true; + + } + }); + } + + public static boolean display() { + return isKicked; + } + + public static void render(HUDComponent component, DrawContext context) { + long diff = System.currentTimeMillis() - kickedTime; + if (diff > 60 * 1000) isKicked = false; + + int x = component.getScaledX(); + int y = component.getScaledY(); + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, "§5Time kicked: §f" + Constants.DECIMAL_FORMAT.format(Math.min(diff / 1000.0, 60)) + "s", x, y, component.getWidth()); + + } + +} @@ -0,0 +1,390 @@ +package blade.addon.features.other; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderUtils; +import blade.addon.utils.times.PersonalBests; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.item.ItemStack; +import net.minecraft.state.property.Properties; +import net.minecraft.text.Text; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class PracticeSS { + + private static final Box NORTH_BOX = new Box(5 / 16.0, 6 / 16.0, 14 / 16.0, 11 / 16.0, 10 / 16.0, 1); + private static final Box SOUTH_BOX = new Box(5 / 16.0, 6 / 16.0, 0, 11 / 16.0, 10 / 16.0, 2 / 16.0); + private static final Box EAST_BOX = new Box(0, 6 / 16.0, 5 / 16.0, 2 / 16.0, 10 / 16.0, 11 / 16.0); + private static final Box WEST_BOX = new Box(14 / 16.0, 6 / 16.0, 5 / 16.0, 1, 10 / 16.0, 11 / 16.0); + + private static final List<BlockPos> START_POSES = List.of(new BlockPos(-17, 5, -26), new BlockPos(-37, 5, -26), new BlockPos(-51, 5, -26), new BlockPos(-74, 5, -26), new BlockPos(7, 5, -26), new BlockPos(-60, 5, -26), new BlockPos(-6, 5, -26), new BlockPos(-28, 5, -26)); + private static final CopyOnWriteArrayList<BlockPos> buttons = new CopyOnWriteArrayList<>(); + + private static BlockPos startPos = null; + + private static final long SKIP_TIME = 500; + private static final int LAST_SHOWN_DURATION = 11; + private static final int UNLUCKY_DURATION = 35; + + private static boolean started = false; + private static boolean showingPattern = false; + + private static int currentIndex = 0; + private static int endIndex = 4; + + private static int ticksLeft = 0; + + private static long startTime = 0; + + private static boolean inSkipPhase = false; + private static int clicks = 0; + private static long skippedTime = 0; + private static boolean skipped = false; + + private static boolean wasLuckyButton = false; + private static int ticksSinceLuckyButton = 0; + + private static Direction direction = null; + + public static void init() { + + Events.ON_BLOCK_INTERACTION.register((BlockHitResult result, ItemStack item) -> { + if (!ExtraOptions.practiceSSAnywhere && !Location.in(Location.PRIVATE_ISLAND)) return false; + ClientWorld world = MinecraftClient.getInstance().world; + if (world == null) return false; + BlockPos pos = result.getBlockPos(); + BlockState state = world.getBlockState(pos); + Block block = state.getBlock(); + + if ( …… diff 过长已截断 …… |
- added color option for storm ticktimer - added hide status effects overlay - changed width and color of termsplits - added a combine ticktimers and combine notifications - added block incorrect relic placement - added drag spawn timer - added disable glowing - added chat prefix - added selected pet in menu and as a hud element - fixed hide after leap hiding mobs that are player entities查看变更gradle.properties | 4 +-
src/main/java/blade/addon/Bladeaddons.java | 6 ++-
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 3 ++
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 8 +---
src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 7 ++-
src/main/java/blade/addon/features/dungeon/f7/DragSpawnTimer.java | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/features/dungeon/f7/InvincibilityTimer.java | 23 ++-------
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 64 ++++++++++---------------
src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 15 +++---
src/main/java/blade/addon/features/item/ItemRarityDrawer.java | 23 ---------
src/main/java/blade/addon/features/item/ItemRarityHighlight.java | 50 +++++++++++++++++++
src/main/java/blade/addon/features/item/PetHolder.java | 14 ++++++
src/main/java/blade/addon/features/item/SelectedPetHighlight.java | 39 +++++++++++++++
src/main/java/blade/addon/features/{ => other}/DianaNotifier.java | 7 ++-
src/main/java/blade/addon/features/other/SelectedPet.java | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/mixin/EntityMixin.java | 19 ++++++++
src/main/java/blade/addon/mixin/HandledScreenMixin.java | 25 ++++++++--
src/main/java/blade/addon/mixin/InGameHudMixin.java | 11 ++++-
src/main/java/blade/addon/mixin/ItemStackMixin.java | 25 +++++++++-
src/main/java/blade/addon/mixin/MinecraftClientMixin.java | 34 +++++++++++++
src/main/java/blade/addon/mixin/NetworkMixin.java | 8 ++++
src/main/java/blade/addon/mixin/ServerTickMixin.java | 12 +++++
src/main/java/blade/addon/mixin/StatusEffectsDisplayMixin.java | 27 +++++++++++
src/main/java/blade/addon/utils/Debug.java | 17 +++++--
src/main/java/blade/addon/utils/JsonUtility.java | 4 +-
src/main/java/blade/addon/utils/Keybinds.java | 5 +-
src/main/java/blade/addon/utils/Misc.java | 48 +++++++------------
src/main/java/blade/addon/utils/Scheduler.java | 21 +++-----
src/main/java/blade/addon/utils/config/Config.java | 46 ++++++++++++------
src/main/java/blade/addon/utils/config/components/CombinedScreenNotifications.java | 37 ++++++++++++++
src/main/java/blade/addon/utils/config/components/CombinedTickTimer.java | 53 ++++++++++++++++++++
src/main/java/blade/addon/utils/config/components/Components.java | 32 ++++++++++---
src/main/java/blade/addon/utils/config/values/Dungeons.java | 3 ++
src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 18 +++++++
src/main/java/blade/addon/utils/config/values/Floor7.java | 19 ++++++++
src/main/java/blade/addon/utils/dungeon/DungeonClass.java | 9 ++++
src/main/java/blade/addon/utils/dungeon/Phase.java | 9 ++--
src/main/java/blade/addon/utils/dungeon/Section.java | 16 ++++---
src/main/java/blade/addon/utils/dungeon/Split.java | 6 +--
src/main/java/blade/addon/utils/events/CancelableEvent.java | 6 +++
src/main/java/blade/addon/utils/events/CancelableEventHandler.java | 22 +++++++++
src/main/java/blade/addon/utils/events/Events.java | 8 ++++
src/main/java/blade/addon/utils/events/interfaces/BlockInteractionEvent.java | 10 ++++
src/main/java/blade/addon/utils/events/interfaces/ParticleEvent.java | 8 ++++
src/main/java/blade/addon/utils/events/interfaces/PetEvent.java | 5 ++
src/main/java/blade/addon/utils/rendering/RenderUtils.java | 4 ++
src/main/resources/assets/blade-addons/Blade-addons-picture.png | Bin 0 -> 128048 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/ammonite.png | Bin 0 -> 2186 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/ankylosaurus.png | Bin 0 -> 1963 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/armadillo.png | Bin 0 -> 2150 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/baby-yeti.png | Bin 0 -> 2828 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/bal.png | Bin 0 -> 2081 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/bat.png | Bin 0 -> 1811 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/bee.png | Bin 0 -> 1294 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/bingo.png | Bin 0 -> 2216 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/black-cat.png | Bin 0 -> 2195 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/blaze.png | Bin 0 -> 2261 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/blue-whale.png | Bin 0 -> 1596 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/chicken.png | Bin 0 -> 2978 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/dolphin.png | Bin 0 -> 982 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/eerie.png | Bin 0 -> 4595 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/elephant.png | Bin 0 -> 2483 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/ender-dragon.png | Bin 0 -> 2433 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/enderman.png | Bin 0 -> 1233 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/endermite.png | Bin 0 -> 1942 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/flying-fish-mythic.png | Bin 0 -> 2278 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/frog.png | Bin 0 -> 2334 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/ghoul.png | Bin 0 -> 2901 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/giraffe.png | Bin 0 -> 1954 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/glacite-golem.png | Bin 0 -> 1875 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/goblin.png | Bin 0 -> 2060 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/golden-dragon.png | Bin 0 -> 2196 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/golem.png | Bin 0 -> 2383 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/grandma-wolf.png | Bin 0 -> 2288 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/griffin.png | Bin 0 -> 3047 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/guardian.png | Bin 0 -> 3303 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/hedgehog.png | Bin 0 -> 2261 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/hermit-crab.png | Bin 0 -> 1902 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/horse.png | Bin 0 -> 1948 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/hound.png | Bin 0 -> 2085 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/jade-dragon.png | Bin 0 -> 1927 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/jellyfish.png | Bin 0 -> 2762 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/jerry.png | Bin 0 -> 1187 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/kuudra.png | Bin 0 -> 2412 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/lion.png | Bin 0 -> 2602 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/magma-cube.png | Bin 0 -> 1751 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/mammoth.png | Bin 0 -> 2020 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/megalodon.png | Bin 0 -> 1715 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/mithril-golem.png | Bin 0 -> 2526 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/mole.png | Bin 0 -> 1706 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/monkey.png | Bin 0 -> 2333 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/mooshroom-cow.png | Bin 0 -> 1486 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/mosquito.png | Bin 0 -> 3047 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/ocelot.png | Bin 0 -> 2545 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/owl.png | Bin 0 -> 1719 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/parrot.png | Bin 0 -> 1969 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/penguin.png | Bin 0 -> 1429 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/phoenix.png | Bin 0 -> 2721 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/pig.png | Bin 0 -> 2606 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/pigman.png | Bin 0 -> 2906 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/rabbit.png | Bin 0 -> 1570 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/rat.png | Bin 0 -> 2144 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/reindeer.png | Bin 0 -> 1864 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/rift-ferret.png | Bin 0 -> 1596 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/rock.png | Bin 0 -> 2648 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/scatha.png | Bin 0 -> 2116 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/sheep.png | Bin 0 -> 2685 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/silverfish.png | Bin 0 -> 2157 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/skeleton-horse.png | Bin 0 -> 1833 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/skeleton.png | Bin 0 -> 1563 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/slug.png | Bin 0 -> 1712 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/snail.png | Bin 0 -> 2088 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/snowman.png | Bin 0 -> 1694 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/spider.png | Bin 0 -> 2354 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/spinosaurus.png | Bin 0 -> 1990 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/spirit.png | Bin 0 -> 2199 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/squid.png | Bin 0 -> 1684 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/subzero-wisp.png | Bin 0 -> 2503 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/t-rex.png | Bin 0 -> 2024 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/tarantula.png | Bin 0 -> 2406 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/tiger.png | Bin 0 -> 2505 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/turtle.png | Bin 0 -> 3282 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/wither-skeleton.png | Bin 0 -> 1811 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/wolf.png | Bin 0 -> 2590 bytes
src/main/resources/assets/blade-addons/textures/gui/sprites/pets/zombie.png | Bin 0 -> 1931 bytes
src/main/resources/blade-addons.mixins.json | 5 +-
126 files changed, 960 insertions(+), 201 deletions(-)@@ -13,12 +13,12 @@ loader_version=0.17.3 loom_version=1.13-SNAPSHOT # Mod Properties -mod_version=2.2.3 +mod_version=2.2.4 maven_group=blade.addon archives_base_name=blade-addons # Dependencies fabric_version=0.136.0+1.21.8 -practical_config=1.3.3 +practical_config=963fde881f048a8ffdcb1468ba076a7985d135c1 modmenu_version = 15.0.0 hypixel_api_version = 1.0.1 \ No newline at end of file @@ -1,6 +1,6 @@ package blade.addon; -import blade.addon.features.DianaNotifier; +import blade.addon.features.other.DianaNotifier; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; import blade.addon.features.dungeon.DeathTickTimer; @@ -16,12 +16,14 @@ import blade.addon.features.dungeon.WarpCooldown; import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.CrystalSpawn; import blade.addon.features.dungeon.f7.DistanceToLedge; +import blade.addon.features.dungeon.f7.DragSpawnTimer; import blade.addon.features.dungeon.f7.GoldorTickTimer; import blade.addon.features.dungeon.f7.InvincibilityTimer; import blade.addon.features.dungeon.f7.PositionMessages; import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; import blade.addon.features.dungeon.f7.TermStartTimer; +import blade.addon.features.other.SelectedPet; import blade.addon.utils.Commands; import blade.addon.utils.Debug; import blade.addon.utils.Keybinds; @@ -69,5 +71,7 @@ public class Bladeaddons implements ModInitializer { ItemHighlight.init(); BossWaypoints.init(); DianaNotifier.init(); + DragSpawnTimer.init(); + SelectedPet.init(); } } \ No newline at end of file @@ -47,6 +47,9 @@ public class HidePlayers { public static boolean shouldHidePlayers(PlayerEntity player) { if (!Location.inDungeon()) return false; + //in case it's a mob instead of a player + if (player.getName().getString().contains(" ")) return false; + if (testHideAtLeap()) { return true; } @@ -22,7 +22,6 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; -import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; @@ -37,9 +36,6 @@ import java.util.concurrent.CopyOnWriteArrayList; public class BossWaypoints { - private static final Text ON = Text.literal("ON").formatted(Formatting.GREEN); - private static final Text OFF = Text.literal("OFF").formatted(Formatting.RED); - private static final String filePath = "./config/" + Constants.NAMESPACE + "-waypoints.json"; private static final String WAYPOINTS_NAME = "waypoints"; @@ -69,12 +65,12 @@ public class BossWaypoints { public static void setPlace(boolean shouldPlace) { place = shouldPlace; - Misc.addChatMessage(Text.literal("Edit mode: ").append(place ? ON : OFF)); + Misc.addChatMessage(Text.literal("Edit mode: ").append(Misc.getStatusText(place))); } public static void setIgnoreBoss(boolean shouldIgnoreBoss) { ignoreBoss = shouldIgnoreBoss; - Misc.addChatMessage(Text.literal("Ignore boss: ").append(ignoreBoss ? ON : OFF)); + Misc.addChatMessage(Text.literal("Ignore boss: ").append(Misc.getStatusText(ignoreBoss))); } public static void togglePlace() { @@ -7,7 +7,6 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -26,12 +25,12 @@ public class CrystalSpawn { public static void init() { - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + Events.ON_GAME_MESSAGE.register(text -> { if (!Location.inDungeon() || !Phase.inP1() || !Floor7.enableCrystalSpawnTime) return; - Matcher matcher = PATTERN_1.matcher(message.getString()); + Matcher matcher = PATTERN_1.matcher(text.getString()); if (!matcher.find()) { - matcher = PATTERN_2.matcher(message.getString()); + matcher = PATTERN_2.matcher(text.getString()); if (!matcher.find()) return; } @@ -0,0 +1,167 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Constants; +import blade.addon.utils.Scheduler; +import blade.addon.utils.config.values.Floor7; +import blade.addon.utils.dungeon.DungeonClass; +import blade.addon.utils.events.Events; +import blade.addon.utils.rendering.RenderUtils; +import config.practical.hud.HUDComponent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.sound.SoundEvents; + +public class DragSpawnTimer { + + enum Dragon { + PURPLE(0xffff55ff, 0, 4), + BLUE(0xff55ffff, 1, 3), + RED(0xffff5555, 2, 2), + GREEN(0xff55ff55, 3, 1), + ORANGE(0xffffaa00, 4, 0), + NONE(0xffffffff, 99, 99); + + final int color; + final int archPrio; + final int bersPrio; + + Dragon(int color, int archPrio, int bersPrio) { + this.color = color; + this.archPrio = archPrio; + this.bersPrio = bersPrio; + } + } + + public enum Team { + ARCHER_TEAM("Archer team"), BERS_TEAM("Bers team"); + + private final String label; + + Team(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } + } + + private static final int SPAWN_DURATION = 100; + private static final int DUPE_DELAY = 130; + + private static Dragon currentDragon = Dragon.NONE; + private static Dragon prevDragon = Dragon.NONE; + private static boolean hasDoneSplit = false; + private static int tick = 0; + private static int dupeTick = 0; + + public static void init() { + Events.ON_PARTICLE.register((x, y, z, effect) -> { + if (effect.getType() != ParticleTypes.FLAME) return; + Dragon detectedDragon = getDragon(x, y, z); + + if (detectedDragon == Dragon.NONE) return; + + //the dupe check is to stop purple from just breaking it when it spawns + if (currentDragon == Dragon.NONE) { + if ((prevDragon == detectedDragon && dupeTick > 0)) return; + currentDragon = detectedDragon; + prevDragon = currentDragon; + dupeTick = DUPE_DELAY; + tick = SPAWN_DURATION; + if (Floor7.sendSoundOnDragSpawn) { + Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 0.75f, 1); + } + } else if (detectedDragon != currentDragon && !hasDoneSplit) { + currentDragon = getPrio(detectedDragon, currentDragon); + prevDragon = currentDragon; + dupeTick = DUPE_DELAY + 50; + hasDoneSplit = true; + } + }); + + Events.ON_SERVER_TICK.register(() -> { + tick = Math.max(tick - 1, 0); + dupeTick = Math.max(dupeTick - 1, 0); + if (dupeTick == 0 && prevDragon != Dragon.NONE) { + prevDragon = Dragon.NONE; + } + + if (tick == 0 && currentDragon != Dragon.NONE) { + currentDragon = Dragon.NONE; + } + }); + + Events.ON_LOCATION_CHANGE.register(newLocation -> reset()); + } + + private static void reset() { + hasDoneSplit = false; + currentDragon = Dragon.NONE; + prevDragon = Dragon.NONE; + tick = 0; + } + + //checks are from valley addons + private static Dragon getDragon(double x, double y, double z) { + // check if correct height + if (y >= 14 && y <= 19) { + // check if red/green + if (x >= 27 && x <= 32) { + // check if red + if (z == 59) { + return Dragon.RED; + // check if green + } else if (z == 94) { + return Dragon.GREEN; + } + // check if blue/orange + } else if (x >= 79 && x <= 85) { + // check if blue + if (z == 94) { + return Dragon.BLUE; + // check if orange + } else if (z == 56) { + return Dragon.ORANGE; + } + // check if purple + } else if (x == 56) { + return Dragon.PURPLE; + } + } + return Dragon.NONE; + } + + private static Dragon getPrio(Dragon dragon1, Dragon dragon2) { + if (DungeonClass.isArchTeam()) { + if (dragon1.archPrio < dragon2.archPrio) { + return dragon1; + } else { + return dragon2; + } + } else if (DungeonClass.isBersTeam()) { + if (dragon1.bersPrio < dragon2.bersPrio) { + return dragon1; + } else { + return dragon2; + } + } + return Dragon.NONE; + } + + public static boolean display() { + return Floor7.dragSpawnTimers && currentDragon != Dragon.NONE; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + double num = tick * Constants.TICK_DURATION; + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth(), currentDragon.color); + + } +} @@ -39,9 +39,6 @@ public class InvincibilityTimer { private static final Pattern BONZO_ON_HEAD_PATTERN = Pattern.compile("Bonzo's Mask"); private static final Pattern SPIRIT_ON_HEAD_PATTERN = Pattern.compile("Spirit Mask"); - private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You summoned your (\\D+)( ✦)?!$"); - private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl [0-9]+] (\\D+)( ✦)?! VIEW RULE$"); - //in ticks private static final int BONZO_MASK_COOLDOWN = 180 * 20; private static final int SPIRIT_MASK_COOLDOWN = 30 * 20; @@ -72,7 +69,6 @@ public class InvincibilityTimer { public static void init() { Events.ON_SERVER_TICK.register(InvincibilityTimer::tick); - ClientReceiveMessageEvents.GAME.register(InvincibilityTimer::detectPet); Events.ON_SLOT_CHANGE.register(InvincibilityTimer::detectHelmet); Events.ON_LOCATION_CHANGE.register(newLocation -> { @@ -83,6 +79,9 @@ public class InvincibilityTimer { } }); + Events.ON_PET.register(name -> phoenixOn = name.equals("Phoenix")); + + ClientReceiveMessageEvents.GAME.register((message, overlay) -> { if (Location.inDungeon()) { parseMessage(message); @@ -96,22 +95,6 @@ public class InvincibilityTimer { phoenixTicks = Math.max(0, phoenixTicks - 1); } - private static void detectPet(Text message, boolean overlay) { - if (!Location.inDungeon()) return; - String string = message.getString().replaceAll("§.", ""); - Matcher matcher = MANUAL_EQUIP_PET_PATTERN.matcher(string); - if (matcher.find()) { - String petName = matcher.group(1); - phoenixOn = petName.contains("Phoenix"); - } - - matcher = RULE_EQUIP_PET_PATTERN.matcher(string); - if (matcher.find()) { - String petName = matcher.group(1); - phoenixOn = petName.contains("Phoenix"); - } - } - private static void detectHelmet(int slot, ItemStack item) { if (slot != HEAD_SLOT || !Location.inDungeon()) return; Text text = item.getCustomName(); @@ -11,10 +11,6 @@ import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; -import net.fabricmc.fabric.api.event.player.AttackBlockCallback; -import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; @@ -24,7 +20,6 @@ import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexRendering; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; @@ -97,20 +92,30 @@ public class RelicTimer { } }); - AttackBlockCallback.EVENT.register((playerEntity, world, hand, blockPos, direction) -> { - if (world == null) return ActionResult.PASS; - if (!Location.inDungeon() || !Phase.inP5() || pickedupRelic == null) return ActionResult.PASS; - BlockState block = world.getBlockState(blockPos); - onBlockClick(block, blockPos); - return ActionResult.PASS; - }); - - UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> { - if (world == null) return ActionResult.PASS; - if (!Location.inDungeon() || !Phase.inP5() || pickedupRelic == null) return ActionResult.PASS; - BlockState block = world.getBlockState(hitResult.getBlockPos()); - onBlockClick(block, hitResult.getBlockPos()); - return ActionResult.PASS; + Events.ON_BLOCK_INTERACTION.register((result, itemStack) -> { + if (!Location.inDungeon() || !Phase.inP5() || pickedupRelic == null) return false; + BlockPos pos = result.getBlockPos(); + + Text name = itemStack.getCustomName(); + if (name == null) return false; + if (!name.getString().contains("Relic")) return false; + + if (pos.getX() == pickedupRelic.box.minX && (pos.getY() == pickedupRelic.box.minY || pos.getY() == pickedupRelic.box.minY - 1) && pos.getZ() == pickedupRelic.box.minZ) { + if (Floor7.enableRelicPlaceTime) { + double diff = (System.currentTimeMillis() - pickupTime) / 1000.0; + Misc.addChatMessage(Text.literal("The ").formatted(Formatting.GREEN) + .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) + .append(" relic was placed in ").formatted(Formatting.GREEN) + .append(Text.literal(Constants.DECIMAL_FORMAT.format(diff) + "s.").formatted(Formatting.YELLOW))); + } + pickedupRelic = null; + } else { + if (Floor7.blockIncorrectRelicPlace) { + Misc.addChatMessage(Text.literal("incorrect click!")); + return true; + } + } + return false; }); WorldRenderEvents.BEFORE_DEBUG_RENDER.register(worldRenderContext -> { @@ -139,28 +144,11 @@ public class RelicTimer { } - private static void onBlockClick(BlockState block, BlockPos pos) { - if (block.getBlock() != Blocks.ANVIL && block.getBlock() != Blocks.CAULDRON) return; - double distance = pickedupRelic.box.getCenter().distanceTo(pos.toCenterPos()); - if (distance <= 1) { - if (Floor7.enableRelicPlaceTime) { - double diff = (System.currentTimeMillis() - pickupTime) / 1000.0; - Misc.addChatMessage(Text.literal("The ").formatted(Formatting.GREEN) - .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) - .append(" relic was placed in ").formatted(Formatting.GREEN) - .append(Text.literal(Constants.DECIMAL_FORMAT.format(diff) + "s.").formatted(Formatting.YELLOW))); - } - pickedupRelic = null; - } - - - } - public static boolean display() { - return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > 0; + return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > 0; } - public static void render(HUDComponent component, DrawContext context) { + public static void render(HUDComponent component, DrawContext context) { int x = component.getScaledX(); int y = component.getScaledY(); @@ -3,13 +3,13 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; @@ -49,19 +49,22 @@ public class StormTickTimer { } }); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + Events.ON_GAME_MESSAGE.register(text -> { if (!Location.inDungeon() || !Phase.inP2() || !Floor7.enableStormDeathTime) return; - Matcher matcher = PATTERN.matcher(message.getString()); + Matcher matcher = PATTERN.matcher(text.getString()); if (matcher.find()) { deathTime = (tick * Constants.TICK_DURATION); deathStartDisplayTime = System.currentTimeMillis(); - Misc.addChatMessage( + + //prob dosent need to schedule it but threads are scary + Scheduler.scheduleTask(() -> Misc.addChatMessage( Text.literal("Storm died at: ").formatted(Formatting.GREEN) .append(Text.literal(Constants.DECIMAL_FORMAT.format(deathTime) + "s").formatted(Formatting.YELLOW)) .append(Text.literal(".").formatted(Formatting.GREEN)) - ); + ), 1); + } }); @@ -87,7 +90,7 @@ public class StormTickTimer { } - RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth()); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth(), Floor7.stormTickTimerColor); } @@ -1,23 +0,0 @@ -package blade.addon.features.item; - -import blade.addon.utils.Misc; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.item.ItemStack; - -public class ItemRarityDrawer { - - public static void draw(DrawContext context, ItemStack stack, int x, int y) { - ItemRarityHolder holder = (ItemRarityHolder) (Object) stack; - assert holder != null; - - if (!holder.blade_addons$hasScanned()) { - ItemRarity rarity = Misc.getRarity(stack); - holder.blade_addons$setItemRarity(rarity); - } - - if (!holder.blade_addons$hasItemRarity()) return; - - ItemRarity rarity = holder.blade_addons$getItemRarity(); - context.fill(x, y, x + 16, y + 16, rarity.getColor()); - } -} @@ -0,0 +1,50 @@ +package blade.addon.features.item; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import java.util.List; + +public class ItemRarityHighlight { + + public static void draw(DrawContext context, ItemStack stack, int x, int y) { + ItemRarityHolder holder = (ItemRarityHolder) (Object) stack; + assert holder != null; + + if (!holder.blade_addons$hasScanned()) { + ItemRarity rarity = getRarity(stack); + holder.blade_addons$setItemRarity(rarity); + } + + if (!holder.blade_addons$hasItemRarity()) return; + + ItemRarity rarity = holder.blade_addons$getItemRarity(); + context.fill(x, y, x + 16, y + 16, rarity.getColor()); + } + + public static ItemRarity getRarity(ItemStack item) { + LoreComponent lore = item.get(DataComponentTypes.LORE); + if (lore == null) return ItemRarity.NONE; + + List<Text> lines = lore.lines(); + if (lines.isEmpty()) return ItemRarity.NONE; + Text line = lines.getLast(); + + if (line == null) return ItemRarity.NONE; + String string = line.getString(); + String[] rarityStrings = string.split(" "); + + for (String testString: rarityStrings) { + try { + ItemRarity rarity = ItemRarity.valueOf(testString); + return rarity; + } catch (IllegalArgumentException ignored) { + + } + } + return ItemRarity.NONE; + } +} @@ -0,0 +1,14 @@ +package blade.addon.features.item; + +public interface PetHolder { + + boolean selectedPet = false; + boolean scannedPet = false; + + boolean blade_addons$hasScannedPet(); + + void blade_addons$setSelected(boolean selected); + + boolean blade_addons$isSelected(); + +} @@ -0,0 +1,39 @@ +package blade.addon.features.item; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; + +import java.util.List; + +public class SelectedPetHighlight { + + public static void draw(DrawContext context, ItemStack stack, int x, int y) { + PetHolder holder = (PetHolder) (Object) stack; + assert holder != null; + + if (!holder.blade_addons$hasScannedPet()) { + holder.blade_addons$setSelected(isSelected(stack)); + } + + if (!holder.blade_addons$isSelected()) return; + + context.fill(x, y, x + 16, y + 16, 0xffff0000); + } + + public static boolean isSelected(ItemStack item) { + LoreComponent lore = item.get(DataComponentTypes.LORE); + if (lore == null) return false; + + List<Text> lines = lore.lines(); + if (lines.isEmpty()) return false; + + for(Text text: lines) { + if (text == null) continue; + if (text.getString().equals("Click to despawn!")) return true; + } + return false; + } +} @@ -1,5 +1,7 @@ -package blade.addon.features; +package blade.addon.features.other; +import blade.addon.utils.Debug; +import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.Scheduler; import blade.addon.utils.events.Events; @@ -24,6 +26,7 @@ public class DianaNotifier { public static void init() { Events.ON_GAME_MESSAGE.register(message-> { + if (!Location.in(Location.HUB)) return; String string = message.getString(); String lowerCase = string.toLowerCase(); if (!lowerCase.contains("you dug out a")) return; @@ -48,7 +51,7 @@ public class DianaNotifier { Misc.setTitle(Text.literal(name)); ClientPlayerEntity player = client.player; if (player == null) { - Misc.addChatMessage(Text.literal("Player is somehow null")); + Debug.sendDebugMessage(Text.literal("Player is null when checking diana message")); return; } @@ -0,0 +1,159 @@ +package blade.addon.features.other; + +import blade.addon.utils.Constants; +import blade.addon.utils.Debug; +import blade.addon.utils.config.values.ExtraOptions; +import blade.addon.utils.events.Events; +import config.practical.hud.HUDComponent; +import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gl.RenderPipelines; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SelectedPet { + + private static final int COLOR_OFFSET = 2; + + private static final Pattern TAB_PET_PATTERN = Pattern.compile(" \\[Lvl \\d+] (\\D+)"); + private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You (summoned|despawned) your (\\D+)!$"); + private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl [0-9]+] (\\D+)! VIEW RULE$"); + + private static final Text NO_PET = Text.literal("No pet").formatted(Formatting.RED); + private static final String identifierPrefix = "pets/"; + + private static Text currentPetText = NO_PET; + private static String currentPetString = ""; + private static Identifier spriteId = null; + + public static void init() { + ClientReceiveMessageEvents.GAME.register((message, overlay) -> { + String string = message.getString(); + Matcher matcher = MANUAL_EQUIP_PET_PATTERN.matcher(string); + if (matcher.find()) { + + if (matcher.group(1).equals("despawned")) { + despawnPet(); + return; + } + + String name = matcher.group(2).replace(" ✦", ""); + Style style = getStyle(message, name); + summonPet(name, Text.literal(name).setStyle(style)); + return; + } + + matcher = RULE_EQUIP_PET_PATTERN.matcher(string.replaceAll("§.", "")); + if (matcher.find()) { + String name = matcher.group(1).replace(" ✦", ""); + + String textName = name; + int index = string.indexOf(name); + if (index > COLOR_OFFSET) { + textName = string.substring(index - COLOR_OFFSET, index) + textName; + } + + summonPet(name, Text.literal(textName)); + } + }); + + Events.ON_PLAYER_ENTRY.register(receivedEntry -> { + if (receivedEntry == null) return; + Text text = receivedEntry.displayName(); + if (text == null) return; + + String string = text.getString(); + if (string.equals(" No pet selected")) { + despawnPet(); + return; + } + + Matcher matcher = TAB_PET_PATTERN.matcher(string); + if (matcher.find()) { + String petName = matcher.group(1).replace(" ✦", ""); + Style style = getStyle(text, petName); + summonPet(petName, Text.literal(petName).setStyle(style)); + } + }); + } + + private static void despawnPet() { + + if (!currentPetString.isEmpty() && Events.ON_PET.hasListeners()) { + Events.ON_PET.invoke(petEvent -> petEvent.onPet("")); + } + + currentPetText = NO_PET; + currentPetString = ""; + spriteId = null; + + } + + private static void summonPet(String stringName, Text textName) { + if (stringName.equals(currentPetString)) { + return; + } + + currentPetText = textName; + currentPetString = stringName; + + if (Events.ON_PET.hasListeners()) { + Events.ON_PET.invoke(petEvent -> petEvent.onPet(currentPetString)); + } + + updateSprite(stringName); + } + + private static Style getStyle(Text text, String name) { + Style style = Style.EMPTY; + List<Text> lines = text.getSiblings(); + + for (Text line : lines) { + if (line.getString().equals(name)) { + style = line.getStyle(); + } + } + + return style; + } + + private static void updateSprite(String petName) { + if (petName == null) { + spriteId = null; + return; + } + String formattedName = petName.toLowerCase().replace(" ", "-"); + if (Identifier.isNamespaceValid(formattedName)) { + spriteId = Identifier.of(Constants.NAMESPACE, identifierPrefix + formattedName); + } else { + Debug.LOGGER.warn("{} includes invalid chars", formattedName); + } + } + + public static boolean display() { + return ExtraOptions.drawPetHUD; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + if (spriteId != null && ExtraOptions.includePetSprite) { + context.drawGuiTexture(RenderPipelines.GUI_TEXTURED, spriteId, x, y, 16, 16, 0xffffffff); + } + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + + context.drawText(textRenderer, currentPetText, x + (ExtraOptions.includePetSprite? 18: 0), y + component.getHeight() - textRenderer.fontHeight, 0xffffffff, true); + + } + +} @@ -0,0 +1,19 @@ +package blade.addon.mixin; + +import blade.addon.utils.config.values.ExtraOptions; +import net.minecraft.entity.Entity; +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.CallbackInfoReturnable; + +@Mixin(Entity.class) +public class EntityMixin { + + @Inject(method = "isGlowing", at=@At("HEAD"), cancellable = true) + public void isGlowing(CallbackInfoReturnable<Boolean> cir) { + if (ExtraOptions.disableGlowing) { + cir.setReturnValue(false); + } + } +} @@ -1,11 +1,14 @@ package blade.addon.mixin; -import blade.addon.features.item.ItemRarityDrawer; +import blade.addon.features.item.ItemRarityHighlight; +import blade.addon.features.item.SelectedPetHighlight; import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.item.ItemStack; import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -13,13 +16,27 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(HandledScreen.class) public class HandledScreenMixin { - @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) public void drawBackground(DrawContext context, Slot slot, CallbackInfo ci) { - if (!ExtraOptions.itemRarityBackground) return; + int x = slot.x; int y = slot.y; ItemStack stack = slot.getStack(); - ItemRarityDrawer.draw(context, stack, x, y); + + if (ExtraOptions.highlightSelectedPet) { + HandledScreen screen = (HandledScreen) (Object) this; + if (screen instanceof GenericContainerScreen containerScreen) { + Text title = containerScreen.getTitle(); + if (title == null) return; + if (title.getString().equals("Pets")) { + SelectedPetHighlight.draw(context, stack, x, y); + } + + } + } + + if (ExtraOptions.itemRarityBackground) { + ItemRarityHighlight.draw(context, stack, x, y); + } } } @@ -1,6 +1,6 @@ package blade.addon.mixin; -import blade.addon.features.item.ItemRarityDrawer; +import blade.addon.features.item.ItemRarityHighlight; import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; @@ -18,6 +18,13 @@ public class InGameHudMixin { @Inject(method = "renderHotbarItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;III)V")) public void drawItem(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { if (!ExtraOptions.itemRarityBackground) return; - ItemRarityDrawer.draw(context, stack, x, y); + ItemRarityHighlight.draw(context, stack, x, y); } + + @Inject(method = "renderStatusEffectOverlay", at=@At("HEAD"), cancellable = true) + public void renderStatusEffectsOverLay(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { + if (ExtraOptions.hideStatusOverLay) { + ci.cancel(); + } + } } @@ -2,16 +2,23 @@ package blade.addon.mixin; import blade.addon.features.item.ItemRarityHolder; import blade.addon.features.item.ItemRarity; +import blade.addon.features.item.PetHolder; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @Mixin(ItemStack.class) -public class ItemStackMixin implements ItemRarityHolder { +public class ItemStackMixin implements ItemRarityHolder, PetHolder { @Unique private ItemRarity itemRarity = null; + @Unique + boolean selectedPet = false; + + @Unique + boolean scannedPet = false; + @Override public ItemRarity blade_addons$getItemRarity() { @@ -32,4 +39,20 @@ public class ItemStackMixin implements ItemRarityHolder { public boolean blade_addons$hasScanned() { return itemRarity != null; } + + @Override + public boolean blade_addons$hasScannedPet() { + return scannedPet; + } + + @Override + public void blade_addons$setSelected(boolean selected) { + selectedPet = selected; + scannedPet = true; + } + + @Override + public boolean blade_addons$isSelected() { + return selectedPet; + } } @@ -0,0 +1,34 @@ +package blade.addon.mixin; + +import blade.addon.utils.events.Events; +import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.MinecraftClient; +import net.minecraft.item.ItemStack; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class MinecraftClientMixin { + + @Shadow + @Nullable + public HitResult crosshairTarget; + + @Inject(method = "doItemUse", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/item/ItemStack;getCount()I"), cancellable = true) + private void testInteraction(CallbackInfo ci, @Local ItemStack itemStack) { + BlockHitResult blockHitResult = (BlockHitResult) this.crosshairTarget; + + if (blockHitResult == null) return; + if (Events.ON_BLOCK_INTERACTION.test(blockInteractionEvent -> blockInteractionEvent.iteract(blockHitResult, itemStack))) { + ci.cancel(); + } + + + } +} @@ -1,5 +1,8 @@ package blade.addon.mixin; +import blade.addon.utils.Debug; +import blade.addon.utils.Misc; +import blade.addon.utils.Scheduler; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.events.Events; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; @@ -15,6 +18,7 @@ import net.minecraft.network.packet.s2c.play.TeamS2CPacket; import net.minecraft.scoreboard.Team; import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -69,6 +73,10 @@ public class NetworkMixin { if (pitch == 0.0 && volume == 8.0 && event == SoundEvents.ENTITY_ENDERMAN_TELEPORT) { ci.cancel(); } + + if (Debug.sendSound) { + Scheduler.scheduleTask(() -> Misc.addChatMessage(Text.literal("Sound: " + event.id())), 1); + } } } \ No newline at end of file @@ -8,6 +8,8 @@ import net.minecraft.network.ClientConnection; import net.minecraft.network.packet.Packet; import net.minecraft.network.packet.s2c.common.CommonPingS2CPacket; import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; +import net.minecraft.particle.ParticleEffect; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -31,6 +33,16 @@ public class ServerTickMixin { } } + if (packet instanceof ParticleS2CPacket particle) { + double x = particle.getX(); + double y = particle.getY(); + double z = particle.getZ(); + ParticleEffect effect = particle.getParameters(); + if (Events.ON_PARTICLE.hasListeners()) { + Events.ON_PARTICLE.invoke(particleEvent -> particleEvent.onParticle(x, y, z, effect)); + } + } + } @Inject(method = "sendImmediately", at = @At("HEAD")) @@ -0,0 +1,27 @@ +package blade.addon.mixin; + +import blade.addon.utils.config.values.ExtraOptions; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.StatusEffectsDisplay; +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(StatusEffectsDisplay.class) +public class StatusEffectsDisplayMixin { + + @Inject(method = "drawStatusEffects", at=@At("HEAD"), cancellable = true) + public void drawEffects(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { + if (ExtraOptions.hideStatusOverLay) { + ci.cancel(); + } + } + + @Inject(method = "drawStatusEffectTooltip", at=@At("HEAD"), cancellable = true) + public void drawToolTip(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { + if (ExtraOptions.hideStatusOverLay) { + ci.cancel(); + } + } +} @@ -4,10 +4,14 @@ import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.Section; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.minecraft.text.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Debug { + public static final Logger LOGGER = LoggerFactory.getLogger(Constants.NAMESPACE); private static boolean sendDebug = false; + public static boolean sendSound = false; public static void init() { registerCommands(); @@ -22,16 +26,19 @@ public class Debug { Commands.registerDevCommand(ClientCommandManager.literal("toggleSendDebug").executes(context -> { sendDebug = !sendDebug; - Misc.addChatMessage(Text.literal("Send debug: " + sendDebug)); + Misc.addChatMessage(Text.literal("Send debug: ").append(Misc.getStatusText(sendDebug))); return Constants.SUCCESS; })); - } - //TODO: change this to a LOG object - public static void addDebugLog(String message) { - System.out.println("Blade-addons:" + message); + Commands.registerDevCommand(ClientCommandManager.literal("toggleSoundInChat").executes(context -> { + sendSound = !sendSound; + Misc.addChatMessage(Text.literal("Send Sound: ").append(Misc.getStatusText(sendSound))); + return Constants.SUCCESS; + })); } + + public static void sendDebugMessage(Text text) { if (sendDebug) { Misc.addChatMessage(text); @@ -32,7 +32,7 @@ public class JsonUtility { return parseSplits(element); } } catch (IOException e) { - Debug.addDebugLog(e.getMessage()); + Debug.LOGGER.error("Failed to parse a split"); } return new HashMap<>(); @@ -78,7 +78,7 @@ public class JsonUtility { return parsePositonalMessages(element); } } catch (IOException e) { - Debug.addDebugLog(e.getMessage()); + Debug.LOGGER.error("failed to parse positional messages"); } return new ArrayList<>(); @@ -1,7 +1,7 @@ package blade.addon.utils; +import blade.addon.features.item.ItemRarityHighlight; import blade.addon.utils.config.Config; -import blade.addon.utils.dungeon.Phase; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; @@ -11,7 +11,6 @@ import net.minecraft.client.util.InputUtil; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; @@ -66,7 +65,7 @@ public class Keybinds { Misc.addChatMessage(line); } - Misc.addChatMessage(Text.literal("Rarity: " + Misc.getRarity(heldStack).name())); + Misc.addChatMessage(Text.literal("Rarity: " + ItemRarityHighlight.getRarity(heldStack).name())); } } } @@ -1,20 +1,19 @@ package blade.addon.utils; -import blade.addon.features.item.ItemRarity; +import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.LoreComponent; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.text.Text; - -import java.util.List; +import net.minecraft.util.Formatting; public class Misc { public static final MinecraftClient instance = MinecraftClient.getInstance(); + private static final Text ON = Text.literal("ON").formatted(Formatting.GREEN); + private static final Text OFF = Text.literal("OFF").formatted(Formatting.RED); public static boolean isClientPlayer(PlayerEntity entity) { ClientPlayerEntity clientPlayer = instance.player; @@ -22,15 +21,25 @@ public class Misc { return clientPlayer == entity; } + public static boolean isClientPlayer(Entity entity) { + ClientPlayerEntity clientPlayer = instance.player; + if (clientPlayer == null) return false; + return clientPlayer == entity; + } + public static void addChatMessage(Text text) { try { InGameHud gameHud = MinecraftClient.getInstance().inGameHud; - gameHud.getChatHud().addMessage(text); + gameHud.getChatHud( …… diff 过长已截断 …… |
- bumped version查看变更gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) @@ -13,7 +13,7 @@ loader_version=0.17.3 loom_version=1.13-SNAPSHOT # Mod Properties -mod_version=2.2.2 +mod_version=2.2.3 maven_group=blade.addon archives_base_name=blade-addons |
- fixed skined phoenix not working with InvincibilityTimer (hopefully) - "/ba refill" will only refill items that you already have in your inventory - added countdown option for storm - sends split when over in chat - added item rarity background (not finished) - added terminal splits (colors and core split not finished) - added /leaporder for backup mage (hasn't been fully tested)查看变更src/main/java/blade/addon/Bladeaddons.java | 10 +++-- src/main/java/blade/addon/features/dungeon/LeapOrder.java | 103 ++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/InvincibilityTimer.java | 6 +-- src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 13 ++++++ src/main/java/blade/addon/features/item/ItemRarity.java | 26 +++++++++++ src/main/java/blade/addon/features/item/ItemRarityDrawer.java | 23 ++++++++++ src/main/java/blade/addon/features/item/ItemRarityHolder.java | 14 ++++++ src/main/java/blade/addon/mixin/HandledScreenMixin.java | 25 +++++++++++ src/main/java/blade/addon/mixin/InGameHudMixin.java | 23 ++++++++++ src/main/java/blade/addon/mixin/ItemStackMixin.java | 35 +++++++++++++++ src/main/java/blade/addon/utils/Commands.java | 48 +++++++++++++------- src/main/java/blade/addon/utils/Constants.java | 1 + src/main/java/blade/addon/utils/Debug.java | 40 ++++++++++++----- src/main/java/blade/addon/utils/JsonUtility.java | 4 +- src/main/java/blade/addon/utils/Keybinds.java | 39 +++++++++++++++- src/main/java/blade/addon/utils/Location.java | 2 - src/main/java/blade/addon/utils/Misc.java | 37 ++++++++++++++- src/main/java/blade/addon/utils/config/Config.java | 9 +++- src/main/java/blade/addon/utils/config/values/ExtraOptions.java | 3 ++ src/main/java/blade/addon/utils/config/values/Floor7.java | 3 ++ src/main/java/blade/addon/utils/dungeon/FillHelper.java | 37 ++++++++++++++- src/main/java/blade/addon/utils/dungeon/Phase.java | 85 +++++++---------------------------- src/main/java/blade/addon/utils/dungeon/PositionMessage.java | 2 +- src/main/java/blade/addon/utils/dungeon/Section.java | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/resources/blade-addons.mixins.json | 3 ++ src/main/resources/fabric.mod.json | 4 +- 26 files changed, 680 insertions(+), 115 deletions(-) @@ -23,13 +23,15 @@ import blade.addon.features.dungeon.f7.RelicTimer; import blade.addon.features.dungeon.f7.StormTickTimer; import blade.addon.features.dungeon.f7.TermStartTimer; import blade.addon.utils.Commands; +import blade.addon.utils.Debug; import blade.addon.utils.Keybinds; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; -import blade.addon.utils.config.components.Components; import blade.addon.utils.config.Config; +import blade.addon.utils.config.components.Components; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.dungeon.Section; import net.fabricmc.api.ModInitializer; public class Bladeaddons implements ModInitializer { @@ -37,10 +39,12 @@ public class Bladeaddons implements ModInitializer { public void onInitialize() { Components.init(); Config.manager.load(); - Keybinds.register(); - Commands.register(); + Keybinds.init(); + Commands.init(); + Debug.init(); Location.init(); Phase.init(); + Section.init(); DungeonClass.init(); StormTickTimer.init(); GoldorTickTimer.init(); @@ -0,0 +1,103 @@ +package blade.addon.features.dungeon; + +import blade.addon.utils.Misc; +import blade.addon.utils.dungeon.DungeonClass; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.scoreboard.Scoreboard; +import net.minecraft.scoreboard.Team; +import net.minecraft.text.Text; + +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class LeapOrder { + + private static final Pattern PATTERN = Pattern.compile("\\[([TBMAH])] (\\w+) "); + + private static final DungeonClass[] ARCHER_ORDER = {DungeonClass.BERSERK, DungeonClass.HEALER, DungeonClass.MAGE, DungeonClass.TANK}; + private static final DungeonClass[] BERSERK_ORDER = {DungeonClass.ARCHER, DungeonClass.HEALER, DungeonClass.MAGE, DungeonClass.TANK}; + private static final DungeonClass[] MAGE_ORDER = {DungeonClass.ARCHER, DungeonClass.BERSERK, DungeonClass.HEALER, DungeonClass.TANK}; + private static final DungeonClass[] TANK_ORDER = {DungeonClass.TANK, DungeonClass.BERSERK, DungeonClass.HEALER, DungeonClass.MAGE}; + private static final DungeonClass[] HEALER_ORDER = {DungeonClass.ARCHER, DungeonClass.BERSERK, DungeonClass.MAGE, DungeonClass.TANK}; + + private static final DungeonClass[] ALPHABETICAL_ORDER = {DungeonClass.ARCHER, DungeonClass.BERSERK, DungeonClass.HEALER, DungeonClass.MAGE, DungeonClass.TANK}; + + public static void leapOrder(String backupMage, boolean odinOrder) { + + HashMap<DungeonClass, String> classNameMap = new HashMap<>(); + DungeonClass playersClass = null; + + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) { + Misc.addChatMessage(Text.literal("Player is somehow null")); + return; + } + + Scoreboard scoreboard = player.getScoreboard(); + for (Team team : scoreboard.getTeams()) { + String teamStr = team.getPrefix().getString() + team.getSuffix().getString(); + Matcher matcher = PATTERN.matcher(teamStr); + if (matcher.find()) { + DungeonClass dungeonClass = getClass(matcher.group(1)); + String name = matcher.group(2); + if (dungeonClass == null) continue; + + if (name.equalsIgnoreCase(backupMage)) { + dungeonClass = DungeonClass.HEALER; + } + + if (name.equalsIgnoreCase(player.getName().getString())) { + playersClass = dungeonClass; + continue; + } + + classNameMap.put(dungeonClass, name); + } + } + + if (classNameMap.size() != 4 || playersClass == null) { + Misc.addChatMessage(Text.literal("Cant find all players or the players class")); + return; + } + DungeonClass[] order; + if (odinOrder) { + order = getOdinOrder(playersClass); + } else { + order = new DungeonClass[4]; + int index = 0; + for (int i = 0; i < 5; i++) { + if (ALPHABETICAL_ORDER[i] == playersClass) continue; + order[index] = ALPHABETICAL_ORDER[i]; + index++; + } + } + + String leapOrder = "odin leaporder " + classNameMap.get(order[0]) + " " + classNameMap.get(order[1]) + " " + classNameMap.get(order[2]) + " " + classNameMap.get(order[3]); + Misc.addChatMessage(Text.literal("Executing command: " + leapOrder)); + Misc.executeCommand(leapOrder); + } + + private static DungeonClass[] getOdinOrder(DungeonClass playerClass) { + return switch (playerClass) { + case ARCHER -> ARCHER_ORDER; + case BERSERK -> BERSERK_ORDER; + case HEALER -> HEALER_ORDER; + case MAGE -> MAGE_ORDER; + case TANK -> TANK_ORDER; + }; + } + + private static DungeonClass getClass(String string) { + return switch (string) { + case "A" -> DungeonClass.ARCHER; + case "B" -> DungeonClass.BERSERK; + case "H" -> DungeonClass.HEALER; + case "M" -> DungeonClass.MAGE; + case "T" -> DungeonClass.TANK; + default -> null; + }; + } + +} @@ -39,7 +39,7 @@ public class InvincibilityTimer { private static final Pattern BONZO_ON_HEAD_PATTERN = Pattern.compile("Bonzo's Mask"); private static final Pattern SPIRIT_ON_HEAD_PATTERN = Pattern.compile("Spirit Mask"); - private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You summoned your (\\D+)!$"); + private static final Pattern MANUAL_EQUIP_PET_PATTERN = Pattern.compile("^You summoned your (\\D+)( ✦)?!$"); private static final Pattern RULE_EQUIP_PET_PATTERN = Pattern.compile("^Autopet equipped your \\[Lvl [0-9]+] (\\D+)( ✦)?! VIEW RULE$"); //in ticks @@ -102,13 +102,13 @@ public class InvincibilityTimer { Matcher matcher = MANUAL_EQUIP_PET_PATTERN.matcher(string); if (matcher.find()) { String petName = matcher.group(1); - phoenixOn = petName.equals("Phoenix"); + phoenixOn = petName.contains("Phoenix"); } matcher = RULE_EQUIP_PET_PATTERN.matcher(string); if (matcher.find()) { String petName = matcher.group(1); - phoenixOn = petName.equals("Phoenix"); + phoenixOn = petName.contains("Phoenix"); } } @@ -25,6 +25,9 @@ public class StormTickTimer { private static final long DEATH_DISPLAY_DURATION = 2000; private static final int WARN_TICK = 20 * 20; + private static final int CRUSH_TICK = 31 * 20; + private static final int COUNTDOWN_DURATION = 5 * 20; + private static int tick = 0; private static double deathTime = 0; private static long deathStartDisplayTime = 0; @@ -65,6 +68,11 @@ public class StormTickTimer { } public static boolean display() { + if (Floor7.tickDownStormTickTimer) { + double diff = CRUSH_TICK - tick; + if (diff > COUNTDOWN_DURATION || diff < 0) return false; + } + return Floor7.enableStormTickTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead(); } @@ -74,6 +82,11 @@ public class StormTickTimer { double num = tick * Constants.TICK_DURATION; + if (Floor7.tickDownStormTickTimer) { + num = CRUSH_TICK * Constants.TICK_DURATION - num; + + } + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth()); } @@ -0,0 +1,26 @@ +package blade.addon.features.item; + +public enum ItemRarity { + NONE(0x0), + COMMON(0x88ffffff), + UNCOMMON(0x8842ab42), + RARE(0x884c4cd0), + EPIC(0x88671067), + LEGENDARY(0x88cf8d0a), + MYTHIC(0x88ff55ff), + DIVINE(0x884fe4e4), + SPECIAL(0x88ff5555), + VERY_SPECIAL(0x88c44747), + ULTIMATE(0x88a10202), + ADMIN(0x88aa0000); + + private int color; + + public int getColor() { + return this.color; + } + + ItemRarity(int color) { + this.color = color; + } +} @@ -0,0 +1,23 @@ +package blade.addon.features.item; + +import blade.addon.utils.Misc; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.item.ItemStack; + +public class ItemRarityDrawer { + + public static void draw(DrawContext context, ItemStack stack, int x, int y) { + ItemRarityHolder holder = (ItemRarityHolder) (Object) stack; + assert holder != null; + + if (!holder.blade_addons$hasScanned()) { + ItemRarity rarity = Misc.getRarity(stack); + holder.blade_addons$setItemRarity(rarity); + } + + if (!holder.blade_addons$hasItemRarity()) return; + + ItemRarity rarity = holder.blade_addons$getItemRarity(); + context.fill(x, y, x + 16, y + 16, rarity.getColor()); + } +} @@ -0,0 +1,14 @@ +package blade.addon.features.item; + +public interface ItemRarityHolder { + + ItemRarity itemRarity = ItemRarity.NONE; + + ItemRarity blade_addons$getItemRarity(); + + boolean blade_addons$hasItemRarity(); + + void blade_addons$setItemRarity(ItemRarity itemRarity); + + boolean blade_addons$hasScanned(); +} @@ -0,0 +1,25 @@ +package blade.addon.mixin; + +import blade.addon.features.item.ItemRarityDrawer; +import blade.addon.utils.config.values.ExtraOptions; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.slot.Slot; +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(HandledScreen.class) +public class HandledScreenMixin { + + @Inject(method = "drawSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/item/ItemStack;III)V")) + public void drawBackground(DrawContext context, Slot slot, CallbackInfo ci) { + if (!ExtraOptions.itemRarityBackground) return; + int x = slot.x; + int y = slot.y; + ItemStack stack = slot.getStack(); + ItemRarityDrawer.draw(context, stack, x, y); + } +} @@ -0,0 +1,23 @@ +package blade.addon.mixin; + +import blade.addon.features.item.ItemRarityDrawer; +import blade.addon.utils.config.values.ExtraOptions; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +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(InGameHud.class) +public class InGameHudMixin { + + @Inject(method = "renderHotbarItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawItem(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/ItemStack;III)V")) + public void drawItem(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { + if (!ExtraOptions.itemRarityBackground) return; + ItemRarityDrawer.draw(context, stack, x, y); + } +} @@ -0,0 +1,35 @@ +package blade.addon.mixin; + +import blade.addon.features.item.ItemRarityHolder; +import blade.addon.features.item.ItemRarity; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ItemStack.class) +public class ItemStackMixin implements ItemRarityHolder { + + @Unique + private ItemRarity itemRarity = null; + + + @Override + public ItemRarity blade_addons$getItemRarity() { + return itemRarity; + } + + @Override + public boolean blade_addons$hasItemRarity() { + return itemRarity != ItemRarity.NONE; + } + + @Override + public void blade_addons$setItemRarity(ItemRarity itemRarity) { + this.itemRarity = itemRarity; + } + + @Override + public boolean blade_addons$hasScanned() { + return itemRarity != null; + } +} @@ -1,11 +1,14 @@ package blade.addon.utils; +import blade.addon.features.dungeon.LeapOrder; import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.utils.config.Config; import blade.addon.utils.dungeon.FillHelper; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.DoubleArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; @@ -14,38 +17,56 @@ import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.command.CommandRegistryAccess; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; + public class Commands { private static final String[] COMMAND_ALIASES = {"ba", "blade", "bladeaddons"}; + private static final LiteralArgumentBuilder<FabricClientCommandSource> devRoot = ClientCommandManager.literal("badev"); - public static void register() { + public static void init() { ClientCommandRegistrationCallback.EVENT.register(Commands::registerCommands); } public static void registerCommands(@NotNull CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) { + dispatcher.register(devRoot); + + //prob not a good solution but I don't use that many commands currently for (String alias : COMMAND_ALIASES) { dispatcher.register( ClientCommandManager.literal(alias) - .then(ClientCommandManager.literal("ep").executes(context -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.ENDER_PEARL, 16, 16))) + .then(ClientCommandManager.literal("ep").executes(context -> FillHelper.fillItem(FillHelper.ENDER_PEARL, 16, 16, false))) - .then(ClientCommandManager.literal("sb").executes(context -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.SUPERBOOM_TNT, 64, 64))) + .then(ClientCommandManager.literal("sb").executes(context -> FillHelper.fillItem(FillHelper.SUPERBOOM_TNT, 64, 64, false))) - .then(ClientCommandManager.literal("ij").executes(context -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.INFLATABLE_JERRY, 64, 64))) + .then(ClientCommandManager.literal("ij").executes(context -> FillHelper.fillItem(FillHelper.INFLATABLE_JERRY, 64, 64, false))) .then(ClientCommandManager.literal("refill") .executes( context -> { - FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.ENDER_PEARL, 16, 16); - Scheduler.scheduleTask(() -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.SUPERBOOM_TNT, 64, 64), 40); - Scheduler.scheduleTask(() -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.INFLATABLE_JERRY, 64, 64), 80); + FillHelper.fillItem(FillHelper.ENDER_PEARL, 16, 16, true); + Scheduler.scheduleTask(() -> FillHelper.fillItem(FillHelper.SUPERBOOM_TNT, 64, 64, true), 40); + Scheduler.scheduleTask(() -> FillHelper.fillItem(FillHelper.INFLATABLE_JERRY, 64, 64, true), 80); return Constants.SUCCESS; } )) + .then(ClientCommandManager.literal("leaporder") + .then(ClientCommandManager.argument("backupMage", StringArgumentType.string()) + .then(ClientCommandManager.argument("odinOrder", BoolArgumentType.bool()) + .executes(context -> { + String backupMage = StringArgumentType.getString(context, "backupMage"); + boolean odinOrder = BoolArgumentType.getBool(context, "odinOrder"); + LeapOrder.leapOrder(backupMage, odinOrder); + return Constants.SUCCESS; + }) + ) + ) + ) .then(ClientCommandManager.literal("waypoint") @@ -145,16 +166,6 @@ public class Commands { ) - .then(ClientCommandManager.literal("debug") - .then(ClientCommandManager.argument("option", StringArgumentType.greedyString()).executes(context -> { - String option = StringArgumentType.getString(context, "option"); - return Debug.parseOption(option); - }) - ) - ) - - - .executes(commandContext -> Scheduler.scheduleScreen(Config.createScreen(null))) ); @@ -165,4 +176,7 @@ public class Commands { } } + public static void registerDevCommand(LiteralArgumentBuilder<FabricClientCommandSource> commandManager) { + devRoot.then(commandManager); + } } @@ -6,6 +6,7 @@ public class Constants { public static final String NAMESPACE = "blade-addons"; public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); public static final double TICK_DURATION = 0.05; + public static final int TEXT_HEIGHT = 10; public static final int GREEN_COLOR = 0xff00ff00; public static final int ORANGE_COLOR = 0xffDAA06D; @@ -1,27 +1,47 @@ package blade.addon.utils; import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.dungeon.Section; +import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.minecraft.text.Text; public class Debug { - public static int parseOption(String string) { + private static boolean sendDebug = false; - switch (string) { - case "RUN_INFO": - sendRunInfo(); - break; - } + public static void init() { + registerCommands(); + + } + private static void registerCommands() { + Commands.registerDevCommand(ClientCommandManager.literal("runInfo").executes(context -> { + sendRunInfo(); + return Constants.SUCCESS; + })); + + Commands.registerDevCommand(ClientCommandManager.literal("toggleSendDebug").executes(context -> { + sendDebug = !sendDebug; + Misc.addChatMessage(Text.literal("Send debug: " + sendDebug)); + return Constants.SUCCESS; + })); + } - return Constants.SUCCESS; + //TODO: change this to a LOG object + public static void addDebugLog(String message) { + System.out.println("Blade-addons:" + message); + } + + public static void sendDebugMessage(Text text) { + if (sendDebug) { + Misc.addChatMessage(text); + } } public static void sendRunInfo() { Misc.addChatMessage(Text.literal("Phase: " + Phase.getPhase())); - Misc.addChatMessage(Text.literal("Section: " + Phase.getSection())); - Misc.addChatMessage(Text.literal("Gateblown: " + Phase.isGateBlownUp())); - Misc.addChatMessage(Text.literal("Terms done: " + Phase.isTermsDone())); + Misc.addChatMessage(Text.literal("Section: " + Section.getSection())); + Misc.addChatMessage(Text.literal("Gateblown: " + Section.isGateBlownUp())); Misc.addChatMessage(Text.literal("In floor 7: " + Phase.isInFloor7())); } @@ -32,7 +32,7 @@ public class JsonUtility { return parseSplits(element); } } catch (IOException e) { - System.out.println(e.getMessage()); + Debug.addDebugLog(e.getMessage()); } return new HashMap<>(); @@ -78,7 +78,7 @@ public class JsonUtility { return parsePositonalMessages(element); } } catch (IOException e) { - System.out.println(e.getMessage()); + Debug.addDebugLog(e.getMessage()); } return new ArrayList<>(); @@ -5,17 +5,26 @@ import blade.addon.utils.dungeon.Phase; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.text.Text; import org.lwjgl.glfw.GLFW; +import java.util.List; + public class Keybinds { private static final String CATEGORY = Constants.NAMESPACE; private static KeyBinding openConfig; + private static KeyBinding getItemLore; - public static void register() { + public static void init() { openConfig = KeyBindingHelper.registerKeyBinding(new KeyBinding( "opens Config", @@ -23,6 +32,12 @@ public class Keybinds { GLFW.GLFW_KEY_RIGHT_SHIFT, CATEGORY)); + getItemLore = KeyBindingHelper.registerKeyBinding(new KeyBinding( + "Grabs the items lore", + InputUtil.Type.KEYSYM, + GLFW.GLFW_KEY_UNKNOWN, + CATEGORY)); + ClientTickEvents.END_CLIENT_TICK.register(Keybinds::checkInputs); } @@ -31,5 +46,27 @@ public class Keybinds { if (openConfig.wasPressed()) { client.setScreen(Config.createScreen(null)); } + + if (getItemLore.wasPressed()) { + ClientPlayerEntity player = client.player; + if (player == null) { + Misc.addChatMessage(Text.literal("player is null")); + return; + } + + ItemStack heldStack = player.getMainHandStack(); + LoreComponent lore = heldStack.get(DataComponentTypes.LORE); + if (lore == null) { + Misc.addChatMessage(Text.literal("lore is null")); + return; + } + + List<Text> lines = lore.lines(); + for(Text line: lines) { + Misc.addChatMessage(line); + } + + Misc.addChatMessage(Text.literal("Rarity: " + Misc.getRarity(heldStack).name())); + } } } @@ -25,8 +25,6 @@ public enum Location { inSkyblock = serverType.getName().equals("SkyBlock"); } - System.out.println(map.toUpperCase().replace(" ", "_")); - try { currentLocation = Location.valueOf(map.toUpperCase().replace(" ", "_")); } catch (IllegalArgumentException ignored) { @@ -1,12 +1,18 @@ package blade.addon.utils; +import blade.addon.features.item.ItemRarity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.text.Text; +import java.util.List; + public class Misc { public static final MinecraftClient instance = MinecraftClient.getInstance(); @@ -17,8 +23,12 @@ public class Misc { } public static void addChatMessage(Text text) { - InGameHud gameHud = MinecraftClient.getInstance().inGameHud; - gameHud.getChatHud().addMessage(text); + try { + InGameHud gameHud = MinecraftClient.getInstance().inGameHud; + gameHud.getChatHud().addMessage(text); + } catch (IndexOutOfBoundsException ignored) { + Debug.addDebugLog("Chat message failed to get added"); + } } public static void setTitle(Text text) { @@ -30,4 +40,27 @@ public class Misc { if (networkHandler == null) return; networkHandler.sendChatCommand(string); } + + public static ItemRarity getRarity(ItemStack item) { + LoreComponent lore = item.get(DataComponentTypes.LORE); + if (lore == null) return ItemRarity.NONE; + + List<Text> lines = lore.lines(); + if (lines.isEmpty()) return ItemRarity.NONE; + Text line = lines.getLast(); + + if (line == null) return ItemRarity.NONE; + String string = line.getString(); + String[] rarityStrings = string.split(" "); + + for (String testString: rarityStrings) { + try { + ItemRarity rarity = ItemRarity.valueOf(testString); + return rarity; + } catch (IllegalArgumentException ignored) { + + } + } + return ItemRarity.NONE; + } } @@ -10,6 +10,7 @@ import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.config.values.ExtraOptions; import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.dungeon.Section; import blade.addon.utils.dungeon.Split; import config.practical.ConfigurableScreen; import config.practical.category.ConfigCategory; @@ -29,7 +30,7 @@ public class Config { private static final Text TITLE = Text.literal("Blade Addons"); public static final ConfigManager manager = new ConfigManager("./config/" + Constants.NAMESPACE + ".json", - List.of(Phase.class, Split.class, MobHighlight.class, ExtraOptions.class, DianaNotifier.class, Components.class, Dungeons.class, Floor7.class)); + List.of(Phase.class, Section.class, Split.class, MobHighlight.class, ExtraOptions.class, DianaNotifier.class, Components.class, Dungeons.class, Floor7.class)); public static Screen createScreen(Screen parent) { ConfigurableScreen screen = new ConfigurableScreen(TITLE, parent, manager); @@ -91,6 +92,7 @@ public class Config { ConfigSection storm = new ConfigSection(Text.literal("Storm")); storm.add(new ConfigBool(Text.literal("Storm Tick timer"), () -> Floor7.enableStormTickTimer, bool -> Floor7.enableStormTickTimer = bool)); + storm.add(new ConfigBool(Text.literal("Tick down from 5"), () -> Floor7.tickDownStormTickTimer, bool -> Floor7.tickDownStormTickTimer = bool)); storm.add(new ConfigBool(Text.literal("First Death time"), () -> Floor7.enableStormDeathTime, bool -> Floor7.enableStormDeathTime = bool)); storm.add(new ConfigBool(Text.literal("Distance to ledge"), () -> Floor7.displayDistanceToLedge, bool -> Floor7.displayDistanceToLedge = bool)); storm.add(new ConfigBool(Text.literal("Warn if spirit mask is used"), () -> Floor7.notifyUsedSpiritMask, bool -> Floor7.notifyUsedSpiritMask = bool)); @@ -101,6 +103,9 @@ public class Config { goldor.add(new ConfigBool(Text.literal("Term start time"), () -> Floor7.enableTermStartTimer, bool -> Floor7.enableTermStartTimer = bool)); goldor.add(new ConfigBool(Text.literal("death ticks intervals"), () -> Floor7.inDeathTicks, bool -> Floor7.inDeathTicks = bool)); goldor.add(new ConfigBool(Text.literal("Positional messages"), () -> Floor7.enablePositionalMessages, bool -> Floor7.enablePositionalMessages = bool)); + goldor.add(new ConfigBool(Text.literal("Terminal splits"), () -> Section.enableTerminalSplits, bool -> Section.enableTerminalSplits = bool)); + goldor.add(new ConfigOptions<>(Text.literal("Display when"), Section.DisplayTerminalSplitsWhen.values(), () -> Section.displayTerminalSplitsWhen, when -> Section.displayTerminalSplitsWhen = when)); + floor7.add(goldor); @@ -116,6 +121,7 @@ public class Config { ConfigCategory splits = new ConfigCategory("Splits"); splits.add(new ConfigBool(Text.literal("Enable Splits"), () -> Phase.enableSplits, bool -> Phase.enableSplits = bool)); splits.add(new ConfigBool(Text.literal("Include total time"), () -> Phase.includeTotalTime, bool -> Phase.includeTotalTime = bool)); + splits.add(new ConfigBool(Text.literal("Send split in chat when over"), () -> Phase.sendSplitInChat, bool -> Phase.sendSplitInChat = bool)); splits.add(new ConfigOptions<>(Text.literal("Tick timer type"), Split.TimerType.values(), () -> Split.timerType, type -> Split.timerType = type)); splits.add(new ConfigColor(Text.literal("Real time color (Inactive)"), () -> Split.realTimeColorInactive, color -> Split.realTimeColorInactive = color, "real-time-inactive", false)); @@ -160,6 +166,7 @@ public class Config { extra.add(new ConfigBool(Text.literal("Hide arrows stuck to entities"), () -> ExtraOptions.hideStuckArrows, bool -> ExtraOptions.hideStuckArrows = bool)); extra.add(new ConfigBool(Text.literal("Disable ability on cooldown sound"), () -> ExtraOptions.disableAbilityCooldownSound, bool -> ExtraOptions.disableAbilityCooldownSound = bool)); extra.add(new ConfigBool(Text.literal("Hide dead entities"), () -> ExtraOptions.hideDeadEntities, bool -> ExtraOptions.hideDeadEntities = bool)); + extra.add(new ConfigBool(Text.literal("Item rarity background"), () -> ExtraOptions.itemRarityBackground, bool -> ExtraOptions.itemRarityBackground = bool)); ConfigSection diana = new ConfigSection(Text.literal("Diana notifications")); diana.add(new ConfigBool(Text.literal("Send Sound"), () -> DianaNotifier.sendSound, bool -> DianaNotifier.sendSound = bool)); @@ -14,4 +14,7 @@ public class ExtraOptions { @ConfigValue public static boolean hideDeadEntities = false; + + @ConfigValue + public static boolean itemRarityBackground = false; } @@ -19,6 +19,9 @@ public class Floor7 { @ConfigValue public static boolean enableStormTickTimer = false; + @ConfigValue + public static boolean tickDownStormTickTimer = false; + @ConfigValue public static boolean enableStormDeathTime = false; @@ -11,14 +11,47 @@ public class FillHelper { public static final String ENDER_PEARL = "Ender Pearl"; public static final String SUPERBOOM_TNT = "Superboom TNT"; public static final String INFLATABLE_JERRY = "Inflatable Jerry"; + public static final String DECOY = "Decoy"; /** - * @param client to get access to the player and networkHandler * @param itemName Name of item * @param minThreshold an integer that the item count has to be lower than to fill * @param maxCount the max count of the item * @return 1 if it succeeds else 0 for fail */ + public static int fillItem(String itemName, int minThreshold, int maxCount, boolean needAtleastOne) { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + + if (player == null) return Constants.FAIL; + + Inventory inventory = player.getInventory(); + + int currentCount = 0; + + for (int i = 0; i < inventory.size(); i++) { + + ItemStack item = inventory.getStack(i); + + if (item.getName().toString().contains(itemName)) { + + int highestCount = item.getCount(); + + if (highestCount > currentCount) { + currentCount = highestCount; + + if (highestCount >= maxCount) return Constants.FAIL; + } + } + + } + + if ((needAtleastOne && currentCount == 0) || minThreshold < currentCount) return Constants.FAIL; + + int itemsToGive = maxCount - currentCount; + player.networkHandler.sendChatCommand("gfs " + itemName + " " + itemsToGive); + return Constants.SUCCESS; + } + public static int fillItem(MinecraftClient client, String itemName, int minThreshold, int maxCount) { ClientPlayerEntity player = client.player; @@ -45,7 +78,7 @@ public class FillHelper { } - if (minThreshold < currentCount) return Constants.FAIL; + if ( minThreshold < currentCount) return Constants.FAIL; int itemsToGive = maxCount - currentCount; player.networkHandler.sendChatCommand("gfs " + itemName + " " + itemsToGive); @@ -23,23 +23,17 @@ public class Phase { private static final Pattern END_PATTERN = Pattern.compile("^\\s*☠ Defeated (.+) in 0?([\\dhms ]+)\\s*(\\(NEW RECORD!\\))?$"); private static final Pattern SEARCH_PATTERN = Pattern.compile("^ ⏣ The Catacombs .*$"); - private static final Pattern TERMINALS_DONE_PATTERN = Pattern.compile("(activated|completed) (a terminal|a device|a lever)! \\((\\d)/(\\d)\\)$"); private static final Split DUMMY_SPLIT = new Split("test split", "if this is called idk", "if this is called idk", 43690); private static final HashMap<String, ArrayList<Split>> FLOOR_SPLITS = JsonUtility.readSplits("/data/splits.json"); - private static final int TEXT_HEIGHT = 10; private static final int DUMMY_SIZE = 10; private static ArrayList<Split> currentSplits; private static int currentPhase = -1; private static String floor = ""; - private static int currentSection = 0; - private static boolean termsDone = false; - private static boolean gateBlownUp = false; - private static boolean inFloor7 = false; private static boolean stormDead = false; private static boolean runOver = false; @@ -50,6 +44,9 @@ public class Phase { @ConfigValue public static boolean includeTotalTime = false; + @ConfigValue + public static boolean sendSplitInChat = false; + public static void init() { Events.ON_SERVER_TICK.register(() -> { if (currentSplits == null || runOver) return; @@ -95,9 +92,6 @@ public class Phase { inFloor7 = false; stormDead = false; runOver = false; - currentSection = 0; - termsDone = false; - gateBlownUp = false; } public static void parseGameMessage(Text message) { @@ -114,6 +108,10 @@ public class Phase { currentSplit.parseMessage(string); if (currentSplit.ended()) { + if (sendSplitInChat) { + Misc.addChatMessage(currentSplit.createNameText().append(currentSplit.createTimeText())); + } + currentPhase = i + 1; if (Events.ON_PHASE_CHANGE.hasListeners()) { Events.ON_PHASE_CHANGE.invoke(PhaseEvent::onPhaseChange); @@ -134,11 +132,9 @@ public class Phase { } if (inP2()) { - parseP2(string); - } - - if (inP3()) { - parseP3(string); + if (string.equals("[BOSS] Storm: I should have known that I stood no chance.")) { + stormDead = true; + } } } @@ -163,64 +159,15 @@ public class Phase { } } - - private static void parseP2(String string) { - if (string.equals("[BOSS] Storm: I should have known that I stood no chance.")) { - stormDead = true; - currentSection = 1; - } - } - - private static void parseP3(String string) { - if (!termsDone) { - Matcher matcher = TERMINALS_DONE_PATTERN.matcher(string); - if (matcher.find()) { - String num1 = matcher.group(3); - String num2 = matcher.group(4); - if (num1.equals(num2)) { - termsDone = true; - } - } - } - - if (!gateBlownUp) { - if (string.equals("The gate has been destroyed!")) { - gateBlownUp = true; - } - } - - if (gateBlownUp && termsDone) { - currentSection++; - gateBlownUp = false; - termsDone = false; - } - - if (string.equals("The Core entrance is opening!")) { - //so in "goldor tunnel" can be shown after terms are done - currentSection = 5; - } - } - public static double getPhase() { return currentPhase; } - public static double getSection() { - return currentSection; - } public static boolean isInFloor7() { return inFloor7; } - public static boolean isGateBlownUp() { - return gateBlownUp; - } - - public static boolean isTermsDone() { - return termsDone; - } - public static boolean runStarted() { return currentPhase >= 0; } @@ -245,12 +192,12 @@ public class Phase { return currentPhase == 6 && inFloor7; } - public static boolean inP3() { - return (currentPhase == 6 || currentPhase == 7) && inFloor7; + public static boolean inGoldorTunnel() { + return currentPhase == 7 && inFloor7; } - public static boolean inSection(int section) { - return currentSection == section && inP3(); + public static boolean inP3() { + return (currentPhase == 6 || currentPhase == 7) && inFloor7; } public static boolean inP5() { @@ -275,12 +222,12 @@ public class Phase { if (!includeTotalTime) splitCount--; for (int i = 0; i < splitCount; i++) { - currentSplits.get(i).drawSplit(drawContext, textRenderer, x, y + TEXT_HEIGHT * i); + currentSplits.get(i).drawSplit(drawContext, textRenderer, x, y + Constants.TEXT_HEIGHT * i); } } else { for (int i = 0; i < DUMMY_SIZE; i++) { - DUMMY_SPLIT.drawSplit(drawContext, textRenderer, x, y + TEXT_HEIGHT * i); + DUMMY_SPLIT.drawSplit(drawContext, textRenderer, x, y + Constants.TEXT_HEIGHT * i); } } }), () -> enableSplits @@ -26,7 +26,7 @@ public class PositionMessage { private boolean inAValidSection() { for (int section: sections) { - if (Phase.inSection(section)) return true; + if (Section.inSection(section)) return true; } return false; } @@ -0,0 +1,200 @@ +package blade.addon.utils.dungeon; + +import blade.addon.utils.Constants; +import blade.addon.utils.Debug; +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.events.Events; +import config.practical.hud.HUDComponent; +import config.practical.manager.ConfigValue; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Section { + public enum DisplayTerminalSplitsWhen { + BOSS("Entire Boss"), TERMINALS_ONLY("Terminals"); + + private final String label; + + DisplayTerminalSplitsWhen(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } + } + + private static final Split[] splits = { + new Split("1st", "", "", 0xffffffff), + new Split("2nd", "", "", 0xffffffff), + new Split("3rd", "", "", 0xffffffff), + new Split("4th", "", "", 0xffffffff),}; + + private static final Pattern TERMINALS_DONE_PATTERN = Pattern.compile("(activated|completed) (a terminal|a device|a lever)! \\((\\d)/(\\d)\\)$"); + + private static int currentSection = 0; + private static int completed = 0; + private static int total = 7; + private static boolean gateBlownUp = false; + + @ConfigValue + public static boolean enableTerminalSplits = false; + + @ConfigValue + public static boolean sendTermianlSplits = false; + + @ConfigValue + public static DisplayTerminalSplitsWhen displayTerminalSplitsWhen = DisplayTerminalSplitsWhen.TERMINALS_ONLY; + + public static void init() { + Events.ON_GAME_MESSAGE.register(Section::parseMessage); + Events.ON_LOCATION_CHANGE.register(newLocation -> { + if (Location.inDungeon()) { + reset(); + } + }); + Events.ON_PHASE_CHANGE.register(() -> { + if (Phase.inTerminals()) { + currentSection = 1; + splits[0].start(); + } else if (Phase.inGoldorTunnel()) { + endAllSections(); + } + }); + Events.ON_SERVER_TICK.register(() -> { + if (currentSection < 1 || currentSection > 5) return; + for (Split split : splits) { + split.tick(); + } + }); + } + + private static void reset() { + currentSection = 0; + resetSection(); + for(Split split: splits) { + split.reset(); + } + } + + private static void resetSection() { + completed = 0; + gateBlownUp = false; + } + + private static void incrementSection() { + resetSection(); + endSplit(currentSection); + currentSection++; + startSplit(currentSection); + } + + private static void endSplit(int section) { + int index = section - 1; + if (index < 0 || index >= splits.length) return; + splits[index].end(); + } + + private static void startSplit(int section) { + int index = section - 1; + if (index < 0 || index >= splits.length) return; + splits[index].start(); + } + + private static void endAllSections() { + for(Split split: splits) { + split.end(); + } + if (sendTermianlSplits) { + Misc.addChatMessage(Text.literal("Splits: ").formatted(Formatting.GREEN)); + for (Split split : splits) { + split.end(); + Misc.addChatMessage(split.createNameText().append(split.createTimeText())); + } + } + } + + private static void parseMessage(Text message) { + if (!Phase.inTerminals() || !enableTerminalSplits) return; + + String string = message.getString(); + Matcher matcher = TERMINALS_DONE_PATTERN.matcher(string); + if (matcher.find()) { + try { + int recentlyCompleted = Integer.parseInt(matcher.group(3)); + if ((recentlyCompleted == total && gateBlownUp) || (recentlyCompleted < completed)) { + incrementSection(); + } else { + total = Integer.parseInt(matcher.group(4)); + completed = recentlyCompleted; + } + } catch (NumberFormatException e) { + Debug.addDebugLog("Failed to parse terminal message, " + e.getMessage()); + } + + + } else if (!gateBlownUp) { + if (string.equals("The gate has been destroyed!")) { + gateBlownUp = true; + + if (completed == total) { + incrementSection(); + } + + } + } else if (string.equals("The Core entrance is opening!")) { + //so in "goldor tunnel" can be shown after terms are done + currentSection = 5; + endAllSections(); + Debug.sendDebugMessage(Text.literal("Core section")); + } + } + + + public static double getSection() { + return currentSection; + } + + public static boolean isGateBlownUp() { + return gateBlownUp; + } + + public static boolean inSection(int section) { + return currentSection == section && Phase.inP3(); + } + + public static boolean display() { + if (enableTerminalSplits && Location.inDungeon()) { + + return switch (displayTerminalSplitsWhen) { + case BOSS -> Phase.inBoss(); + case TERMINALS_ONLY -> Phase.inTerminals(); + }; + + } + + return false; + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + + for (int i = 0; i < splits.length; i++) { + splits[i].drawSplit(context, textRenderer, x, y + Constants.TEXT_HEIGHT * i); + } + } + + @ConfigValue + public static HUDComponent terminalSplits = new HUDComponent(0, 0, Split.SPLIT_LENGTH, 50, 1, "Term splits", Section::display, Section::render, () -> enableTerminalSplits); +} @@ -5,6 +5,7 @@ "mixins": [ "ArrowMixin", "InventoryMixin", + "ItemStackMixin", "NetworkMixin", "ServerTickMixin" ], @@ -17,6 +18,8 @@ "client": [ "BlockEntityRenderMixin", "FireMixin", + "HandledScreenMixin", + "InGameHudMixin", "NetworkMixin", "PositionMixin", "RenderMixin" @@ -3,9 +3,9 @@ "id": "blade-addons", "version": "${version}", "name": "blade-addons", - "description": "This is an example description! Tell everyone what your mod is about!", + "description": "Just some 1.21 mod that ports mods like valley", "authors": [ - "Me!" + "BladeMasterGabe" ], "contact": { "homepage": "https://fabricmc.net/", |
- refactoring of where config values are stored查看变更src/main/java/blade/addon/Bladeaddons.java | 2 ++
src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 8 ++----
src/main/java/blade/addon/features/dungeon/ChestCounter.java | 46 +++++++++++--------------------
src/main/java/blade/addon/features/dungeon/DeathTickTimer.java | 25 ++++++++---------
src/main/java/blade/addon/features/dungeon/DupeClassChecker.java | 26 ++++++++----------
src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 11 +++-----
src/main/java/blade/addon/features/dungeon/HidePlayers.java | 21 ++++----------
src/main/java/blade/addon/features/dungeon/ItemHighlight.java | 8 ++----
src/main/java/blade/addon/features/dungeon/KeyNotifier.java | 38 ++++++++++++--------------
src/main/java/blade/addon/features/dungeon/LeapMessage.java | 7 ++---
src/main/java/blade/addon/features/dungeon/SecretSpawnTimer.java | 49 ++++++++++++++++-----------------
src/main/java/blade/addon/features/dungeon/WarpCooldown.java | 52 ++++++++++++++++-------------------
src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 17 +++---------
src/main/java/blade/addon/features/dungeon/f7/CrystalSpawn.java | 29 ++++++++------------
src/main/java/blade/addon/features/dungeon/f7/DistanceToLedge.java | 28 ++++++++-----------
src/main/java/blade/addon/features/dungeon/f7/GoldorTickTimer.java | 50 +++++++++++++++-------------------
src/main/java/blade/addon/features/dungeon/f7/InvincibilityTimer.java | 100 +++++++++++++++++++++++++++++--------------------------------------
src/main/java/blade/addon/features/dungeon/f7/PositionMessages.java | 8 ++----
src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 49 ++++++++++++---------------------
src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 57 ++++++++++++++++----------------------
src/main/java/blade/addon/features/dungeon/f7/TermStartTimer.java | 32 ++++++++++------------
src/main/java/blade/addon/mixin/ArrowMixin.java | 2 +-
src/main/java/blade/addon/mixin/FireMixin.java | 2 +-
src/main/java/blade/addon/mixin/NetworkMixin.java | 2 +-
src/main/java/blade/addon/mixin/RenderMixin.java | 5 ++--
src/main/java/blade/addon/utils/config/Config.java | 110 +++++++++++++++++++++++++++++++-------------------------------------------
src/main/java/blade/addon/utils/config/components/Components.java | 67 +++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/utils/config/values/Dungeons.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
src/main/java/blade/addon/{features => utils/config/values}/ExtraOptions.java | 8 +-----
src/main/java/blade/addon/utils/config/values/Floor7.java | 54 ++++++++++++++++++++++++++++++++++++
30 files changed, 520 insertions(+), 466 deletions(-)@@ -26,6 +26,7 @@ import blade.addon.utils.Commands; import blade.addon.utils.Keybinds; import blade.addon.utils.Location; import blade.addon.utils.Scheduler; +import blade.addon.utils.config.components.Components; import blade.addon.utils.config.Config; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; @@ -34,6 +35,7 @@ import net.fabricmc.api.ModInitializer; public class Bladeaddons implements ModInitializer { @Override public void onInitialize() { + Components.init(); Config.manager.load(); Keybinds.register(); Commands.register(); @@ -2,8 +2,8 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.ChatHud; @@ -24,14 +24,12 @@ public class AutoRequeue { private static final HashMap<String, Text> playerHashMap = new HashMap<>(); - @ConfigValue - public static boolean enableAutoRequeue = false; private static boolean someoneLeft = false; public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() && !enableAutoRequeue) return; + if (!Location.inDungeon() && !Dungeons.enableAutoRequeue) return; String string = message.getString(); Matcher matcher = LEFT_PATTERN.matcher(string); if (matcher.find()) { @@ -65,7 +63,7 @@ public class AutoRequeue { }); Events.ON_RUN_END.register(() -> { - if (!enableAutoRequeue || someoneLeft) return; + if (!Dungeons.enableAutoRequeue || someoneLeft) return; if (playerHashMap.isEmpty()) { Misc.executeCommand("instancerequeue"); @@ -1,11 +1,12 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Text; @@ -17,16 +18,6 @@ public class ChestCounter { private static final Pattern PATTERN = Pattern.compile("^ Unclaimed chests: (\\d+)$"); - @ConfigValue - public static boolean displayChestCount = false; - @ConfigValue - public static boolean onlyAfterRunOver = false; - @ConfigValue - public static boolean sendChestWarning = false; - - @ConfigValue - public static int chestWarningCount = 55; - private static int chestDisplayCount = 0; private static int countedChests = 0; private static boolean hasUpdatedData = false; @@ -57,7 +48,7 @@ public class ChestCounter { Events.ON_RUN_END.register(() -> { countedChests++; - if (sendChestWarning && chestDisplayCount + countedChests >= chestWarningCount) { + if (Dungeons.sendChestWarning && chestDisplayCount + countedChests >= Dungeons.chestWarningCount) { ClientPlayerEntity player = MinecraftClient.getInstance().player; if (player != null) { player.playSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); @@ -67,25 +58,20 @@ public class ChestCounter { }); } - @ConfigValue - public static HUDComponent chestCounter = new HUDComponent(0, 0, 100, 10, 1, "Chest count", - () -> - { - if ((onlyAfterRunOver && !Phase.runOver())) return false; - return displayChestCount && Location.inDungeon(); - }, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - - if (hasUpdatedData) { - drawContext.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, 0xffffffff, true); - } else { - drawContext.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, 0xffff0000, true); + public static boolean display() { + if ((Dungeons.onlyAfterRunOver && !Phase.runOver())) return false; + return Dungeons.displayChestCount && Location.inDungeon(); + } - } - }), () -> displayChestCount - ); + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + if (hasUpdatedData) { + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, 0xffffffff, true); + } else { + context.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, 0xffff0000, true); + } + } } @@ -2,22 +2,20 @@ package blade.addon.features.dungeon; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.math.Vec3d; public class DeathTickTimer { - private static final int WIDTH = 30; private static final int TOTAL_DEATH_TICKS = 40; private static Vec3d firstPosition; - @ConfigValue - public static boolean enableDeathTickTimer = false; private static int tick = TOTAL_DEATH_TICKS; public static void init() { @@ -48,17 +46,16 @@ public class DeathTickTimer { } } - @ConfigValue - public static HUDComponent deathTickTimer = new HUDComponent(0, 0, WIDTH, 10, 1, "Death Tick Timer", - () -> enableDeathTickTimer && Location.inDungeon(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + public static boolean display() { + return Dungeons.enableDeathTickTimer && Location.inDungeon(); + } - double num = tick * Constants.TICK_DURATION; + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, WIDTH); + double num = tick * Constants.TICK_DURATION; + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth()); - }), () -> enableDeathTickTimer - ); + } } @@ -1,12 +1,13 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.world.ClientWorld; import net.minecraft.scoreboard.Scoreboard; @@ -28,12 +29,9 @@ public class DupeClassChecker { private static boolean hasDuplicateClass = false; - @ConfigValue - public static boolean detectDuplicateClass = false; - public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || Phase.runStarted() || !detectDuplicateClass) return; + if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return; Matcher matcher = STARTING_PATTERN.matcher(message.getString()); if (!matcher.find()) return; @@ -74,14 +72,14 @@ public class DupeClassChecker { return false; } - @ConfigValue - public static HUDComponent duplicateClassDisplay = new HUDComponent(0, 0, 130, 10, 1, "", - () -> Location.inDungeon() && hasDuplicateClass && !Phase.runStarted(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + public static boolean display() { + return Location.inDungeon() && hasDuplicateClass && !Phase.runStarted(); + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - drawContext.drawText(MinecraftClient.getInstance().textRenderer, DISPLAY_TEXT, x, y, 0xffffffff, true); - }), () -> detectDuplicateClass - ); + context.drawText(MinecraftClient.getInstance().textRenderer, DISPLAY_TEXT, x, y, 0xffffffff, true); + } } @@ -2,8 +2,8 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -17,15 +17,12 @@ public class ExplosiveShot { private static final Pattern PATTERN = Pattern.compile("^Your Explosive Shot hit (\\d+) enemies for ([\\d,?.]+) damage\\.$"); private static final DecimalFormat FORMAT = new DecimalFormat("###,###,###,###"); - @ConfigValue - public static boolean calculateCriticalHit = false; - @ConfigValue - public static boolean onlyInBoss = false; + public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !calculateCriticalHit) return; - if (onlyInBoss && !Phase.inBoss()) return; + if (!Location.inDungeon() || !Dungeons.calculateCriticalHit) return; + if (Dungeons.onlyInBoss && !Phase.inBoss()) return; String string = message.getString(); @@ -1,9 +1,9 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; -import config.practical.manager.ConfigValue; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.Vec3d; @@ -17,17 +17,6 @@ public class HidePlayers { private static long startTime; private static boolean justLeapt = false; - @ConfigValue - public static boolean hideAfterLeap = false; - - @ConfigValue - public static boolean hideOnlyInBoss = true; - - @ConfigValue - public static boolean hideAtSS = false; - - @ConfigValue - public static boolean hideBeforeTermsOnly = false; public static void init() { Events.ON_LEAP.register(message -> { @@ -37,8 +26,8 @@ public class HidePlayers { } public static boolean testHideAtLeap() { - if (!hideAfterLeap || !justLeapt) return false; - if (!Phase.inBoss() && hideOnlyInBoss) return false; + if (!Dungeons.hideAfterLeap || !justLeapt) return false; + if (!Phase.inBoss() && Dungeons.hideOnlyInBoss) return false; if (System.currentTimeMillis() - startTime >= HIDE_DURATION) { justLeapt = false; @@ -49,8 +38,8 @@ public class HidePlayers { } public static boolean testHideAtSS(PlayerEntity player) { - if (!hideAtSS || !Phase.inBoss()) return false; - if (hideBeforeTermsOnly && Phase.inP3()) return false; + if (!Dungeons.hideAtSS || !Phase.inBoss()) return false; + if (Dungeons.hideBeforeTermsOnly && Phase.inP3()) return false; return SS_POSITION.distanceTo(player.getPos()) <= DISTANCE; } @@ -2,10 +2,10 @@ package blade.addon.features.dungeon; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; @@ -34,8 +34,6 @@ public class ItemHighlight { private static final ConcurrentHashMap<ItemEntity, Integer> trackedItems = new ConcurrentHashMap<>(); - @ConfigValue - public static boolean highlightItems = false; public static void init() { ClientTickEvents.END_CLIENT_TICK.register(minecraftClient -> { @@ -61,7 +59,7 @@ public class ItemHighlight { }); WorldRenderEvents.BEFORE_DEBUG_RENDER.register(worldRenderContext -> { - if (!highlightItems) return; + if (!Dungeons.highlightItems) return; Camera camera = worldRenderContext.camera(); Vec3d cameraPos = camera.getPos(); MatrixStack matrixStack = worldRenderContext.matrixStack(); @@ -90,7 +88,7 @@ public class ItemHighlight { } public static boolean highlightItem(ItemEntity item) { - if (!highlightItems || !Location.inDungeon() || Phase.inBoss()) return false; + if (!Dungeons.highlightItems || !Location.inDungeon() || Phase.inBoss()) return false; Text itemText = item.getStack().getName(); if (itemText == null) return false; @@ -1,13 +1,14 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.sound.SoundEvents; import net.minecraft.text.Style; @@ -30,12 +31,9 @@ public class KeyNotifier { private static boolean isBloodKey = false; private static boolean sentSound = false; - @ConfigValue - public static boolean enableKeyNotifier = false; - public static void init() { Events.ON_ENTITY_TRACKED.register((entity, world) -> { - if (!Location.inDungeon() || hasKey || !enableKeyNotifier) return; + if (!Location.inDungeon() || hasKey || !Dungeons.enableKeyNotifier) return; if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return; @@ -55,7 +53,7 @@ public class KeyNotifier { }); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !hasKey || !enableKeyNotifier) return; + if (!Location.inDungeon() || !hasKey || !Dungeons.enableKeyNotifier) return; if (!DungeonClass.isClass(DungeonClass.ARCHER) && !DungeonClass.isClass(DungeonClass.MAGE)) return; Matcher matcher = AUTOMATIC_PICKUP_PATTERN.matcher(message.getString()); @@ -93,19 +91,19 @@ public class KeyNotifier { } - @ConfigValue - public static HUDComponent keyNotifierDisplay = new HUDComponent(0, 0, 120, 10, 1, "", - () -> Location.inDungeon() && hasKey, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - - if (isBloodKey) { - drawContext.drawText(MinecraftClient.getInstance().textRenderer, BLOOD_KEY, x, y, 0xffffffff, true); - } else { - drawContext.drawText(MinecraftClient.getInstance().textRenderer, WITHER_KEY, x, y, 0xffffffff, true); - } + public static boolean display() { + return Location.inDungeon() && hasKey; + } - }), () -> enableKeyNotifier - ); + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + if (isBloodKey) { + context.drawText(MinecraftClient.getInstance().textRenderer, BLOOD_KEY, x, y, 0xffffffff, true); + } else { + context.drawText(MinecraftClient.getInstance().textRenderer, WITHER_KEY, x, y, 0xffffffff, true); + } + + } } @@ -1,8 +1,8 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.events.Events; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; @@ -15,9 +15,6 @@ public class LeapMessage { private static final int INDEX_REMOVAL = 9; private static final Pattern SEARCH_PATTERN = Pattern.compile("^You have teleported to .*!$"); - @ConfigValue - public static boolean enableLeapMessages = false; - public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { if (Location.inDungeon()) { @@ -33,7 +30,7 @@ public class LeapMessage { }); Events.ON_LEAP.register(message -> { - if (!enableLeapMessages) return; + if (!Dungeons.enableLeapMessages) return; ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); if (networkHandler == null) return; @@ -2,12 +2,13 @@ package blade.addon.features.dungeon; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import java.util.regex.Matcher; @@ -17,17 +18,13 @@ public class SecretSpawnTimer { private static final Pattern PATTERN = Pattern.compile("^Time Elapsed: "); private static final int TICKS_PER_SECOND = 20; - private static final int WIDTH = 20; - - @ConfigValue - public static boolean enableSecretSpawnTimer = false; private static int tick = 0; public static void init() { Events.ON_TEAM.register(text -> { - if (!Location.inDungeon() || !enableSecretSpawnTimer) return; + if (!Location.inDungeon() || !Dungeons.enableSecretSpawnTimer) return; Matcher matcher = PATTERN.matcher(text); if (matcher.find()) { @@ -38,24 +35,24 @@ public class SecretSpawnTimer { Events.ON_SERVER_TICK.register(() -> tick = Math.max(tick - 1, 0)); } - @ConfigValue - public static HUDComponent secretSpawnTimer = new HUDComponent(0, 0, WIDTH, 10, 1, "Secret spawn timer", - () -> Location.inDungeon() && enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - - int color; - if (tick > 10) { - color = Constants.GREEN_COLOR; - } else if (tick > 5) { - color = Constants.ORANGE_COLOR; - } else { - color = Constants.RED_COLOR; - } - - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(tick + ""), x, y, WIDTH, color); - - }), () -> enableSecretSpawnTimer - ); + public static boolean display() { + return Location.inDungeon() && Dungeons.enableSecretSpawnTimer && !Phase.inBoss() && Phase.runStarted(); + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + int color; + if (tick > 10) { + color = Constants.GREEN_COLOR; + } else if (tick > 5) { + color = Constants.ORANGE_COLOR; + } else { + color = Constants.RED_COLOR; + } + + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(tick + ""), x, y, component.getWidth(), color); + + } } @@ -1,10 +1,11 @@ package blade.addon.features.dungeon; import blade.addon.utils.Constants; +import blade.addon.utils.config.values.Dungeons; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -19,12 +20,9 @@ public class WarpCooldown { private static long endTime = 0; private static boolean displayCooldown = false; - @ConfigValue - public static boolean enableWarpCooldown = false; - public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!enableWarpCooldown) return; + if (!Dungeons.enableWarpCooldown) return; Matcher matcher = PATTERN.matcher(message.getString()); if (matcher.find()) { @@ -34,27 +32,25 @@ public class WarpCooldown { }); } - @ConfigValue - public static HUDComponent warpCoolDown = new HUDComponent(0, 0, 110, 10, 0.75f, "Warp cooldown", - () -> { - if (!enableWarpCooldown || !displayCooldown) return false; - - if ((endTime - System.currentTimeMillis()) > 0) { - return true; - } else { - displayCooldown = false; - return false; - } - }, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - - double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); - - Text text = Text.literal("Warp Cooldown: ").formatted(Formatting.DARK_PURPLE).append(Text.literal(Constants.DECIMAL_FORMAT.format(timeRemaining)).formatted(Formatting.WHITE)); - - drawContext.drawText(MinecraftClient.getInstance().textRenderer, text, x, y, 0xffffffff, true); - }), () ->enableWarpCooldown - ); + public static boolean display() { + if (!Dungeons.enableWarpCooldown || !displayCooldown) return false; + + if ((endTime - System.currentTimeMillis()) > 0) { + return true; + } else { + displayCooldown = false; + return false; + } + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + double timeRemaining = Math.max((endTime - System.currentTimeMillis()) / 1000.0, 0); + + Text text = Text.literal("Warp Cooldown: ").formatted(Formatting.DARK_PURPLE).append(Text.literal(Constants.DECIMAL_FORMAT.format(timeRemaining)).formatted(Formatting.WHITE)); + + context.drawText(MinecraftClient.getInstance().textRenderer, text, x, y, 0xffffffff, true); + } } @@ -4,6 +4,7 @@ import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; import blade.addon.utils.Waypoint; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; @@ -11,7 +12,6 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; @@ -45,15 +45,6 @@ public class BossWaypoints { public static final CopyOnWriteArrayList<Waypoint> waypoints = new CopyOnWriteArrayList<>(); - @ConfigValue - public static boolean enableBossWaypoints = false; - - @ConfigValue - public static int nextWaypointColor = 0xff00F7F7; - - @ConfigValue - public static boolean nextWaypointThroughWall = false; - private static boolean ignoreBoss = false; private static boolean place = false; @@ -66,7 +57,7 @@ public class BossWaypoints { } public static boolean isInValidArea() { - if (!enableBossWaypoints) return false; + if (!Floor7.enableBossWaypoints) return false; if (ignoreBoss) return true; return Location.inDungeon() && Phase.inBoss(); @@ -100,8 +91,8 @@ public class BossWaypoints { } private static void addWaypoint(double x, double y, double z, double dx, double dy, double dz) { - float[] colorAsFloat = RenderUtils.toFloats(nextWaypointColor); - waypoints.add(new Waypoint(x, y, z, dx, dy, dz, colorAsFloat[0], colorAsFloat[1], colorAsFloat[2], colorAsFloat[3], nextWaypointThroughWall)); + float[] colorAsFloat = RenderUtils.toFloats(Floor7.nextWaypointColor); + waypoints.add(new Waypoint(x, y, z, dx, dy, dz, colorAsFloat[0], colorAsFloat[1], colorAsFloat[2], colorAsFloat[3],Floor7.nextWaypointThroughWall)); save(); } @@ -2,13 +2,14 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -20,18 +21,13 @@ public class CrystalSpawn { private static final Pattern PATTERN_1 = Pattern.compile("^\\[BOSS] Maxor: THAT BEAM! IT HURTS! IT HURTS!!$"); private static final Pattern PATTERN_2 = Pattern.compile("^\\[BOSS] Maxor: YOU TRICKED ME!$"); - @ConfigValue - public static boolean enableCrystalSpawnTime = false; - - private static final int WIDTH = 30; - private static final int TICK_SPAWN = 34; private static int tick = 0; public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !Phase.inP1() || !enableCrystalSpawnTime) return; + if (!Location.inDungeon() || !Phase.inP1() || !Floor7.enableCrystalSpawnTime) return; Matcher matcher = PATTERN_1.matcher(message.getString()); if (!matcher.find()) { @@ -54,17 +50,16 @@ public class CrystalSpawn { } - @ConfigValue - public static HUDComponent crystalSpawnTime = new HUDComponent(0, 0, WIDTH, 10, 1, "Crystal Spawn Time", - () -> tick > 0 && Location.inDungeon(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + public static boolean display() { + return tick > 0 && Location.inDungeon() && Floor7.enableCrystalSpawnTime; + } - double num = tick * Constants.TICK_DURATION; + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)).formatted(Formatting.LIGHT_PURPLE), x, y, WIDTH); + double num = tick * Constants.TICK_DURATION; - }), () -> enableCrystalSpawnTime - ); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)).formatted(Formatting.LIGHT_PURPLE), x, y, component.getWidth()); + } } @@ -2,22 +2,19 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.text.Text; public class DistanceToLedge { private static final double MIN_X = 33.704; - private static final int WIDTH = 30; - - @ConfigValue - public static boolean displayDistanceToLedge = false; public static void init() { @@ -30,18 +27,15 @@ public class DistanceToLedge { return player.getX() - MIN_X; } - @ConfigValue - public static HUDComponent distanceToLedgeComponent = new HUDComponent(0, 0, WIDTH, 10, 1, "Distance to ledge", - () -> { - if (!displayDistanceToLedge || !Location.inDungeon()) return false; + public static boolean display() { + if (!Floor7.displayDistanceToLedge || !Location.inDungeon()) return false; + return Phase.inP2() && !Phase.stormDead() && (DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER)); + } - return Phase.inP2() && !Phase.stormDead() && (DungeonClass.isClass(DungeonClass.MAGE) || DungeonClass.isClass(DungeonClass.ARCHER)); - }, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(getDistance())), x, y, WIDTH); - }), () -> displayDistanceToLedge - ); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(getDistance())), x, y, component.getWidth()); + } } @@ -2,23 +2,17 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; public class GoldorTickTimer { - private static final int WIDTH = 30; - - @ConfigValue - public static boolean enableGoldorTickTimer = false; - - @ConfigValue - public static boolean inDeathTicks = true; private static int tick = 0; public static void init() { @@ -33,29 +27,29 @@ public class GoldorTickTimer { }); } - @ConfigValue - public static HUDComponent goldorTickTimer = new HUDComponent(0, 0, WIDTH, 10, 1, "Goldor Tick Timer", - () -> enableGoldorTickTimer && Location.inDungeon() && Phase.inTerminals(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + public static boolean display() { + return Floor7.enableGoldorTickTimer && Location.inDungeon() && Phase.inTerminals(); + } - int color; - double num = tick * Constants.TICK_DURATION; + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - double mod = num % 3; - if (mod < 1) { - color = Constants.GREEN_COLOR; - } else if (mod < 2) { - color = Constants.ORANGE_COLOR; - } else { - color = Constants.RED_COLOR; - } + int color; + double num = tick * Constants.TICK_DURATION; - if (inDeathTicks) num = mod; + double mod = num % 3; + if (mod < 1) { + color = Constants.GREEN_COLOR; + } else if (mod < 2) { + color = Constants.ORANGE_COLOR; + } else { + color = Constants.RED_COLOR; + } - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, WIDTH, color); + if (Floor7.inDeathTicks) num = mod; - }), () -> enableGoldorTickTimer - ); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); + + } } @@ -3,10 +3,10 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Dungeons; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.RenderPipelines; @@ -70,18 +70,6 @@ public class InvincibilityTimer { } } - @ConfigValue - public static boolean displayInvincibilityTimer = false; - - @ConfigValue - public static boolean showProcTitle = false; - - @ConfigValue - public static DisplayWhen displayWhen = DisplayWhen.ALWAYS; - - @ConfigValue - public static boolean useSprites = false; - public static void init() { Events.ON_SERVER_TICK.register(InvincibilityTimer::tick); ClientReceiveMessageEvents.GAME.register(InvincibilityTimer::detectPet); @@ -143,19 +131,19 @@ public class InvincibilityTimer { Matcher matcher = BONZO_PATTERN.matcher(string); if (matcher.matches()) { bonzoMaskTicks = BONZO_MASK_COOLDOWN; - if (showProcTitle) { + if (Dungeons.showProcTitle) { Misc.setTitle(Text.literal("Bonzo")); } } if (string.equals("Second Wind Activated! Your Spirit Mask saved your life!")) { spiritMaskTicks = SPIRIT_MASK_COOLDOWN; - if (showProcTitle) { + if (Dungeons.showProcTitle) { Misc.setTitle(Text.literal("Spirit")); } } if (string.equals("Your Phoenix Pet saved you from certain death!")) { phoenixTicks = PHOENIX_COOLDOWN; - if (showProcTitle) { + if (Dungeons.showProcTitle) { Misc.setTitle(Text.literal("Phoenix")); } } @@ -223,45 +211,43 @@ public class InvincibilityTimer { return spiritMaskTicks > 0; } - @ConfigValue - public static HUDComponent invincibilityTimer = new HUDComponent(0, 0, 110, 28, 1, "Invincibility timer", - () -> { - if (!displayInvincibilityTimer || !Location.inDungeon()) { - return false; - } - - switch (displayWhen) { - case BOSS_ONLY -> { - return Phase.inBoss(); - } - case P3_ONLY -> { - return Phase.inP3(); - } - case ALWAYS -> { - return true; - } - case USEFUL_PHASES -> { - return Phase.inP3() || Phase.inP2(); - } - case null, default -> { - return false; - } - } - }, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - - if (useSprites) { - drawSprite(drawContext, BONZO_SPRITE, x, y, bonzoMaskOn, bonzoMaskTicks, formatTimer(bonzoMaskTicks)); - drawSprite(drawContext, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, spiritMaskOn, spiritMaskTicks, formatTimer(spiritMaskTicks)); - drawSprite(drawContext, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); - - } else { - drawContext.drawText(MinecraftClient.getInstance().textRenderer, getBonzoText(), x, y, 0xffffffff, true); - drawContext.drawText(MinecraftClient.getInstance().textRenderer, getSpiritText(), x, y + TEXT_HEIGHT, 0xffffffff, true); - drawContext.drawText(MinecraftClient.getInstance().textRenderer, getPhoenixText(), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); - } - }), () -> displayInvincibilityTimer - ); + public static boolean display() { + if (!Dungeons.displayInvincibilityTimer || !Location.inDungeon()) { + return false; + } + + switch (Dungeons.displayWhen) { + case BOSS_ONLY -> { + return Phase.inBoss(); + } + case P3_ONLY -> { + return Phase.inP3(); + } + case ALWAYS -> { + return true; + } + case USEFUL_PHASES -> { + return Phase.inP3() || Phase.inP2(); + } + case null, default -> { + return false; + } + } + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + if (Dungeons.useSprites) { + drawSprite(context, BONZO_SPRITE, x, y, bonzoMaskOn, bonzoMaskTicks, formatTimer(bonzoMaskTicks)); + drawSprite(context, SPIRIT_SPRITE, x, y + SPRITE_SIZE + 1, spiritMaskOn, spiritMaskTicks, formatTimer(spiritMaskTicks)); + drawSprite(context, PHOENIX_SPRITE, x, y + (SPRITE_SIZE + 1) * 2, phoenixOn, phoenixTicks, formatTimer(phoenixTicks)); + + } else { + context.drawText(MinecraftClient.getInstance().textRenderer, getBonzoText(), x, y, 0xffffffff, true); + context.drawText(MinecraftClient.getInstance().textRenderer, getSpiritText(), x, y + TEXT_HEIGHT, 0xffffffff, true); + context.drawText(MinecraftClient.getInstance().textRenderer, getPhoenixText(), x, y + TEXT_HEIGHT * 2, 0xffffffff, true); + } + } } @@ -2,10 +2,10 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.JsonUtility; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.dungeon.PositionMessage; import blade.addon.utils.events.Events; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; @@ -14,9 +14,6 @@ import java.util.ArrayList; public class PositionMessages { - @ConfigValue - public static boolean enablePositionalMessages = false; - private static final ArrayList<PositionMessage> positionMessages = JsonUtility.readPositionalMessages("/data/positions.json"); public static void init() { @@ -32,8 +29,7 @@ public class PositionMessages { } public static void tick(MinecraftClient client) { - if (!Location.inDungeon()) return; - if (!Phase.inP3()) return; + if (!Location.inDungeon() || !Phase.inP3() || !Floor7.enablePositionalMessages) return; ClientPlayerEntity player = client.player; if (player == null) return; @@ -3,12 +3,12 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.event.player.AttackBlockCallback; @@ -16,6 +16,7 @@ import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; @@ -53,27 +54,12 @@ public class RelicTimer { private static final int GREEN_COLOR = 0xff00ff00; private static final int RED_COLOR = 0xffff0000; - private static final int WIDTH = 30; - private static final Pattern PATTERN = Pattern.compile("^(.+) picked the Corrupted (Red|Purple|Orange|Green|Blue) Relic!$"); private static long pickupTime; private static Relic pickedupRelic = null; - @ConfigValue - public static boolean enableRelicStartTimer = false; - - @ConfigValue - public static int relicSpawnTicks = 42; - - @ConfigValue - public static boolean enableRelicPlaceTime = false; - - @ConfigValue - public static boolean renderRelicHighlight = false; - - - private static int tick = relicSpawnTicks; + private static int tick = Floor7.relicSpawnTicks; public static void init() { Events.ON_SERVER_TICK.register(() -> { @@ -83,7 +69,7 @@ public class RelicTimer { Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { - tick = relicSpawnTicks; + tick = Floor7.relicSpawnTicks; pickedupRelic = null; } }); @@ -95,7 +81,7 @@ public class RelicTimer { }); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !Phase.inP5() || !enableRelicPlaceTime) return; + if (!Location.inDungeon() || !Phase.inP5() || !Floor7.enableRelicPlaceTime) return; String str = message.getString().replaceAll("§.", ""); Matcher matcher = PATTERN.matcher(str); @@ -128,7 +114,7 @@ public class RelicTimer { }); WorldRenderEvents.BEFORE_DEBUG_RENDER.register(worldRenderContext -> { - if (pickedupRelic == null || !renderRelicHighlight) return; + if (pickedupRelic == null || !Floor7.renderRelicHighlight) return; Camera camera = worldRenderContext.camera(); Vec3d cameraPos = camera.getPos(); @@ -157,7 +143,7 @@ public class RelicTimer { if (block.getBlock() != Blocks.ANVIL && block.getBlock() != Blocks.CAULDRON) return; double distance = pickedupRelic.box.getCenter().distanceTo(pos.toCenterPos()); if (distance <= 1) { - if (enableRelicPlaceTime) { + if (Floor7.enableRelicPlaceTime) { double diff = (System.currentTimeMillis() - pickupTime) / 1000.0; Misc.addChatMessage(Text.literal("The ").formatted(Formatting.GREEN) .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) @@ -170,20 +156,19 @@ public class RelicTimer { } - @ConfigValue - public static HUDComponent relicSpawnTimer = new HUDComponent(0, 0, WIDTH, 10, 1, "Relic Spawn Timer", - () -> enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > 0, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + public static boolean display() { + return Floor7.enableRelicStartTimer && Location.inDungeon() && Phase.inP5() && tick > 0; + } - int color = tick > 7 ? GREEN_COLOR : RED_COLOR; + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - double num = tick * Constants.TICK_DURATION; + int color = tick > 7 ? GREEN_COLOR : RED_COLOR; - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, WIDTH, color); + double num = tick * Constants.TICK_DURATION; - }), () -> enableRelicStartTimer - ); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), color); + } } @@ -3,14 +3,15 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -22,18 +23,8 @@ public class StormTickTimer { private static final Pattern PATTERN = Pattern.compile("^⚠ Storm is enraged! ⚠$"); private static final long DEATH_DISPLAY_DURATION = 2000; - private static final int WIDTH = 30; private static final int WARN_TICK = 20 * 20; - @ConfigValue - public static boolean enableStormTickTimer = false; - - @ConfigValue - public static boolean enableStormDeathTime = false; - - @ConfigValue - public static boolean notifyUsedSpiritMask = false; - private static int tick = 0; private static double deathTime = 0; private static long deathStartDisplayTime = 0; @@ -42,7 +33,7 @@ public class StormTickTimer { Events.ON_SERVER_TICK.register(() -> { if (Location.inDungeon() && Phase.inP2() && !Phase.stormDead()) tick++; - if (tick == WARN_TICK && notifyUsedSpiritMask && DungeonClass.isClass(DungeonClass.MAGE) && InvincibilityTimer.spiritMaskUsed()) { + if (tick == WARN_TICK && Floor7.notifyUsedSpiritMask && DungeonClass.isClass(DungeonClass.MAGE) && InvincibilityTimer.spiritMaskUsed()) { Misc.setTitle(Text.literal("Leap to arch")); } }); @@ -56,7 +47,7 @@ public class StormTickTimer { }); ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon() || !Phase.inP2() || !enableStormDeathTime) return; + if (!Location.inDungeon() || !Phase.inP2() || !Floor7.enableStormDeathTime) return; Matcher matcher = PATTERN.matcher(message.getString()); @@ -72,30 +63,30 @@ public class StormTickTimer { }); } - - @ConfigValue - public static HUDComponent stormTickTimer = new HUDComponent(0, 0, WIDTH, 10, 1, "Storm Tick Timer", - () -> enableStormTickTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - double num = tick * Constants.TICK_DURATION; + public static boolean display() { + return Floor7.enableStormTickTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead(); + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, WIDTH); + double num = tick * Constants.TICK_DURATION; - }) - ); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Constants.DECIMAL_FORMAT.format(num), x, y, component.getWidth()); - @ConfigValue - public static HUDComponent stormDeathTime = new HUDComponent(0, 0, WIDTH, 10, 1, "Storm Death Time", - () -> enableStormTickTimer && Location.inDungeon() && Phase.inP2() && !Phase.stormDead() && deathTime > 0 && deathStartDisplayTime > System.currentTimeMillis() - DEATH_DISPLAY_DURATION, - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); + } + + public static boolean displayDeathTime() { + return Floor7.enableStormDeathTime && Location.inDungeon() && Phase.inP2() && !Phase.stormDead() && deathTime > 0 && deathStartDisplayTime > System.currentTimeMillis() - DEATH_DISPLAY_DURATION; + } - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(deathTime)).formatted(Formatting.DARK_PURPLE), x, y, WIDTH); + public static void renderDeathTime(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); - }), () -> enableStormTickTimer - ); + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(deathTime)).formatted(Formatting.DARK_PURPLE), x, y, component.getWidth()); + + } } @@ -2,21 +2,19 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.config.values.Floor7; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; import config.practical.hud.HUDComponent; -import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.text.Text; public class TermStartTimer { - private static final int WIDTH = 30; private static final int TOTAL_TICKS = 100; - @ConfigValue - public static boolean enableTermStartTimer = false; private static int tick = 100; public static void init() { @@ -30,17 +28,17 @@ public class TermStartTimer { } }); } - - @ConfigValue - public static HUDComponent termStartTimer = new HUDComponent(0, 0, WIDTH, 10, 1, "Term Start Timer", - () -> enableTermStartTimer && Location.inDungeon() && Phase.inP2() && Phase.stormDead(), - ((hudComponent, drawContext) -> { - int x = hudComponent.getScaledX(); - int y = hudComponent.getScaledY(); - - double num = tick * Constants.TICK_DURATION; - RenderUtils.drawCenteredText(drawContext, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, WIDTH, 0xFFFFFF55); - - }), () -> enableTermStartTimer - ); + + public static boolean display() { + return Floor7.enableTermStartTimer && Location.inDungeon() && Phase.inP2() && Phase.stormDead(); + } + + public static void render(HUDComponent component, DrawContext context) { + int x = component.getScaledX(); + int y = component.getScaledY(); + + double num = tick * Constants.TICK_DURATION; + RenderUtils.drawCenteredText(context, MinecraftClient.getInstance().textRenderer, Text.literal(Constants.DECIMAL_FORMAT.format(num)), x, y, component.getWidth(), 0xFFFFFF55); + + } } @@ -1,6 +1,6 @@ package blade.addon.mixin; -import blade.addon.features.ExtraOptions; +import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -1,7 +1,7 @@ package blade.addon.mixin; -import blade.addon.features.ExtraOptions; import blade.addon.utils.Misc; +import blade.addon.utils.config.values.ExtraOptions; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.state.EntityRenderState; import net.minecraft.entity.Entity; …… diff 过长已截断 …… |
- added /refill - added chestCounter only in boss - added calc exposhot only in boss - added a check for if your in skyblock to some things - added some diana notifier (will get moved)查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 18 ++++++++++-------- src/main/java/blade/addon/features/DianaNotifier.java | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 9 +-------- src/main/java/blade/addon/features/dungeon/ChestCounter.java | 10 ++++++++-- src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 7 +++++-- src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 2 +- src/main/java/blade/addon/utils/Commands.java | 14 ++++++++++++++ src/main/java/blade/addon/utils/Location.java | 34 ++++++++++++++++++---------------- src/main/java/blade/addon/utils/Scheduler.java | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 21 ++++++++++++++++++--- src/main/java/blade/addon/utils/dungeon/Phase.java | 4 ++++ 12 files changed, 205 insertions(+), 41 deletions(-) @@ -13,7 +13,7 @@ loader_version=0.17.3 loom_version=1.13-SNAPSHOT # Mod Properties -mod_version=2.2.0 +mod_version=2.2.2 maven_group=blade.addon archives_base_name=blade-addons @@ -1,26 +1,27 @@ package blade.addon; +import blade.addon.features.DianaNotifier; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; -import blade.addon.features.dungeon.f7.BossWaypoints; -import blade.addon.features.dungeon.f7.CrystalSpawn; import blade.addon.features.dungeon.DeathTickTimer; import blade.addon.features.dungeon.DupeClassChecker; import blade.addon.features.dungeon.ExplosiveShot; -import blade.addon.features.dungeon.f7.DistanceToLedge; -import blade.addon.features.dungeon.f7.GoldorTickTimer; import blade.addon.features.dungeon.HidePlayers; -import blade.addon.features.dungeon.f7.InvincibilityTimer; +import blade.addon.features.dungeon.ItemHighlight; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.LeapMessage; import blade.addon.features.dungeon.MobHighlight; -import blade.addon.features.dungeon.ItemHighlight; +import blade.addon.features.dungeon.SecretSpawnTimer; +import blade.addon.features.dungeon.WarpCooldown; +import blade.addon.features.dungeon.f7.BossWaypoints; +import blade.addon.features.dungeon.f7.CrystalSpawn; +import blade.addon.features.dungeon.f7.DistanceToLedge; +import blade.addon.features.dungeon.f7.GoldorTickTimer; +import blade.addon.features.dungeon.f7.InvincibilityTimer; import blade.addon.features.dungeon.f7.PositionMessages; import blade.addon.features.dungeon.f7.RelicTimer; -import blade.addon.features.dungeon.SecretSpawnTimer; import blade.addon.features.dungeon.f7.StormTickTimer; import blade.addon.features.dungeon.f7.TermStartTimer; -import blade.addon.features.dungeon.WarpCooldown; import blade.addon.utils.Commands; import blade.addon.utils.Keybinds; import blade.addon.utils.Location; @@ -61,5 +62,6 @@ public class Bladeaddons implements ModInitializer { DistanceToLedge.init(); ItemHighlight.init(); BossWaypoints.init(); + DianaNotifier.init(); } } \ No newline at end of file @@ -0,0 +1,65 @@ +package blade.addon.features; + +import blade.addon.utils.Misc; +import blade.addon.utils.Scheduler; +import blade.addon.utils.events.Events; +import config.practical.manager.ConfigValue; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.sound.SoundEvents; +import net.minecraft.text.Text; + +public class DianaNotifier { + + @ConfigValue + public static boolean sendSound = false; + @ConfigValue + public static boolean sendWaypoint = false; + @ConfigValue + public static boolean checkHarpy = false; + @ConfigValue + public static boolean checkBull = false; + @ConfigValue + public static boolean checkNymph = false; + + public static void init() { + Events.ON_GAME_MESSAGE.register(message-> { + String string = message.getString(); + String lowerCase = string.toLowerCase(); + if (!lowerCase.contains("you dug out a")) return; + if (checkHarpy) { + check(lowerCase, "harpy"); + } + + if (checkBull) { + check(lowerCase, "cretan bull"); + + } + + if (checkNymph) { + check(lowerCase, "stranded nymph"); + } + }); + } + + private static void check(String string, String name) { + if (string.contains(name)) { + MinecraftClient client = MinecraftClient.getInstance(); + Misc.setTitle(Text.literal(name)); + ClientPlayerEntity player = client.player; + if (player == null) { + Misc.addChatMessage(Text.literal("Player is somehow null")); + return; + } + + if (sendSound) { + Scheduler.scheduleSound(SoundEvents.BLOCK_NOTE_BLOCK_PLING.value(), 2, 1); + + } + + if (sendWaypoint) { + Scheduler.scheduleCommand("pc x: " + (int) player.getX() + ", y: " + (int) player.getY() + ", z: " + (int) player.getZ()); + } + } + } +} @@ -21,8 +21,6 @@ public class AutoRequeue { private static final Pattern LEFT_PATTERN = Pattern.compile("has left the party.$"); private static final int MESSAGE_OFFSET = 2; - private static final int NO_RANK_OFFSET = 12; - private static final HashMap<String, Text> playerHashMap = new HashMap<>(); @@ -46,16 +44,11 @@ public class AutoRequeue { if (!matcher.find()) return; int startOfMessage = string.indexOf(":"); - int startOfUsername = string.indexOf("]"); if (startOfMessage == -1 || startOfMessage + MESSAGE_OFFSET >= string.length()) return; - if (startOfUsername == -1) { - startOfUsername = NO_RANK_OFFSET; - } - String realMessage = string.substring(startOfMessage + MESSAGE_OFFSET); - String username = string.substring(startOfUsername + MESSAGE_OFFSET, startOfMessage - MESSAGE_OFFSET); + String username = string.substring(0, startOfMessage - MESSAGE_OFFSET); if (playerHashMap.containsKey(username)) { matcher = UNDT_PATTERN.matcher(realMessage); @@ -1,6 +1,7 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; import config.practical.manager.ConfigValue; @@ -18,7 +19,8 @@ public class ChestCounter { @ConfigValue public static boolean displayChestCount = false; - + @ConfigValue + public static boolean onlyAfterRunOver = false; @ConfigValue public static boolean sendChestWarning = false; @@ -67,7 +69,11 @@ public class ChestCounter { @ConfigValue public static HUDComponent chestCounter = new HUDComponent(0, 0, 100, 10, 1, "Chest count", - () -> displayChestCount && Location.inDungeon(), + () -> + { + if ((onlyAfterRunOver && !Phase.runOver())) return false; + return displayChestCount && Location.inDungeon(); + }, ((hudComponent, drawContext) -> { int x = hudComponent.getScaledX(); int y = hudComponent.getScaledY(); @@ -2,6 +2,7 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.Misc; +import blade.addon.utils.dungeon.Phase; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.text.Text; @@ -18,11 +19,13 @@ public class ExplosiveShot { @ConfigValue public static boolean calculateCriticalHit = false; + @ConfigValue + public static boolean onlyInBoss = false; public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon()) return; - if (!calculateCriticalHit) return; + if (!Location.inDungeon() || !calculateCriticalHit) return; + if (onlyInBoss && !Phase.inBoss()) return; String string = message.getString(); @@ -23,7 +23,7 @@ public class StormTickTimer { private static final long DEATH_DISPLAY_DURATION = 2000; private static final int WIDTH = 30; - private static final int WARN_TICK = 23 * 20; + private static final int WARN_TICK = 20 * 20; @ConfigValue public static boolean enableStormTickTimer = false; @@ -35,6 +35,18 @@ public class Commands { .then(ClientCommandManager.literal("ij").executes(context -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.INFLATABLE_JERRY, 64, 64))) + .then(ClientCommandManager.literal("refill") + .executes( + context -> { + FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.ENDER_PEARL, 16, 16); + Scheduler.scheduleTask(() -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.SUPERBOOM_TNT, 64, 64), 40); + Scheduler.scheduleTask(() -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.INFLATABLE_JERRY, 64, 64), 80); + return Constants.SUCCESS; + } + + )) + + .then(ClientCommandManager.literal("waypoint") .then(ClientCommandManager.literal("add") @@ -141,6 +153,8 @@ public class Commands { ) ) + + .executes(commandContext -> Scheduler.scheduleScreen(Config.createScreen(null))) ); @@ -1,36 +1,32 @@ package blade.addon.utils; import blade.addon.utils.events.Events; +import net.hypixel.data.type.ServerType; import net.hypixel.modapi.HypixelModAPI; import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacket; public enum Location { NONE, DUNGEON, - DUNGEON_HUB; + DUNGEON_HUB, + PRIVATE_ISLAND, + HUB; private static Location currentLocation = Location.NONE; + private static boolean inSkyblock = false; public static void init() { - /* - System.out.println(packet.getMap().toString()); - System.out.println(packet.getLobbyName().toString()); - System.out.println(packet.getMode().toString()); - System.out.println(packet.getServerName()); - System.out.println(packet.getServerType().toString()); - - [STDOUT]: Optional[Private Island] - [STDOUT]: Optional.empty - [STDOUT]: Optional[dynamic] - [STDOUT]: mini87DF - [STDOUT]: Optional[SKYBLOCK] - */ - HypixelModAPI instance = HypixelModAPI.getInstance(); + instance.createHandler(ClientboundLocationPacket.class, packet -> packet.getMap().ifPresent(map -> { + + if (packet.getServerType().isPresent()) { + ServerType serverType = packet.getServerType().get(); + inSkyblock = serverType.getName().equals("SkyBlock"); + } + System.out.println(map.toUpperCase().replace(" ", "_")); - instance.createHandler(ClientboundLocationPacket.class, packet -> packet.getMap().ifPresent(map -> { try { currentLocation = Location.valueOf(map.toUpperCase().replace(" ", "_")); } catch (IllegalArgumentException ignored) { @@ -48,10 +44,16 @@ public enum Location { } public static boolean in(Location location) { + if (!inSkyblock) return false; return currentLocation == location; } public static boolean inDungeon() { + if (!inSkyblock) return false; return currentLocation == Location.DUNGEON; } + + public static boolean inSkyblock() { + return inSkyblock; + } } \ No newline at end of file @@ -3,11 +3,31 @@ package blade.addon.utils; import com.mojang.brigadier.Command; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.sound.SoundEvent; + +import java.util.concurrent.CopyOnWriteArrayList; public class Scheduler { private static Screen scheduledScreen = null; private static int screenTicks = 0; + private static SoundEvent scheduledSound = null; + private static float scheduledVolume = 0; + private static float scheduledPitch = 0; + private static String scheduledCommand = null; + + static class Task { + Runnable task; + int delay; + + public Task(Runnable task, int delay) { + this.task = task; + this.delay = delay; + } + } + + private static final CopyOnWriteArrayList<Task> tasks = new CopyOnWriteArrayList<>(); public static void init() { ClientTickEvents.START_CLIENT_TICK.register(minecraftClient -> { @@ -18,6 +38,32 @@ public class Scheduler { scheduledScreen = null; } } + + if (scheduledSound != null) { + ClientPlayerEntity player = minecraftClient.player; + if (player != null) { + player.playSound(scheduledSound, scheduledVolume, scheduledPitch); + scheduledSound = null; + } + } + + if (scheduledCommand != null) { + ClientPlayerEntity player = minecraftClient.player; + if (player != null && player.networkHandler != null) { + player.networkHandler.sendChatCommand(scheduledCommand); + scheduledCommand = null; + } + } + + for (int i = tasks.size() - 1; i >= 0; i--) { + Task task = tasks.get(i); + task.delay--; + if (task.delay <= 0) { + minecraftClient.execute(task.task); + tasks.remove(i); + } + } + }); } @@ -27,4 +73,18 @@ public class Scheduler { screenTicks = 1; return Command.SINGLE_SUCCESS; } + + public static void scheduleSound(SoundEvent soundEvent, float volume, float pitch) { + scheduledSound = soundEvent; + scheduledVolume = volume; + scheduledPitch = pitch; + } + + public static void scheduleCommand(String command) { + scheduledCommand = command; + } + + public static void scheduleTask(Runnable runnable, int ticks) { + tasks.add(new Task(runnable, ticks)); + } } @@ -1,5 +1,6 @@ package blade.addon.utils.config; +import blade.addon.features.DianaNotifier; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; import blade.addon.features.dungeon.ItemHighlight; @@ -46,7 +47,7 @@ public class Config { List.of(StormTickTimer.class, GoldorTickTimer.class, Phase.class, LeapMessage.class, PositionMessages.class, TermStartTimer.class, Split.class, DeathTickTimer.class, ExplosiveShot.class, InvincibilityTimer.class, WarpCooldown.class, DupeClassChecker.class, HidePlayers.class, CrystalSpawn.class, KeyNotifier.class, RelicTimer.class, AutoRequeue.class, MobHighlight.class, ChestCounter.class, SecretSpawnTimer.class, DistanceToLedge.class, ItemHighlight.class, ExtraOptions.class, - BossWaypoints.class)); + BossWaypoints.class, DianaNotifier.class)); public static Screen createScreen(Screen parent) { ConfigurableScreen screen = new ConfigurableScreen(TITLE, parent, manager); @@ -75,15 +76,20 @@ public class Config { ConfigSection chests = new ConfigSection(Text.literal("Croesus")); chests.add(new ConfigBool(Text.literal("Display current chest count"), () -> ChestCounter.displayChestCount, bool -> ChestCounter.displayChestCount = bool)); + chests.add(new ConfigBool(Text.literal("Only display after run is over"), () -> ChestCounter.onlyAfterRunOver, bool -> ChestCounter.onlyAfterRunOver = bool)); chests.add(new ConfigBool(Text.literal("Send chest count warning"), () -> ChestCounter.sendChestWarning, bool -> ChestCounter.sendChestWarning = bool)); chests.add(new ConfigInt(Text.literal("Warning at chest"), () -> ChestCounter.chestWarningCount, num -> ChestCounter.chestWarningCount = num, 1, 1, 60)); dungeons.add(chests); - dungeons.add(new ConfigBool(Text.literal("Leap message"), () -> LeapMessage.enableLeapMessages, bool -> LeapMessage.enableLeapMessages = bool)); dungeons.add(new ConfigBool(Text.literal("Auto requeue"), () -> AutoRequeue.enableAutoRequeue, bool -> AutoRequeue.enableAutoRequeue = bool)); dungeons.add(new ConfigBool(Text.literal("Death tick timer (not accurate currently)"), () -> DeathTickTimer.enableDeathTickTimer, bool -> DeathTickTimer.enableDeathTickTimer = bool)); - dungeons.add(new ConfigBool(Text.literal("calculate explosive shot"), () -> ExplosiveShot.calculateCriticalHit, bool -> ExplosiveShot.calculateCriticalHit = bool)); + + ConfigSection expo = new ConfigSection(Text.literal("Explosive shot")); + expo.add(new ConfigBool(Text.literal("calculate explosive shot"), () -> ExplosiveShot.calculateCriticalHit, bool -> ExplosiveShot.calculateCriticalHit = bool)); + expo.add(new ConfigBool(Text.literal("Only in boss"), () -> ExplosiveShot.onlyInBoss, bool -> ExplosiveShot.onlyInBoss = bool)); + dungeons.add(expo); + dungeons.add(new ConfigBool(Text.literal("Notification on key spawn"), () -> KeyNotifier.enableKeyNotifier, bool -> KeyNotifier.enableKeyNotifier = bool)); dungeons.add(new ConfigBool(Text.literal("Secret spawn timer"), () -> SecretSpawnTimer.enableSecretSpawnTimer, bool -> SecretSpawnTimer.enableSecretSpawnTimer = bool)); dungeons.add(new ConfigBool(Text.literal("Item highlight"), () -> ItemHighlight.highlightItems, bool -> ItemHighlight.highlightItems = bool)); @@ -173,6 +179,15 @@ public class Config { extra.add(new ConfigBool(Text.literal("Disable ability on cooldown sound"), () -> ExtraOptions.disableAbilityCooldownSound, bool -> ExtraOptions.disableAbilityCooldownSound = bool)); extra.add(new ConfigBool(Text.literal("Hide dead entities"), () -> ExtraOptions.hideDeadEntities, bool -> ExtraOptions.hideDeadEntities = bool)); + ConfigSection diana = new ConfigSection(Text.literal("Diana notifications")); + diana.add(new ConfigBool(Text.literal("Send Sound"), () -> DianaNotifier.sendSound, bool -> DianaNotifier.sendSound = bool)); + diana.add(new ConfigBool(Text.literal("Send Waypoint"), () -> DianaNotifier.sendWaypoint, bool -> DianaNotifier.sendWaypoint = bool)); + diana.add(new ConfigBool(Text.literal("Check Harpy"), () -> DianaNotifier.checkHarpy, bool -> DianaNotifier.checkHarpy = bool)); + diana.add(new ConfigBool(Text.literal("Check Bull"), () -> DianaNotifier.checkBull, bool -> DianaNotifier.checkBull = bool)); + diana.add(new ConfigBool(Text.literal("Check Nymph"), () -> DianaNotifier.checkNymph, bool -> DianaNotifier.checkNymph = bool)); + + extra.add(diana); + screen.addCategory(extra); @@ -257,6 +257,10 @@ public class Phase { return currentPhase == 9 && inFloor7; } + public static boolean runOver() { + return runOver; + } + @ConfigValue public static HUDComponent splitTimer = new HUDComponent(0, 0, Split.SPLIT_LENGTH, 100, 1, "Splits", () -> Location.inDungeon() && enableSplits && Phase.runStarted(), |
- added boss waypoints - fixed reque working even if someone leaves the party - made the chestcounter update in the dungeon hub while opening chests - added a title on use for InvincibilityTimer - added a warning if spirit mask is used for py - added /dh command for dungeon hub查看变更gradle.properties | 2 +- src/main/java/blade/addon/Bladeaddons.java | 2 + src/main/java/blade/addon/features/dungeon/AutoRequeue.java | 27 +++++---- src/main/java/blade/addon/features/dungeon/ChestCounter.java | 7 +-- src/main/java/blade/addon/features/dungeon/DupeClassChecker.java | 7 +++ src/main/java/blade/addon/features/dungeon/ExplosiveShot.java | 6 +- src/main/java/blade/addon/features/dungeon/MobHighlight.java | 62 +++++++++++++++----- src/main/java/blade/addon/features/dungeon/f7/BossWaypoints.java | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/features/dungeon/f7/InvincibilityTimer.java | 103 ++++++++++++++++++-------------- src/main/java/blade/addon/features/dungeon/f7/RelicTimer.java | 5 +- src/main/java/blade/addon/features/dungeon/f7/StormTickTimer.java | 14 ++++- src/main/java/blade/addon/mixin/FireMixin.java | 10 ++-- src/main/java/blade/addon/utils/Commands.java | 115 ++++++++++++++++++++++++++++++++++++ src/main/java/blade/addon/utils/Constants.java | 3 + src/main/java/blade/addon/utils/Debug.java | 28 +++++++++ src/main/java/blade/addon/utils/Misc.java | 33 +++++++++++ src/main/java/blade/addon/utils/Waypoint.java | 60 +++++++++++++++++++ src/main/java/blade/addon/utils/config/Config.java | 12 +++- src/main/java/blade/addon/utils/dungeon/FillHelper.java | 12 ++-- src/main/java/blade/addon/utils/dungeon/Phase.java | 188 ++++++++++++++++++++++++++++++++++------------------------ src/main/java/blade/addon/utils/dungeon/Split.java | 68 +++++++++++---------- src/main/java/blade/addon/utils/rendering/RenderPipelines.java | 20 +++---- 22 files changed, 831 insertions(+), 216 deletions(-) @@ -13,7 +13,7 @@ loader_version=0.17.3 loom_version=1.13-SNAPSHOT # Mod Properties -mod_version=2.1.0 +mod_version=2.2.0 maven_group=blade.addon archives_base_name=blade-addons @@ -2,6 +2,7 @@ package blade.addon; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; +import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.CrystalSpawn; import blade.addon.features.dungeon.DeathTickTimer; import blade.addon.features.dungeon.DupeClassChecker; @@ -59,5 +60,6 @@ public class Bladeaddons implements ModInitializer { SecretSpawnTimer.init(); DistanceToLedge.init(); ItemHighlight.init(); + BossWaypoints.init(); } } \ No newline at end of file @@ -1,12 +1,12 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.events.Events; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.text.Text; import java.util.HashMap; @@ -18,6 +18,7 @@ public class AutoRequeue { private static final Pattern PATTERN = Pattern.compile("^§9Party §8>"); private static final Pattern DT_PATTERN = Pattern.compile("!dt"); private static final Pattern UNDT_PATTERN = Pattern.compile("!undt"); + private static final Pattern LEFT_PATTERN = Pattern.compile("has left the party.$"); private static final int MESSAGE_OFFSET = 2; private static final int NO_RANK_OFFSET = 12; @@ -28,11 +29,19 @@ public class AutoRequeue { @ConfigValue public static boolean enableAutoRequeue = false; + private static boolean someoneLeft = false; + public static void init() { ClientReceiveMessageEvents.GAME.register((message, overlay) -> { if (!Location.inDungeon() && !enableAutoRequeue) return; String string = message.getString(); - Matcher matcher = PATTERN.matcher(string); + Matcher matcher = LEFT_PATTERN.matcher(string); + if (matcher.find()) { + someoneLeft = true; + return; + } + + matcher = PATTERN.matcher(string); if (!matcher.find()) return; @@ -63,16 +72,13 @@ public class AutoRequeue { }); Events.ON_RUN_END.register(() -> { - if (!enableAutoRequeue) return; + if (!enableAutoRequeue || someoneLeft) return; if (playerHashMap.isEmpty()) { - ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); - if (networkHandler == null) return; - networkHandler.sendChatCommand("instancerequeue"); + Misc.executeCommand("instancerequeue"); } else { + Misc.addChatMessage(Text.literal("Downtime reasons:")); ChatHud chathud = MinecraftClient.getInstance().inGameHud.getChatHud(); - chathud.addMessage(Text.literal("Downtime reasons:")); - playerHashMap.forEach((name, text) -> chathud.addMessage(text)); @@ -80,9 +86,8 @@ public class AutoRequeue { }); Events.ON_LOCATION_CHANGE.register(newLocation -> { - if (Location.inDungeon()) { - playerHashMap.clear(); - } + playerHashMap.clear(); + someoneLeft = false; }); } } @@ -28,19 +28,16 @@ public class ChestCounter { private static int chestDisplayCount = 0; private static int countedChests = 0; private static boolean hasUpdatedData = false; - private static boolean readPlayerEntryEvents = false; public static void init() { Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.in(Location.DUNGEON_HUB)) { - readPlayerEntryEvents = true; hasUpdatedData = false; } }); Events.ON_PLAYER_ENTRY.register(receivedEntry -> { - if (!readPlayerEntryEvents || hasUpdatedData) return; - if (receivedEntry == null) return; + if (receivedEntry == null || !Location.in(Location.DUNGEON_HUB)) return; Text text = receivedEntry.displayName(); if (text == null) return; @@ -77,8 +74,6 @@ public class ChestCounter { if (hasUpdatedData) { drawContext.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Chests: " + Math.min(chestDisplayCount + countedChests, 60)), x, y, 0xffffffff, true); - } else if(readPlayerEntryEvents) { - drawContext.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("Updating"), x, y, 0xffffd700, true); } else { drawContext.drawText(MinecraftClient.getInstance().textRenderer, Text.literal("go to the dungeon hub"), x, y, 0xffff0000, true); @@ -2,6 +2,7 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; @@ -39,6 +40,12 @@ public class DupeClassChecker { hasDuplicateClass = hasDuplicateClasses(); }); + + Events.ON_LOCATION_CHANGE.register(location -> { + if (Location.inDungeon()) { + hasDuplicateClass = false; + } + }); } private static boolean hasDuplicateClasses() { @@ -1,10 +1,9 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -39,8 +38,7 @@ public class ExplosiveShot { double damagePerEntity = amountNum / countNum; - InGameHud gameHud = MinecraftClient.getInstance().inGameHud; - gameHud.getChatHud().addMessage( + Misc.addChatMessage( Text.literal("Explosive shot did ").formatted(Formatting.GREEN) .append(Text.literal(FORMAT.format(damagePerEntity)).formatted(Formatting.YELLOW)) .append(Text.literal(" damage per enemy.").formatted(Formatting.GREEN)) @@ -1,6 +1,7 @@ package blade.addon.features.dungeon; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; @@ -187,7 +188,8 @@ public class MobHighlight { possibleEntities.clear(); }); - WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::Render); + WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::renderFilled); + WorldRenderEvents.AFTER_ENTITIES.register(MobHighlight::renderOutline); } private static void testArmourStand(ArmorStandEntity armorStand) { @@ -300,6 +302,8 @@ public class MobHighlight { private static boolean isARealPlayer(Entity entity) { if (entity instanceof PlayerEntity player) { + if (Misc.isClientPlayer(player)) return true; + ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); if (networkHandler == null) return false; @@ -406,8 +410,45 @@ public class MobHighlight { return box; } - private static void Render(WorldRenderContext worldRenderContext) { + private static void renderFilled(WorldRenderContext worldRenderContext) { + if (!mobHighlight || dontRenderHighlight) return; + if (!renderFilled()) return; + Camera camera = worldRenderContext.camera(); + Vec3d cameraPos = camera.getPos(); + MatrixStack matrixStack = worldRenderContext.matrixStack(); + if (matrixStack == null) return; + matrixStack.push(); + matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + + VertexConsumerProvider consumers = worldRenderContext.consumers(); + if (consumers == null) return; + VertexConsumer filledConsumer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); + + trackedMobs.forEach((entity, mobType) -> { + + if (entity.isInvisible() && MobHighlight.dontShowInvisibleMobs && entity instanceof PlayerEntity) return; + + double tickProgress = worldRenderContext.tickCounter().getTickProgress(false); + double x = MathHelper.lerp(tickProgress, entity.lastRenderX, entity.getX()); + double y = MathHelper.lerp(tickProgress, entity.lastRenderY, entity.getY()); + double z = MathHelper.lerp(tickProgress, entity.lastRenderZ, entity.getZ()); + + Box box = getBox(entity, x, y, z); + + + int filledColor = MobHighlight.getFilledColor(entity); + float[] rgba = RenderUtils.toFloats(filledColor); + VertexRendering.drawFilledBox(matrixStack, filledConsumer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); + }); + + + matrixStack.pop(); + + } + + private static void renderOutline(WorldRenderContext worldRenderContext) { if (!mobHighlight || dontRenderHighlight) return; + if (!renderOutline()) return; Camera camera = worldRenderContext.camera(); Vec3d cameraPos = camera.getPos(); MatrixStack matrixStack = worldRenderContext.matrixStack(); @@ -417,8 +458,7 @@ public class MobHighlight { VertexConsumerProvider consumers = worldRenderContext.consumers(); if (consumers == null) return; - VertexConsumer filledBuffer = consumers.getBuffer(RenderLayers.FILLED_ENTITY_LAYER); - VertexConsumer outlineBuffer = consumers.getBuffer(RenderLayers.OUTLINE_ENTITY_LAYER); + VertexConsumer outlineConsumer = consumers.getBuffer(RenderLayers.OUTLINE_ENTITY_LAYER); trackedMobs.forEach((entity, mobType) -> { @@ -432,16 +472,10 @@ public class MobHighlight { Box box = getBox(entity, x, y, z); - if (MobHighlight.renderFilled()) { - int filledColor = MobHighlight.getFilledColor(entity); - float[] rgba = RenderUtils.toFloats(filledColor); - VertexRendering.drawFilledBox(matrixStack, filledBuffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, rgba[0], rgba[1], rgba[2], rgba[3]); - } - if (MobHighlight.renderOutline()) { - int outlineColor = MobHighlight.getOutlineColor(entity); - float[] rgba = RenderUtils.toFloats(outlineColor); - VertexRendering.drawBox(matrixStack, outlineBuffer, box, rgba[0], rgba[1], rgba[2], rgba[3]); - } + + int outlineColor = MobHighlight.getOutlineColor(entity); + float[] rgba = RenderUtils.toFloats(outlineColor); + VertexRendering.drawBox(matrixStack, outlineConsumer, box, rgba[0], rgba[1], rgba[2], rgba[3]); }); @@ -0,0 +1,263 @@ +package blade.addon.features.dungeon.f7; + +import blade.addon.utils.Constants; +import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.Waypoint; +import blade.addon.utils.dungeon.Phase; +import blade.addon.utils.rendering.RenderLayers; +import blade.addon.utils.rendering.RenderUtils; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import config.practical.manager.ConfigValue; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Formatting; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.concurrent.CopyOnWriteArrayList; + +public class BossWaypoints { + + private static final Text ON = Text.literal("ON").formatted(Formatting.GREEN); + private static final Text OFF = Text.literal("OFF").formatted(Formatting.RED); + + private static final String filePath = "./config/" + Constants.NAMESPACE + "-waypoints.json"; + private static final String WAYPOINTS_NAME = "waypoints"; + + public static final CopyOnWriteArrayList<Waypoint> waypoints = new CopyOnWriteArrayList<>(); + + @ConfigValue + public static boolean enableBossWaypoints = false; + + @ConfigValue + public static int nextWaypointColor = 0xff00F7F7; + + @ConfigValue + public static boolean nextWaypointThroughWall = false; + + private static boolean ignoreBoss = false; + private static boolean place = false; + + public static void init() { + load(); + //needs separate consumers because of depth checking or smth + WorldRenderEvents.BEFORE_ENTITIES.register(BossWaypoints::renderThroughWall); + WorldRenderEvents.BEFORE_ENTITIES.register(BossWaypoints::render); + UseBlockCallback.EVENT.register(BossWaypoints::onBlock); + } + + public static boolean isInValidArea() { + if (!enableBossWaypoints) return false; + if (ignoreBoss) return true; + + return Location.inDungeon() && Phase.inBoss(); + } + + public static boolean getPlace() { + return place; + } + + public static void setPlace(boolean shouldPlace) { + place = shouldPlace; + Misc.addChatMessage(Text.literal("Edit mode: ").append(place ? ON : OFF)); + } + + public static void setIgnoreBoss(boolean shouldIgnoreBoss) { + ignoreBoss = shouldIgnoreBoss; + Misc.addChatMessage(Text.literal("Ignore boss: ").append(ignoreBoss ? ON : OFF)); + } + + public static void togglePlace() { + setPlace(!place); + } + + public static void toggleIgnoreBoss() { + setIgnoreBoss(!ignoreBoss); + } + + public static void attemptAddWaypoint(double x, double y, double z, double dx, double dy, double dz) { + if (waypointExists(x, y, z)) return; + addWaypoint(x, y, z, dx, dy, dz); + } + + private static void addWaypoint(double x, double y, double z, double dx, double dy, double dz) { + float[] colorAsFloat = RenderUtils.toFloats(nextWaypointColor); + waypoints.add(new Waypoint(x, y, z, dx, dy, dz, colorAsFloat[0], colorAsFloat[1], colorAsFloat[2], colorAsFloat[3], nextWaypointThroughWall)); + save(); + } + + public static Waypoint getWaypoint(double x, double y, double z) { + for (Waypoint waypoint : waypoints) { + if (waypoint.samePosition(x, y, z)) return waypoint; + } + return null; + } + + public static void removeWaypoints(double x, double y, double z, double range) { + for (int i = waypoints.size() - 1; i >= 0; i--) { + if (waypoints.get(i).inRange(x, y, z, range)) { + waypoints.remove(i); + } + } + save(); + } + + public static void removeWaypoint(double x, double y, double z) { + Waypoint waypoint = getWaypoint(x, y, z); + if (waypoint == null) return; + waypoints.remove(waypoint); + save(); + } + + private static ActionResult onBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) { + if (!isInValidArea() || !Misc.isClientPlayer(playerEntity)) return ActionResult.PASS; + if (hand == Hand.OFF_HAND) return ActionResult.PASS; + + BlockPos pos = blockHitResult.getBlockPos(); + + int x = pos.getX(); + int y = pos.getY(); + int z = pos.getZ(); + + if (!place) return ActionResult.PASS; + + Waypoint waypoint = getWaypoint(x, y, z); + if (waypoint == null) { + addWaypoint(pos.getX(), pos.getY(), pos.getZ(), 1, 1, 1); + } else { + waypoints.remove(waypoint); + } + + return ActionResult.PASS; + } + + private static void renderThroughWall(WorldRenderContext worldRenderContext) { + if (!isInValidArea()) return; + + Camera camera = worldRenderContext.camera(); + Vec3d cameraPos = camera.getPos(); + MatrixStack matrixStack = worldRenderContext.matrixStack(); + if (matrixStack == null) return; + matrixStack.push(); + matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + + VertexConsumerProvider consumers = worldRenderContext.consumers(); + if (consumers == null) return; + VertexConsumer consumer = consumers.getBuffer(RenderLayers.FILLED_LAYER); + + waypoints.forEach(waypoint -> { + if (waypoint.isThroughWall()) { + waypoint.Render(consumer, matrixStack); + } + }); + matrixStack.pop(); + + } + + private static void render(WorldRenderContext worldRenderContext) { + if (!isInValidArea()) return; + + Camera camera = worldRenderContext.camera(); + Vec3d cameraPos = camera.getPos(); + MatrixStack matrixStack = worldRenderContext.matrixStack(); + if (matrixStack == null) return; + matrixStack.push(); + matrixStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); + + VertexConsumerProvider consumers = worldRenderContext.consumers(); + if (consumers == null) return; + VertexConsumer consumer = consumers.getBuffer(RenderLayers.THROUGH_WALL_FILLED_LAYER); + + waypoints.forEach(waypoint -> { + if (!waypoint.isThroughWall()) { + waypoint.Render(consumer, matrixStack); + } + }); + matrixStack.pop(); + + } + + public static boolean waypointExists(double x, double y, double z) { + for (Waypoint waypoint : waypoints) { + if (waypoint.samePosition(x, y, z)) return true; + } + return false; + } + + public static void save() { + + JsonObject obj = new JsonObject(); + Gson gson = new Gson(); + + obj.add(WAYPOINTS_NAME, gson.toJsonTree(waypoints)); + + JsonElement tree = gson.toJsonTree(obj); + try (FileWriter writer = new FileWriter(filePath)) { + writer.write(tree.toString()); + } catch (IOException ignored) { + + } + } + + public static void load() { + String jsonContent; + try { + jsonContent = new String(Files.readAllBytes(Paths.get(filePath))); + } catch (IOException ignored) { + return; + } + Gson gson = new Gson(); + JsonObject object = gson.fromJson(jsonContent, JsonObject.class); + JsonElement element = object.get(WAYPOINTS_NAME); + + if (!element.isJsonArray()) return; + JsonArray array = element.getAsJsonArray(); + + for (JsonElement waypointElement : array) { + JsonObject waypoint = waypointElement.getAsJsonObject(); + + try { + if (!waypoint.has("x") || !waypoint.has("y") || !waypoint.has("z") + || !waypoint.has("dx") || !waypoint.has("dy") || !waypoint.has("dz") + || !waypoint.has("r") || !waypoint.has("g") || !waypoint.has("b") || !waypoint.has("a") + || !waypoint.has("throughWall")) continue; + + double x = waypoint.get("x").getAsDouble(); + double y = waypoint.get("y").getAsDouble(); + double z = waypoint.get("z").getAsDouble(); + double dx = waypoint.get("dx").getAsDouble(); + double dy = waypoint.get("dy").getAsDouble(); + double dz = waypoint.get("dz").getAsDouble(); + + float r = waypoint.get("r").getAsFloat(); + float g = waypoint.get("g").getAsFloat(); + float b = waypoint.get("b").getAsFloat(); + float a = waypoint.get("a").getAsFloat(); + + boolean throughWall = waypoint.get("throughWall").getAsBoolean(); + waypoints.add(new Waypoint(x, y, z, dx, dy, dz, r, g, b, a, throughWall)); + } catch (NumberFormatException e) { + System.out.println("msg: " + e.getMessage()); + } + } + } +} @@ -2,6 +2,7 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import config.practical.hud.HUDComponent; @@ -10,6 +11,7 @@ import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.RenderPipelines; import net.minecraft.client.gui.DrawContext; +import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; @@ -33,8 +35,6 @@ public class InvincibilityTimer { private static final int SPRITE_SIZE = TEXT_HEIGHT; private static final Pattern BONZO_PATTERN = Pattern.compile("^Your (?:\\S+ )?Bonzo's Mask saved your life!$"); - private static final Pattern SPIRIT_PATTERN = Pattern.compile("^Second Wind Activated! Your Spirit Mask saved your life!$"); - private static final Pattern PHOENIX_PATTERN = Pattern.compile("^Your Phoenix Pet saved you from certain death!$"); private static final Pattern BONZO_ON_HEAD_PATTERN = Pattern.compile("Bonzo's Mask"); private static final Pattern SPIRIT_ON_HEAD_PATTERN = Pattern.compile("Spirit Mask"); @@ -73,6 +73,9 @@ public class InvincibilityTimer { @ConfigValue public static boolean displayInvincibilityTimer = false; + @ConfigValue + public static boolean showProcTitle = false; + @ConfigValue public static DisplayWhen displayWhen = DisplayWhen.ALWAYS; @@ -80,43 +83,9 @@ public class InvincibilityTimer { public static boolean useSprites = false; public static void init() { - Events.ON_SERVER_TICK.register(() -> { - bonzoMaskTicks = Math.max(0, bonzoMaskTicks - 1); - spiritMaskTicks = Math.max(0, spiritMaskTicks - 1); - phoenixTicks = Math.max(0, phoenixTicks - 1); - }); - - Events.ON_SLOT_CHANGE.register(((slot, item) -> { - if (slot == HEAD_SLOT && Location.inDungeon()) { - Text text = item.getCustomName(); - if (text == null) return; - String string = text.getString(); - - Matcher matcher = BONZO_ON_HEAD_PATTERN.matcher(string); - bonzoMaskOn = matcher.find(); - - matcher = SPIRIT_ON_HEAD_PATTERN.matcher(string); - spiritMaskOn = matcher.find(); - - - } - })); - ClientReceiveMessageEvents.GAME.register((message, overlay) -> { - if (!Location.inDungeon()) return; - String string = message.getString().replaceAll("§.", ""); - Matcher matcher = MANUAL_EQUIP_PET_PATTERN.matcher(string); - if (matcher.find()) { - String petName = matcher.group(1); - phoenixOn = petName.equals("Phoenix"); - } - - matcher = RULE_EQUIP_PET_PATTERN.matcher(string); - if (matcher.find()) { - String petName = matcher.group(1); - phoenixOn = petName.equals("Phoenix"); - } - - }); + Events.ON_SERVER_TICK.register(InvincibilityTimer::tick); + ClientReceiveMessageEvents.GAME.register(InvincibilityTimer::detectPet); + Events.ON_SLOT_CHANGE.register(InvincibilityTimer::detectHelmet); Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { @@ -133,20 +102,62 @@ public class InvincibilityTimer { }); } - public static void parseMessage(Text message) { + private static void tick() { + bonzoMaskTicks = Math.max(0, bonzoMaskTicks - 1); + spiritMaskTicks = Math.max(0, spiritMaskTicks - 1); + phoenixTicks = Math.max(0, phoenixTicks - 1); + } + + private static void detectPet(Text message, boolean overlay) { + if (!Location.inDungeon()) return; + String string = message.getString().replaceAll("§.", ""); + Matcher matcher = MANUAL_EQUIP_PET_PATTERN.matcher(string); + if (matcher.find()) { + String petName = matcher.group(1); + phoenixOn = petName.equals("Phoenix"); + } + + matcher = RULE_EQUIP_PET_PATTERN.matcher(string); + if (matcher.find()) { + String petName = matcher.group(1); + phoenixOn = petName.equals("Phoenix"); + } + } + + private static void detectHelmet(int slot, ItemStack item) { + if (slot != HEAD_SLOT || !Location.inDungeon()) return; + Text text = item.getCustomName(); + if (text == null) return; + String string = text.getString(); + + Matcher matcher = BONZO_ON_HEAD_PATTERN.matcher(string); + bonzoMaskOn = matcher.find(); + + matcher = SPIRIT_ON_HEAD_PATTERN.matcher(string); + spiritMaskOn = matcher.find(); + } + + private static void parseMessage(Text message) { String string = message.getString(); Matcher matcher = BONZO_PATTERN.matcher(string); if (matcher.matches()) { bonzoMaskTicks = BONZO_MASK_COOLDOWN; + if (showProcTitle) { + Misc.setTitle(Text.literal("Bonzo")); + } } - matcher = SPIRIT_PATTERN.matcher(string); - if (matcher.matches()) { + if (string.equals("Second Wind Activated! Your Spirit Mask saved your life!")) { spiritMaskTicks = SPIRIT_MASK_COOLDOWN; + if (showProcTitle) { + Misc.setTitle(Text.literal("Spirit")); + } } - matcher = PHOENIX_PATTERN.matcher(string); - if (matcher.matches()) { + if (string.equals("Your Phoenix Pet saved you from certain death!")) { phoenixTicks = PHOENIX_COOLDOWN; + if (showProcTitle) { + Misc.setTitle(Text.literal("Phoenix")); + } } } @@ -208,6 +219,10 @@ public class InvincibilityTimer { } + public static boolean spiritMaskUsed() { + return spiritMaskTicks > 0; + } + @ConfigValue public static HUDComponent invincibilityTimer = new HUDComponent(0, 0, 110, 28, 1, "Invincibility timer", () -> { @@ -2,6 +2,7 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderLayers; @@ -15,7 +16,6 @@ import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.render.Camera; import net.minecraft.client.render.VertexConsumer; @@ -159,8 +159,7 @@ public class RelicTimer { if (distance <= 1) { if (enableRelicPlaceTime) { double diff = (System.currentTimeMillis() - pickupTime) / 1000.0; - InGameHud gameHud = MinecraftClient.getInstance().inGameHud; - gameHud.getChatHud().addMessage(Text.literal("The ").formatted(Formatting.GREEN) + Misc.addChatMessage(Text.literal("The ").formatted(Formatting.GREEN) .append(Text.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color)) .append(" relic was placed in ").formatted(Formatting.GREEN) .append(Text.literal(Constants.DECIMAL_FORMAT.format(diff) + "s.").formatted(Formatting.YELLOW))); @@ -2,6 +2,8 @@ package blade.addon.features.dungeon.f7; import blade.addon.utils.Constants; import blade.addon.utils.Location; +import blade.addon.utils.Misc; +import blade.addon.utils.dungeon.DungeonClass; import blade.addon.utils.dungeon.Phase; import blade.addon.utils.events.Events; import blade.addon.utils.rendering.RenderUtils; @@ -9,7 +11,6 @@ import config.practical.hud.HUDComponent; import config.practical.manager.ConfigValue; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.hud.InGameHud; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -22,6 +23,7 @@ public class StormTickTimer { private static final long DEATH_DISPLAY_DURATION = 2000; private static final int WIDTH = 30; + private static final int WARN_TICK = 23 * 20; @ConfigValue public static boolean enableStormTickTimer = false; @@ -29,6 +31,9 @@ public class StormTickTimer { @ConfigValue public static boolean enableStormDeathTime = false; + @ConfigValue + public static boolean notifyUsedSpiritMask = false; + private static int tick = 0; private static double deathTime = 0; private static long deathStartDisplayTime = 0; @@ -36,6 +41,10 @@ public class StormTickTimer { public static void init() { Events.ON_SERVER_TICK.register(() -> { if (Location.inDungeon() && Phase.inP2() && !Phase.stormDead()) tick++; + + if (tick == WARN_TICK && notifyUsedSpiritMask && DungeonClass.isClass(DungeonClass.MAGE) && InvincibilityTimer.spiritMaskUsed()) { + Misc.setTitle(Text.literal("Leap to arch")); + } }); Events.ON_LOCATION_CHANGE.register(newLocation -> { @@ -54,8 +63,7 @@ public class StormTickTimer { if (matcher.find()) { deathTime = (tick * Constants.TICK_DURATION); deathStartDisplayTime = System.currentTimeMillis(); - InGameHud gameHud = MinecraftClient.getInstance().inGameHud; - gameHud.getChatHud().addMessage( + Misc.addChatMessage( Text.literal("Storm died at: ").formatted(Formatting.GREEN) .append(Text.literal(Constants.DECIMAL_FORMAT.format(deathTime) + "s").formatted(Formatting.YELLOW)) .append(Text.literal(".").formatted(Formatting.GREEN)) @@ -1,11 +1,11 @@ package blade.addon.mixin; import blade.addon.features.ExtraOptions; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; +import blade.addon.utils.Misc; import net.minecraft.client.render.entity.EntityRenderer; import net.minecraft.client.render.entity.state.EntityRenderState; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -17,12 +17,10 @@ public class FireMixin<T extends Entity, S extends EntityRenderState> { @Inject(method = "updateRenderState", at = @At("TAIL")) public void test(T entity, S state, float tickProgress, CallbackInfo ci) { - ClientPlayerEntity clientPlayer = MinecraftClient.getInstance().player; - if (clientPlayer != null) { - if (clientPlayer == entity && ExtraOptions.hideFireInf5) { + if (entity instanceof PlayerEntity player && ExtraOptions.hideFireInf5) { + if (Misc.isClientPlayer(player)) { state.onFire = false; } } - } } @@ -1,12 +1,16 @@ package blade.addon.utils; +import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.utils.config.Config; import blade.addon.utils.dungeon.FillHelper; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.command.CommandRegistryAccess; import org.jetbrains.annotations.NotNull; @@ -31,8 +35,119 @@ public class Commands { .then(ClientCommandManager.literal("ij").executes(context -> FillHelper.fillItem(MinecraftClient.getInstance(), FillHelper.INFLATABLE_JERRY, 64, 64))) + .then(ClientCommandManager.literal("waypoint") + + .then(ClientCommandManager.literal("add") + .then(ClientCommandManager.argument("x", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("y", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("z", DoubleArgumentType.doubleArg()) + .executes(context -> { + double x = DoubleArgumentType.getDouble(context, "x"); + double y = DoubleArgumentType.getDouble(context, "y"); + double z = DoubleArgumentType.getDouble(context, "z"); + + BossWaypoints.attemptAddWaypoint(x, y, z, 1, 1, 1); + return Constants.SUCCESS; + }) + + .then(ClientCommandManager.argument("dx", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("dy", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("dz", DoubleArgumentType.doubleArg()) + .executes(context -> { + double x = DoubleArgumentType.getDouble(context, "x"); + double y = DoubleArgumentType.getDouble(context, "y"); + double z = DoubleArgumentType.getDouble(context, "z"); + double dx = DoubleArgumentType.getDouble(context, "dx"); + double dy = DoubleArgumentType.getDouble(context, "dy"); + double dz = DoubleArgumentType.getDouble(context, "dz"); + BossWaypoints.attemptAddWaypoint(x, y, z, dx, dy, dz); + return Constants.SUCCESS; + }) + + + ) + ) + ) + + ) + ) + ) + .executes(context -> { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return 0; + + BossWaypoints.attemptAddWaypoint(player.getBlockX(), player.getBlockY(), player.getBlockZ(), 1, 1, 1); + return Constants.SUCCESS; + }) + + ) + .then(ClientCommandManager.literal("remove") + + .then(ClientCommandManager.argument("radius", DoubleArgumentType.doubleArg()) + .executes(context -> { + double r = DoubleArgumentType.getDouble(context, "radius"); + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if (player == null) return Constants.FAIL; + BossWaypoints.removeWaypoints(player.getX(), player.getY(), player.getZ(), r); + return Constants.SUCCESS; + })) + + .then(ClientCommandManager.argument("x", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("y", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("z", DoubleArgumentType.doubleArg()) + .then(ClientCommandManager.argument("radius", DoubleArgumentType.doubleArg()) + .executes(context -> { + double x = DoubleArgumentType.getDouble(context, "x"); + double y = DoubleArgumentType.getDouble(context, "y"); + double z = DoubleArgumentType.getDouble(context, "z"); + double radius = DoubleArgumentType.getDouble(context, "radius"); + + BossWaypoints.removeWaypoints(x, y, z, radius); + return Constants.SUCCESS; + })) + + + .executes(context -> { + double x = DoubleArgumentType.getDouble(context, "x"); + double y = DoubleArgumentType.getDouble(context, "y"); + double z = DoubleArgumentType.getDouble(context, "z"); + + BossWaypoints.removeWaypoint(x, y, z); + return Constants.SUCCESS; + }) + ) + ) + ) + + ) + + .then(ClientCommandManager.literal("editMode").executes(context -> { + BossWaypoints.togglePlace(); + return Constants.SUCCESS; + })) + + .then(ClientCommandManager.literal("ignoreBoss").executes(context -> { + BossWaypoints.toggleIgnoreBoss(); + return Constants.SUCCESS; + })) + + ) + + .then(ClientCommandManager.literal("debug") + .then(ClientCommandManager.argument("option", StringArgumentType.greedyString()).executes(context -> { + String option = StringArgumentType.getString(context, "option"); + return Debug.parseOption(option); + }) + ) + ) + .executes(commandContext -> Scheduler.scheduleScreen(Config.createScreen(null))) ); + + dispatcher.register(ClientCommandManager.literal("dh").executes(context -> { + Misc.executeCommand("warp dungeon_hub"); + return Constants.SUCCESS; + })); } } @@ -10,4 +10,7 @@ public class Constants { public static final int GREEN_COLOR = 0xff00ff00; public static final int ORANGE_COLOR = 0xffDAA06D; public static final int RED_COLOR = 0xffff0000; + + public static final int FAIL = 0; + public static final int SUCCESS = 1; } @@ -0,0 +1,28 @@ +package blade.addon.utils; + +import blade.addon.utils.dungeon.Phase; +import net.minecraft.text.Text; + +public class Debug { + + public static int parseOption(String string) { + + switch (string) { + case "RUN_INFO": + sendRunInfo(); + break; + } + + + return Constants.SUCCESS; + } + + public static void sendRunInfo() { + Misc.addChatMessage(Text.literal("Phase: " + Phase.getPhase())); + Misc.addChatMessage(Text.literal("Section: " + Phase.getSection())); + Misc.addChatMessage(Text.literal("Gateblown: " + Phase.isGateBlownUp())); + Misc.addChatMessage(Text.literal("Terms done: " + Phase.isTermsDone())); + Misc.addChatMessage(Text.literal("In floor 7: " + Phase.isInFloor7())); + } + +} @@ -0,0 +1,33 @@ +package blade.addon.utils; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; + +public class Misc { + public static final MinecraftClient instance = MinecraftClient.getInstance(); + + public static boolean isClientPlayer(PlayerEntity entity) { + ClientPlayerEntity clientPlayer = instance.player; + if (clientPlayer == null) return false; + return clientPlayer == entity; + } + + public static void addChatMessage(Text text) { + InGameHud gameHud = MinecraftClient.getInstance().inGameHud; + gameHud.getChatHud().addMessage(text); + } + + public static void setTitle(Text text) { + MinecraftClient.getInstance().inGameHud.setTitle(text); + } + + public static void executeCommand(String string) { + ClientPlayNetworkHandler networkHandler = MinecraftClient.getInstance().getNetworkHandler(); + if (networkHandler == null) return; + networkHandler.sendChatCommand(string); + } +} @@ -0,0 +1,60 @@ +package blade.addon.utils; + +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexRendering; +import net.minecraft.client.util.math.MatrixStack; + +public class Waypoint { + private final double x, y, z, dx, dy, dz; + private final float r, g, b, a; + private final boolean throughWall; + + + public Waypoint(double x, double y, double z, double dx, double dy, double dz, float r, float g, float b, float a, boolean throughWall) { + this.x = x; + this.y = y; + this.z = z; + this.dx = dx; + this.dy = dy; + this.dz = dz; + this.r = r; + this.g = g; + this.b = b; + this.a = a; + this.throughWall = throughWall; + } + + public boolean samePosition(double x, double y, double z) { + return this.x == x && this.y == y && this.z == z; + } + + public boolean inRange(double x, double y, double z, double range) { + double distanceSquared = (this.x - x) * (this.x - x) + (this.y - y) * (this.y - y) + (this.z - z) * (this.z - z); + return distanceSquared < range * range; + } + + public boolean isThroughWall() { + return throughWall; + } + + public void Render(VertexConsumer consumer, MatrixStack matrixStack) { + VertexRendering.drawFilledBox(matrixStack, consumer, x, y, z, x + dx, y + dy, z + dz, r, g, b, a); + } + + @Override + public String toString() { + return "Waypoint{" + + "x=" + x + + ", y=" + y + + ", z=" + z + + ", dx=" + dx + + ", dy=" + dy + + ", dz=" + dz + + ", r=" + r + + ", g=" + g + + ", b=" + b + + ", a=" + a + + ", throughWall=" + throughWall + + '}'; + } +} @@ -3,6 +3,7 @@ package blade.addon.utils.config; import blade.addon.features.dungeon.AutoRequeue; import blade.addon.features.dungeon.ChestCounter; import blade.addon.features.dungeon.ItemHighlight; +import blade.addon.features.dungeon.f7.BossWaypoints; import blade.addon.features.dungeon.f7.CrystalSpawn; import blade.addon.features.dungeon.DeathTickTimer; import blade.addon.features.dungeon.DupeClassChecker; @@ -44,7 +45,8 @@ public class Config { public static final ConfigManager manager = new ConfigManager("./config/" + Constants.NAMESPACE + ".json", List.of(StormTickTimer.class, GoldorTickTimer.class, Phase.class, LeapMessage.class, PositionMessages.class, TermStartTimer.class, Split.class, DeathTickTimer.class, ExplosiveShot.class, InvincibilityTimer.class, WarpCooldown.class, DupeClassChecker.class, HidePlayers.class, CrystalSpawn.class, - KeyNotifier.class, RelicTimer.class, AutoRequeue.class, MobHighlight.class, ChestCounter.class, SecretSpawnTimer.class, DistanceToLedge.class, ItemHighlight.class, ExtraOptions.class)); + KeyNotifier.class, RelicTimer.class, AutoRequeue.class, MobHighlight.class, ChestCounter.class, SecretSpawnTimer.class, DistanceToLedge.class, ItemHighlight.class, ExtraOptions.class, + BossWaypoints.class)); public static Screen createScreen(Screen parent) { ConfigurableScreen screen = new ConfigurableScreen(TITLE, parent, manager); @@ -60,6 +62,7 @@ public class Config { invincibility.add(new ConfigBool(Text.literal("Enable invincibility display"), () -> InvincibilityTimer.displayInvincibilityTimer, bool -> InvincibilityTimer.displayInvincibilityTimer = bool)); invincibility.add(new ConfigOptions<>(Text.literal("Display when"), InvincibilityTimer.DisplayWhen.values(), () -> InvincibilityTimer.displayWhen, when -> InvincibilityTimer.displayWhen = when)); invincibility.add(new ConfigBool(Text.literal("Use sprites"), () -> InvincibilityTimer.useSprites, bool -> InvincibilityTimer.useSprites = bool)); + invincibility.add(new ConfigBool(Text.literal("Show title on proc"), () -> InvincibilityTimer.showProcTitle, bool -> InvincibilityTimer.showProcTitle = bool)); dungeons.add(invincibility); @@ -87,6 +90,12 @@ public class Config { screen.addCategory(dungeons); ConfigCategory floor7 = new ConfigCategory("Floor 7"); + ConfigSection waypoints = new ConfigSection(Text.literal("Waypoints")); + waypoints.add(new ConfigBool(Text.literal("Enable boss waypoints"), () -> BossWaypoints.enableBossWaypoints, bool -> BossWaypoints.enableBossWaypoints = bool)); + waypoints.add(new ConfigBool(Text.literal("Enable placing waypoints"), BossWaypoints::getPlace, BossWaypoints::setPlace)); + waypoints.add(new ConfigColor(Text.literal("Next waypoint color"), () -> BossWaypoints.nextWaypointColor, color -> BossWaypoints.nextWaypointColor = color, "next-waypoint-color", true)); + waypoints.add(new ConfigBool(Text.literal("Next waypoint no depth check"), () -> BossWaypoints.nextWaypointThroughWall, bool -> BossWaypoints.nextWaypointThroughWall = bool)); + floor7.add(waypoints); ConfigSection maxor = new ConfigSection(Text.literal("Maxor")); maxor.add(new ConfigBool(Text.literal("Crystal Spawn Time"), () -> CrystalSpawn.enableCrystalSpawnTime, bool -> CrystalSpawn.enableCrystalSpawnTime = bool)); @@ -96,6 +105,7 @@ public class Config { storm.add(new ConfigBool(Text.literal("Storm Tick timer"), () -> StormTickTimer.enableStormTickTimer, bool -> StormTickTimer.enableStormTickTimer = bool)); storm.add(new ConfigBool(Text.literal("First Death time"), () -> StormTickTimer.enableStormDeathTime, bool -> StormTickTimer.enableStormDeathTime = bool)); storm.add(new ConfigBool(Text.literal("Distance to ledge"), () -> DistanceToLedge.displayDistanceToLedge, bool -> DistanceToLedge.displayDistanceToLedge = bool)); + storm.add(new ConfigBool(Text.literal("Warn if spirit mask is used"), () -> StormTickTimer.notifyUsedSpiritMask, bool -> StormTickTimer.notifyUsedSpiritMask = bool)); floor7.add(storm); ConfigSection goldor = new ConfigSection(Text.literal("Goldor")); @@ -1,5 +1,6 @@ package blade.addon.utils.dungeon; +import blade.addon.utils.Constants; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.inventory.Inventory; @@ -11,9 +12,6 @@ public class FillHelper { public static final String SUPERBOOM_TNT = "Superboom TNT"; public static final String INFLATABLE_JERRY = "Inflatable Jerry"; - private static final int FAIL = 0; - private static final int SUCCESS = 1; - /** * @param client to get access to the player and networkHandler * @param itemName Name of item @@ -24,7 +22,7 @@ public class FillHelper { public static int fillItem(MinecraftClient client, String itemName, int minThreshold, int maxCount) { ClientPlayerEntity player = client.player; - if (player == null) return FAIL; + if (player == null) return Constants.FAIL; Inventory inventory = player.getInventory(); @@ -41,16 +39,16 @@ public class FillHelper { if (highestCount > currentCount) { currentCount = highestCount; - if (highestCount >= maxCount) return FAIL; + if (highestCount >= maxCount) return Constants.FAIL; } } } - if (minThreshold < currentCount) return FAIL; + if (minThreshold < currentCount) return Constants.FAIL; int itemsToGive = maxCount - currentCount; player.networkHandler.sendChatCommand("gfs " + itemName + " " + itemsToGive); - return SUCCESS; + return Constants.SUCCESS; } } @@ -1,7 +1,9 @@ package blade.addon.utils.dungeon; +import blade.addon.utils.Constants; import blade.addon.utils.JsonUtility; import blade.addon.utils.Location; +import blade.addon.utils.Misc; import blade.addon.utils.events.Events; import blade.addon.utils.events.interfaces.PhaseEvent; import blade.addon.utils.events.interfaces.RunEndEvent; @@ -10,6 +12,7 @@ import config.practical.manager.ConfigValue; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import java.util.ArrayList; import java.util.HashMap; @@ -20,11 +23,7 @@ public class Phase { private static final Pattern END_PATTERN = Pattern.compile("^\\s*☠ Defeated (.+) in 0?([\\dhms ]+)\\s*(\\(NEW RECORD!\\))?$"); private static final Pattern SEARCH_PATTERN = Pattern.compile("^ ⏣ The Catacombs .*$"); - private static final Pattern STORM_KILL_PATTERN = Pattern.compile("^\\[BOSS] Storm: I should have known that I stood no chance\\.$"); - private static final Pattern GATE_BLOWN_PATTERN = Pattern.compile("^The gate has been destroyed!$"); private static final Pattern TERMINALS_DONE_PATTERN = Pattern.compile("(activated|completed) (a terminal|a device|a lever)! \\((\\d)/(\\d)\\)$"); - private static final Pattern CORE_OPENING_PATTERN = Pattern.compile("^The Core entrance is opening!$"); - private static final Split DUMMY_SPLIT = new Split("test split", "if this is called idk", "if this is called idk", 43690); @@ -61,47 +60,47 @@ public class Phase { Events.ON_LOCATION_CHANGE.register(newLocation -> { if (Location.inDungeon()) { - currentSplits = null; - floor = null; - currentPhase = -1; - inFloor7 = false; - stormDead = false; - runOver = false; - currentSection = 0; - termsDone = false; - gateBlownUp = false; + reset(); } }); - Events.ON_GAME_MESSAGE.register(text -> { - if (Location.inDungeon()) { - Phase.parseMessage(text); - } - }); + Events.ON_GAME_MESSAGE.register(Phase::parseGameMessage); + Events.ON_TEAM.register(Phase::detectFloor); + } - Events.ON_TEAM.register(text -> { - if (!Location.inDungeon() || floor != null) return; + private static void detectFloor(String line) { + if (!Location.inDungeon() || floor != null) return; - Matcher matcher = SEARCH_PATTERN.matcher(text); - if (!matcher.find()) return; - int start = text.indexOf("("); - int end = text.indexOf(")"); - floor = text.substring(start + 1, end); + Matcher matcher = SEARCH_PATTERN.matcher(line); + if (!matcher.find()) return; + int start = line.indexOf("("); + int end = line.indexOf(")"); + floor = line.substring(start + 1, end); - currentSplits = FLOOR_SPLITS.get(floor); - if (currentSplits!= null) { - for (Split split : currentSplits) { - split.reset(); - } - } - if (floor != null) { - if (floor.contains("7")) inFloor7 = true; + currentSplits = FLOOR_SPLITS.get(floor); + if (currentSplits!= null) { + for (Split split : currentSplits) { + split.reset(); } - }); + } + if (floor != null) { + if (floor.contains("7")) inFloor7 = true; + } } + private static void reset() { + currentSplits = null; + floor = null; + currentPhase = -1; + inFloor7 = false; + stormDead = false; + runOver = false; + currentSection = 0; + termsDone = false; + gateBlownUp = false; + } - public static void parseMessage(Text message) { + public static void parseGameMessage(Text message) { if (!Location.inDungeon()) return; String string = message.getString(); if (currentSplits == null) return; @@ -131,59 +130,97 @@ public class Phase { Matcher matcher = END_PATTERN.matcher(string); if (matcher.find()) { - runOver = true; - currentPhase = currentSplits.size(); - - for (Split split : currentSplits) { - split.end(); - } - - if (Events.ON_RUN_END.hasListeners()) { - Events.ON_RUN_END.listeners.forEach(RunEndEvent::onRunEnd); - } + endRun(); } if (inP2()) { - matcher = STORM_KILL_PATTERN.matcher(string); - if (matcher.find()) { - stormDead = true; - currentSection = 1; - } + …… diff 过长已截断 …… |
- fixed leap hiding only in boss not working - moved hide dead entities查看变更src/main/java/blade/addon/Bladeaddons.java | 4 ++--
src/main/java/blade/addon/features/ExtraOptions.java | 3 +++
src/main/java/blade/addon/features/dungeon/{HideEntities.java => HidePlayers.java} | 6 ++----
src/main/java/blade/addon/mixin/RenderMixin.java | 7 ++++---
src/main/java/blade/addon/utils/config/Config.java | 20 ++++++++++----------
5 files changed, 21 insertions(+), 19 deletions(-)@@ -8,7 +8,7 @@ import blade.addon.features.dungeon.DupeClassChecker; import blade.addon.features.dungeon.ExplosiveShot; import blade.addon.features.dungeon.f7.DistanceToLedge; import blade.addon.features.dungeon.f7.GoldorTickTimer; -import blade.addon.features.dungeon.HideEntities; +import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.f7.InvincibilityTimer; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.LeapMessage; @@ -48,7 +48,7 @@ public class Bladeaddons implements ModInitializer { LeapMessage.init(); ExplosiveShot.init(); DupeClassChecker.init(); - HideEntities.init(); + HidePlayers.init(); CrystalSpawn.init(); KeyNotifier.init(); RelicTimer.init(); @@ -13,6 +13,9 @@ public class ExtraOptions { @ConfigValue public static boolean disableAbilityCooldownSound = true; + @ConfigValue + public static boolean hideDeadEntities = false; + public static void init() { } @@ -7,7 +7,7 @@ import config.practical.manager.ConfigValue; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.math.Vec3d; -public class HideEntities { +public class HidePlayers { private static final int HIDE_DURATION = 3 * 1000; private static final double DISTANCE = 3; @@ -17,9 +17,6 @@ public class HideEntities { private static long startTime; private static boolean justLeapt = false; - @ConfigValue - public static boolean hideDeadEntities = false; - @ConfigValue public static boolean hideAfterLeap = false; @@ -41,6 +38,7 @@ public class HideEntities { public static boolean testHideAtLeap() { if (!hideAfterLeap || !justLeapt) return false; + if (!Phase.inBoss() && hideOnlyInBoss) return false; if (System.currentTimeMillis() - startTime >= HIDE_DURATION) { justLeapt = false; @@ -1,6 +1,7 @@ package blade.addon.mixin; -import blade.addon.features.dungeon.HideEntities; +import blade.addon.features.ExtraOptions; +import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.ItemHighlight; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; @@ -24,11 +25,11 @@ public class RenderMixin { if (clientPlayer != null) { if (player.getId() == clientPlayer.getId()) return; } - cir.setReturnValue(!HideEntities.shouldHidePlayers(player)); + cir.setReturnValue(!HidePlayers.shouldHidePlayers(player)); } - if (!entity.isAlive() && HideEntities.hideDeadEntities) { + if (!entity.isAlive() && ExtraOptions.hideDeadEntities) { cir.setReturnValue(false); } @@ -9,7 +9,7 @@ import blade.addon.features.dungeon.DupeClassChecker; import blade.addon.features.dungeon.ExplosiveShot; import blade.addon.features.dungeon.f7.DistanceToLedge; import blade.addon.features.dungeon.f7.GoldorTickTimer; -import blade.addon.features.dungeon.HideEntities; +import blade.addon.features.dungeon.HidePlayers; import blade.addon.features.dungeon.f7.InvincibilityTimer; import blade.addon.features.dungeon.KeyNotifier; import blade.addon.features.dungeon.LeapMessage; @@ -43,7 +43,7 @@ public class Config { private static final Text TITLE = Text.literal("Blade Addons"); public static final ConfigManager manager = new ConfigManager("./config/" + Constants.NAMESPACE + ".json", List.of(StormTickTimer.class, GoldorTickTimer.class, Phase.class, LeapMessage.class, PositionMessages.class, TermStartTimer.class, Split.class, DeathTickTimer.class, ExplosiveShot.class, - InvincibilityTimer.class, WarpCooldown.class, DupeClassChecker.class, HideEntities.class, CrystalSpawn.class, + InvincibilityTimer.class, WarpCooldown.class, DupeClassChecker.class, HidePlayers.class, CrystalSpawn.class, KeyNotifier.class, RelicTimer.class, AutoRequeue.class, MobHighlight.class, ChestCounter.class, SecretSpawnTimer.class, DistanceToLedge.class, ItemHighlight.class, ExtraOptions.class)); public static Screen createScreen(Screen parent) { @@ -63,14 +63,12 @@ public class Config { dungeons.add(invincibility); - ConfigSection hideAfterLeap = new ConfigSection(Text.literal("Hide Entities")); - hideAfterLeap.add(new ConfigBool(Text.literal("Hide on leap"), () -> HideEntities.hideAfterLeap, bool -> HideEntities.hideAfterLeap = bool)); - hideAfterLeap.add(new ConfigBool(Text.literal("Hide only in boss"), () -> HideEntities.hideOnlyInBoss, bool -> HideEntities.hideOnlyInBoss = bool)); - hideAfterLeap.add(new ConfigBool(Text.literal("Hide at SS"), () -> HideEntities.hideAtSS, bool -> HideEntities.hideAtSS = bool)); - hideAfterLeap.add(new ConfigBool(Text.literal("SS only hides before terms"), () -> HideEntities.hideBeforeTermsOnly, bool -> HideEntities.hideBeforeTermsOnly = bool)); - hideAfterLeap.add(new ConfigBool(Text.literal("Hide dead entities"), () -> HideEntities.hideDeadEntities, bool -> HideEntities.hideDeadEntities = bool)); - - dungeons.add(hideAfterLeap); + ConfigSection hidePlayers = new ConfigSection(Text.literal("Hide Players")); + hidePlayers.add(new ConfigBool(Text.literal("Hide on leap"), () -> HidePlayers.hideAfterLeap, bool -> HidePlayers.hideAfterLeap = bool)); + hidePlayers.add(new ConfigBool(Text.literal("Hide only in boss"), () -> HidePlayers.hideOnlyInBoss, bool -> HidePlayers.hideOnlyInBoss = bool)); + hidePlayers.add(new ConfigBool(Text.literal("Hide at SS"), () -> HidePlayers.hideAtSS, bool -> HidePlayers.hideAtSS = bool)); + hidePlayers.add(new ConfigBool(Text.literal("SS only hides before terms"), () -> HidePlayers.hideBeforeTermsOnly, bool -> HidePlayers.hideBeforeTermsOnly = bool)); + dungeons.add(hidePlayers); ConfigSection chests = new ConfigSection(Text.literal("Croesus")); chests.add(new ConfigBool(Text.literal("Display current chest count"), () -> ChestCounter.displayChestCount, bool -> ChestCounter.displayChestCount = bool)); @@ -163,6 +161,8 @@ public class Config { extra.add(new ConfigBool(Text.literal("Disable fire in f5"), () -> ExtraOptions.hideFireInf5, bool -> ExtraOptions.hideFireInf5 = bool)); extra.add(new ConfigBool(Text.literal("Hide arrows stuck to entities"), () -> ExtraOptions.hideStuckArrows, bool -> ExtraOptions.hideStuckArrows = bool)); extra.add(new ConfigBool(Text.literal("Disable ability on cooldown sound"), () -> ExtraOptions.disableAbilityCooldownSound, bool -> ExtraOptions.disableAbilityCooldownSound = bool)); + extra.add(new ConfigBool(Text.literal("Hide dead entities"), () -> ExtraOptions.hideDeadEntities, bool -> ExtraOptions.hideDeadEntities = bool)); + screen.addCategory(extra); |