Skip to content

Commit

Permalink
Merge pull request #597 from kevinthegreat1/dungeons-secrets-fix
Browse files Browse the repository at this point in the history
Fix bugs with secret detection
  • Loading branch information
kevinthegreat1 authored Mar 18, 2024
2 parents 23f44b4 + 3d361df commit c5d059d
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,37 @@
import com.llamalad7.mixinextras.injector.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
import de.hysky.skyblocker.skyblock.FishingHelper;
import de.hysky.skyblocker.skyblock.end.TheEnd;
import de.hysky.skyblocker.skyblock.dungeon.DungeonScore;
import de.hysky.skyblocker.skyblock.dungeon.secrets.DungeonManager;
import de.hysky.skyblocker.skyblock.end.BeaconHighlighter;
import de.hysky.skyblocker.skyblock.end.TheEnd;
import de.hysky.skyblocker.skyblock.waypoint.MythologicalRitual;
import de.hysky.skyblocker.utils.SlayerUtils;
import de.hysky.skyblocker.utils.Utils;
import net.minecraft.block.Blocks;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityStatuses;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.network.packet.s2c.play.BlockUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.EntityStatusS2CPacket;
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
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(ClientPlayNetworkHandler.class)
public abstract class ClientPlayNetworkHandlerMixin {
@Shadow
private ClientWorld world;

@Inject(method = "onBlockUpdate", at = @At("RETURN"))
private void skyblocker$onBlockUpdate(BlockUpdateS2CPacket packet, CallbackInfo ci) {
if (Utils.isInTheEnd() && SlayerUtils.isInSlayer()) {
Expand All @@ -42,9 +45,16 @@ public abstract class ClientPlayNetworkHandlerMixin {
}
}

@ModifyVariable(method = "onItemPickupAnimation", at = @At(value = "STORE", ordinal = 0))
private ItemEntity skyblocker$onItemPickup(ItemEntity itemEntity, @Local LivingEntity collector) {
DungeonManager.onItemPickup(itemEntity, collector, collector == MinecraftClient.getInstance().player);
@Inject(method = "method_37472", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;removeEntity(ILnet/minecraft/entity/Entity$RemovalReason;)V"))
private void skyblocker$onItemDestroy(int entityId, CallbackInfo ci) {
if (world.getEntityById(entityId) instanceof ItemEntity itemEntity) {
DungeonManager.onItemPickup(itemEntity);
}
}

@ModifyVariable(method = "onItemPickupAnimation", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;removeEntity(ILnet/minecraft/entity/Entity$RemovalReason;)V", ordinal = 0))
private ItemEntity skyblocker$onItemPickup(ItemEntity itemEntity) {
DungeonManager.onItemPickup(itemEntity);
return itemEntity;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,10 +515,7 @@ private static Room newDebugRoom(String roomName, Room.Direction direction, Play
*/
@SuppressWarnings("JavadocReference")
private static void update() {
if (!Utils.isInDungeons()) {
if (mapEntrancePos != null) {
reset();
}
if (!Utils.isInDungeons() || isInBoss()) {
return;
}
MinecraftClient client = MinecraftClient.getInstance();
Expand Down Expand Up @@ -613,7 +610,7 @@ private static void onChatMessage(Text text, boolean overlay) {

String message = text.getString();

if (overlay && isCurrentRoomMatched()) {
if (isCurrentRoomMatched()) {
currentRoom.onChatMessage(message);
}

Expand Down Expand Up @@ -663,7 +660,7 @@ private static void onChatMessage(Text text, boolean overlay) {
@SuppressWarnings("JavadocReference")
private static ActionResult onUseBlock(World world, BlockHitResult hitResult) {
if (isCurrentRoomMatched()) {
currentRoom.onUseBlock(world, hitResult);
currentRoom.onUseBlock(world, hitResult.getBlockPos());
}
return ActionResult.PASS;
}
Expand All @@ -674,16 +671,10 @@ private static ActionResult onUseBlock(World world, BlockHitResult hitResult) {
* If the collector is the player, {@link #currentRoom} is used as an optimization.
*/
@SuppressWarnings("JavadocReference")
public static void onItemPickup(ItemEntity itemEntity, LivingEntity collector, boolean isPlayer) {
if (isPlayer) {
if (isCurrentRoomMatched()) {
currentRoom.onItemPickup(itemEntity, collector);
}
} else {
Room room = getRoomAtPhysical(collector.getPos());
if (isRoomMatched(room)) {
room.onItemPickup(itemEntity, collector);
}
public static void onItemPickup(ItemEntity itemEntity) {
Room room = getRoomAtPhysical(itemEntity.getPos());
if (isRoomMatched(room)) {
room.onItemPickup(itemEntity);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@
import net.minecraft.client.world.ClientWorld;
import net.minecraft.command.argument.EnumArgumentType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.AmbientEntity;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
Expand All @@ -54,6 +52,7 @@
public class Room implements Tickable, Renderable {
private static final Pattern SECRET_INDEX = Pattern.compile("^(\\d+)");
private static final Pattern SECRETS = Pattern.compile("§7(\\d{1,2})/(\\d{1,2}) Secrets");
private static final String LOCKED_CHEST = "That chest is locked!";
private static final Vec3d DOOR_SIZE = new Vec3d(3, 4, 3);
protected static final float[] RED_COLOR_COMPONENTS = {1, 0, 0};
protected static final float[] GREEN_COLOR_COMPONENTS = {0, 1, 0};
Expand Down Expand Up @@ -99,6 +98,8 @@ public class Room implements Tickable, Renderable {

protected List<Tickable> tickables = new ArrayList<>();
protected List<Renderable> renderables = new ArrayList<>();
private BlockPos lastChestSecret;
private long lastChestSecretTime;
/**
* Stores the next room in the dungeon. Currently only used if the next room is the fairy room.
*/
Expand Down Expand Up @@ -207,7 +208,7 @@ protected void addCustomWaypoint(CommandContext<FabricClientCommandSource> conte
SecretWaypoint.Category category = SecretWaypoint.Category.CategoryArgumentType.getCategory(context, "category");
Text waypointName = context.getArgument("name", Text.class);
addCustomWaypoint(secretIndex, category, waypointName, pos);
context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.customWaypointAdded", pos.getX(), pos.getY(), pos.getZ(), name, secretIndex, category, waypointName)));
context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.stringifiedTranslatable("skyblocker.dungeons.secrets.customWaypointAdded", pos.getX(), pos.getY(), pos.getZ(), name, secretIndex, category, waypointName)));
}

/**
Expand Down Expand Up @@ -241,7 +242,7 @@ private void addCustomWaypoint(SecretWaypoint relativeWaypoint) {
protected void removeCustomWaypoint(CommandContext<FabricClientCommandSource> context, BlockPos pos) {
SecretWaypoint waypoint = removeCustomWaypoint(pos);
if (waypoint != null) {
context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.customWaypointRemoved", pos.getX(), pos.getY(), pos.getZ(), name, waypoint.secretIndex, waypoint.category, waypoint.name)));
context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.stringifiedTranslatable("skyblocker.dungeons.secrets.customWaypointRemoved", pos.getX(), pos.getY(), pos.getZ(), name, waypoint.secretIndex, waypoint.category, waypoint.name)));
} else {
context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.dungeons.secrets.customWaypointNotFound", pos.getX(), pos.getY(), pos.getZ(), name)));
}
Expand Down Expand Up @@ -549,11 +550,14 @@ public void render(WorldRenderContext context) {
}

/**
* Sets all secrets as found if {@link #isAllSecretsFound(String)}.
* Sets all secrets as found if {@link #isAllSecretsFound(String)} and sets {@link #lastChestSecret} as missing if message equals {@link #LOCKED_CHEST}.
*/
protected void onChatMessage(String message) {
if (isAllSecretsFound(message)) {
secretWaypoints.values().forEach(SecretWaypoint::setFound);
} else if (LOCKED_CHEST.equals(message) && lastChestSecretTime + 1000 > System.currentTimeMillis() && lastChestSecret != null) {
secretWaypoints.column(lastChestSecret).values().stream().filter(SecretWaypoint::needsInteraction).findAny()
.ifPresent(secretWaypoint -> markSecretsAndLogInfo(secretWaypoint, false, "[Skyblocker Dungeon Secrets] Detected locked chest interaction, setting secret #{} as missing", secretWaypoint.secretIndex));
}
}

Expand All @@ -572,58 +576,72 @@ protected static boolean isAllSecretsFound(String message) {
}

/**
* Marks the secret at the interaction position as found when the player interacts with a chest or a player head,
* if there is a secret at the interaction position.
* Marks the secret at the interaction position as found when the player interacts with a chest, player head, or lever
* if there is a secret at the interaction position and saves the position to {@link #lastChestSecret} if the block is a chest.
*
* @param world the world to get the block from
* @param hitResult the block being interacted with
* @see #onSecretFound(SecretWaypoint, String, Object...)
* @param world the world to get the block from
* @param pos the position of the block being interacted with
* @see #markSecretsFoundAndLogInfo(SecretWaypoint, String, Object...)
*/
protected void onUseBlock(World world, BlockHitResult hitResult) {
BlockState state = world.getBlockState(hitResult.getBlockPos());
if (state.isOf(Blocks.CHEST) || state.isOf(Blocks.PLAYER_HEAD) || state.isOf(Blocks.PLAYER_WALL_HEAD)) {
secretWaypoints.column(hitResult.getBlockPos()).values().stream().filter(SecretWaypoint::needsInteraction).findAny()
.ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} interaction, setting secret #{} as found", secretWaypoint.category, secretWaypoint.secretIndex));
protected void onUseBlock(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
if ((state.isOf(Blocks.CHEST) || state.isOf(Blocks.TRAPPED_CHEST)) && lastChestSecretTime + 1000 < System.currentTimeMillis() || state.isOf(Blocks.PLAYER_HEAD) || state.isOf(Blocks.PLAYER_WALL_HEAD)) {
secretWaypoints.column(pos).values().stream().filter(SecretWaypoint::needsInteraction).findAny()
.ifPresent(secretWaypoint -> markSecretsFoundAndLogInfo(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} interaction, setting secret #{} as found", secretWaypoint.category, secretWaypoint.secretIndex));
if (state.isOf(Blocks.CHEST) || state.isOf(Blocks.TRAPPED_CHEST)) {
lastChestSecret = pos;
lastChestSecretTime = System.currentTimeMillis();
}
} else if (state.isOf(Blocks.LEVER)) {
secretWaypoints.column(hitResult.getBlockPos()).values().stream().filter(SecretWaypoint::isLever).forEach(SecretWaypoint::setFound);
secretWaypoints.column(pos).values().stream().filter(SecretWaypoint::isLever).forEach(SecretWaypoint::setFound);
}
}

/**
* Marks the closest secret that requires item pickup no greater than 6 blocks away as found when the player picks up a secret item.
* Marks the closest secret that requires item pickup no greater than 6 blocks away as found when a secret item is removed from the world.
*
* @param itemEntity the item entity being picked up
* @param collector the collector of the item
* @see #onSecretFound(SecretWaypoint, String, Object...)
* @see #markSecretsFoundAndLogInfo(SecretWaypoint, String, Object...)
*/
protected void onItemPickup(ItemEntity itemEntity, LivingEntity collector) {
protected void onItemPickup(ItemEntity itemEntity) {
if (SecretWaypoint.SECRET_ITEMS.stream().noneMatch(itemEntity.getStack().getName().getString()::contains)) {
return;
}
secretWaypoints.values().stream().filter(SecretWaypoint::needsItemPickup).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(collector))).filter(SecretWaypoint.getRangePredicate(collector))
.ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} picked up a {} from a {} secret, setting secret #{} as found", collector.getName().getString(), itemEntity.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
secretWaypoints.values().stream().filter(SecretWaypoint::needsItemPickup).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(itemEntity))).filter(SecretWaypoint.getRangePredicate(itemEntity))
.ifPresent(secretWaypoint -> markSecretsFoundAndLogInfo(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected item {} removed from a {} secret, setting secret #{} as found", itemEntity.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
}

/**
* Marks the closest bat secret as found when a bat is killed.
*
* @param bat the bat being killed
* @see #onSecretFound(SecretWaypoint, String, Object...)
* @see #markSecretsFoundAndLogInfo(SecretWaypoint, String, Object...)
*/
protected void onBatRemoved(AmbientEntity bat) {
secretWaypoints.values().stream().filter(SecretWaypoint::isBat).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(bat)))
.ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} killed for a {} secret, setting secret #{} as found", bat.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
.ifPresent(secretWaypoint -> markSecretsFoundAndLogInfo(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} killed for a {} secret, setting secret #{} as found", bat.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
}

/**
* Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found.
* Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found and logs the given message.
*
* @param secretWaypoint the secret waypoint to read the index from.
* @param msg the message to log
* @param args the args for the {@link org.slf4j.Logger#info(String, Object...) Logger#info(String, Object...)} call
*/
private void onSecretFound(SecretWaypoint secretWaypoint, String msg, Object... args) {
secretWaypoints.row(secretWaypoint.secretIndex).values().forEach(SecretWaypoint::setFound);
private void markSecretsFoundAndLogInfo(SecretWaypoint secretWaypoint, String msg, Object... args) {
markSecretsAndLogInfo(secretWaypoint, true, msg, args);
}

/**
* Marks all secret waypoints with the same index as the given {@link SecretWaypoint} as found or missing and logs the given message.
* @param secretWaypoint the secret waypoint to read the index from.
* @param found whether to mark the secret as found or missing
* @param msg the message to log
* @param args the args for the {@link org.slf4j.Logger#info(String, Object...) Logger#info(String, Object...)} call
*/
private void markSecretsAndLogInfo(SecretWaypoint secretWaypoint, boolean found, String msg, Object... args) {
markSecrets(secretWaypoint.secretIndex, found);
DungeonManager.LOGGER.info(msg, args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4730,7 +4730,7 @@
"z":15
},
{
"secretName":"2 - Stonk",
"secretName":"1 - Stonk",
"category":"stonk",
"x":26,
"y":112,
Expand Down

0 comments on commit c5d059d

Please sign in to comment.