Skip to content

Commit

Permalink
Fix Glow (#1050)
Browse files Browse the repository at this point in the history
* Fix Glow

* Remove cache
  • Loading branch information
AzureAaron authored Nov 16, 2024
1 parent f39f793 commit 96d7cc8
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 53 deletions.
31 changes: 31 additions & 0 deletions src/main/java/de/hysky/skyblocker/mixins/WorldRendererMixin.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package de.hysky.skyblocker.mixins;

import org.spongepowered.asm.mixin.Final;
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.ModifyVariable;
Expand All @@ -17,6 +19,7 @@
import de.hysky.skyblocker.skyblock.entity.MobBoundingBoxes;
import de.hysky.skyblocker.skyblock.entity.MobGlow;
import de.hysky.skyblocker.skyblock.slayers.SlayerEntitiesGlow;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.DefaultFramebufferSet;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.entity.Entity;
Expand All @@ -25,7 +28,30 @@
@Mixin(WorldRenderer.class)
public class WorldRendererMixin {
@Shadow
@Final
private MinecraftClient client;
@Shadow
@Final
private DefaultFramebufferSet framebufferSet;
@Unique
private boolean atLeastOneMobHasCustomGlow;

@ModifyExpressionValue(method = "getEntitiesToRender", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;hasOutline(Lnet/minecraft/entity/Entity;)Z"))
private boolean skyblocker$setupEntityOutlineFramebufferIfCustomGlow(boolean original, @Local Entity entity) {
boolean hasCustomGlow = MobGlow.shouldMobGlow(entity);

if (hasCustomGlow) atLeastOneMobHasCustomGlow = true;

return original || hasCustomGlow;
}

@Inject(method = "method_62214",
slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;canDrawEntityOutlines()Z")),
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gl/Framebuffer;clear()V", ordinal = 0, shift = At.Shift.AFTER)
)
private void skyblocker$copyFramebufferDepth2AdjustGlowVisibility(CallbackInfo ci) {
if (atLeastOneMobHasCustomGlow) framebufferSet.entityOutlineFramebuffer.get().copyDepthFrom(client.getFramebuffer());
}

@ModifyExpressionValue(method = "renderEntities", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;hasOutline(Lnet/minecraft/entity/Entity;)Z"))
private boolean skyblocker$shouldMobGlow(boolean original, @Local Entity entity, @Share("hasCustomGlow") LocalBooleanRef hasCustomGlow) {
Expand Down Expand Up @@ -54,4 +80,9 @@ public class WorldRendererMixin {
);
}
}

@Inject(method = "render", at = @At("TAIL"))
private void skyblocker$resetCustomGlowBool(CallbackInfo ci) {
atLeastOneMobHasCustomGlow = false;
}
}
54 changes: 2 additions & 52 deletions src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.hysky.skyblocker.skyblock.entity;

import com.google.common.collect.Streams;
import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.config.configs.SlayersConfig;
import de.hysky.skyblocker.skyblock.crimson.dojo.DojoManager;
Expand All @@ -14,7 +13,6 @@
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.SlayerUtils;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ArmorStandEntity;
Expand All @@ -28,63 +26,23 @@
import net.minecraft.world.World;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class MobGlow {

/**
* The Nukekubi head texture id is eb07594e2df273921a77c101d0bfdfa1115abed5b9b2029eb496ceba9bdbb4b3.
*/
public static final String NUKEKUBI_HEAD_TEXTURE = "eyJ0aW1lc3RhbXAiOjE1MzQ5NjM0MzU5NjIsInByb2ZpbGVJZCI6ImQzNGFhMmI4MzFkYTRkMjY5NjU1ZTMzYzE0M2YwOTZjIiwicHJvZmlsZU5hbWUiOiJFbmRlckRyYWdvbiIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0=";
private static final long GLOW_CACHE_DURATION = 50;
private static final long PLAYER_CAN_SEE_CACHE_DURATION = 100;
private static final ConcurrentHashMap<Entity, CacheEntry> glowCache = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<Entity, CacheEntry> canSeeCache = new ConcurrentHashMap<>();

@Init
public static void init() {
Scheduler.INSTANCE.scheduleCyclic(MobGlow::clearCache, 300 * 20);
}
private static final String NUKEKUBI_HEAD_TEXTURE = "eyJ0aW1lc3RhbXAiOjE1MzQ5NjM0MzU5NjIsInByb2ZpbGVJZCI6ImQzNGFhMmI4MzFkYTRkMjY5NjU1ZTMzYzE0M2YwOTZjIiwicHJvZmlsZU5hbWUiOiJFbmRlckRyYWdvbiIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0=";

public static boolean shouldMobGlow(Entity entity) {

long currentTime = System.currentTimeMillis();

CacheEntry cachedGlow = glowCache.get(entity);
if (cachedGlow == null || (currentTime - cachedGlow.timestamp) > GLOW_CACHE_DURATION) {
boolean shouldGlow = computeShouldMobGlow(entity);
glowCache.put(entity, new CacheEntry(shouldGlow, currentTime));
cachedGlow = glowCache.get(entity);
}

return cachedGlow.value && playerCanSee(entity, currentTime);
}


/**
* Checks if the player can see the entity.
* Has "True sight" within a certain aura, but since name tags exist I think this is fine...
*/
private static boolean playerCanSee(Entity entity, long currentTime) {

CacheEntry canSee = canSeeCache.get(entity);
if (canSee == null || (currentTime - canSee.timestamp) > PLAYER_CAN_SEE_CACHE_DURATION) {
boolean playerCanSee = entity.distanceTo(MinecraftClient.getInstance().player) <= 20 || MinecraftClient.getInstance().player.canSee(entity);
canSeeCache.put(entity, new CacheEntry(playerCanSee, currentTime));
return playerCanSee;
}

return canSee.value;
return computeShouldMobGlow(entity);
}

private static boolean computeShouldMobGlow(Entity entity) {

// Dungeons
if (Utils.isInDungeons()) {
String name = entity.getName().getString();

return switch (entity) {

// Minibosses
case PlayerEntity p when (name.equals("Lost Adventurer") || name.equals("Shadow Assassin") || name.equals("Diamond Guy")) && !DungeonManager.getBoss().isFloor(4) -> SkyblockerConfigManager.get().dungeons.starredMobGlow;
case PlayerEntity p when entity.getId() == LividColor.getCorrectLividId() -> LividColor.shouldGlow(name);
Expand All @@ -101,7 +59,6 @@ private static boolean computeShouldMobGlow(Entity entity) {
}

return switch (entity) {

// Rift Blobbercyst
case PlayerEntity p when Utils.isInTheRift() && p.getName().getString().equals("Blobbercyst ") -> SkyblockerConfigManager.get().otherLocations.rift.blobbercystGlow;

Expand Down Expand Up @@ -193,11 +150,4 @@ public static int getGlowColor(Entity entity) {
private static boolean isNukekubiHead(ArmorStandEntity entity) {
return Streams.stream(entity.getArmorItems()).map(ItemUtils::getHeadTexture).anyMatch(headTexture -> headTexture.contains(NUKEKUBI_HEAD_TEXTURE));
}

private record CacheEntry(boolean value, long timestamp) {}

private static void clearCache() {
canSeeCache.clear();
glowCache.clear();
}
}
2 changes: 1 addition & 1 deletion src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@
"skyblocker.config.dungeons.starredMobBoundingBoxes.@Tooltip": "Draws the bounding boxes of starred mobs.",

"skyblocker.config.dungeons.starredMobGlow": "Starred Mob Glow",
"skyblocker.config.dungeons.starredMobGlow.@Tooltip": "Applies the glowing effect to starred mobs that are visible.\n\nWARNING: This feature utilises ray casting on entities which may have an impact on performance.",
"skyblocker.config.dungeons.starredMobGlow.@Tooltip": "Applies the glowing effect to starred mobs that are visible.\n\nNote that using this will result in the teammate glow no longer being visible through walls when a starred mob is present.",
"skyblocker.config.dungeons.terminals": "Terminal Solvers (F7/M7)",
"skyblocker.config.dungeons.terminals.blockIncorrectClicks": "Block Incorrect Clicks",
"skyblocker.config.dungeons.terminals.solveColor": "Solve Select Colored",
Expand Down

0 comments on commit 96d7cc8

Please sign in to comment.