diff --git a/src/client/java/tobinio/visibleentities/mixin/client/EntityMixin.java b/src/client/java/tobinio/visibleentities/mixin/client/EntityMixin.java index 98a0692..c53b40b 100644 --- a/src/client/java/tobinio/visibleentities/mixin/client/EntityMixin.java +++ b/src/client/java/tobinio/visibleentities/mixin/client/EntityMixin.java @@ -1,27 +1,54 @@ package tobinio.visibleentities.mixin.client; import net.minecraft.entity.Entity; -import net.minecraft.entity.MarkerEntity; +import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; 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; import tobinio.visibleentities.VisibleEntitiesClient; import tobinio.visibleentities.settings.Config; +import java.util.List; +import java.util.UUID; + /** * Created: 31.08.24 * * @author Tobias Frischmann */ @Mixin (Entity.class) -public class EntityMixin { +public abstract class EntityMixin { + @Shadow + public abstract EntityType getType(); + + @Shadow + public abstract UUID getUuid(); + @Inject (method = "isInvisibleTo", at = @At ("HEAD"), cancellable = true) private void overwriteVisibility(PlayerEntity player, CallbackInfoReturnable cir) { + if (isInFilterList(player) == (Config.HANDLER.instance().listType == Config.ListType.BLACKLIST)) { + return; + } + if (VisibleEntitiesClient.isActive && Config.HANDLER.instance().showEntities) { cir.setReturnValue(false); cir.cancel(); } } + + @Unique + private boolean isInFilterList(PlayerEntity renderingPlayer) { + List entityKeys = Config.HANDLER.instance().entityKeys; + + if (this.getUuid() == renderingPlayer.getUuid() && entityKeys.contains("self")) { + return true; + } + + var key = getType().getTranslationKey(); + return entityKeys.contains(key); + } } diff --git a/src/client/java/tobinio/visibleentities/settings/Config.java b/src/client/java/tobinio/visibleentities/settings/Config.java index 9caa78f..97fcade 100644 --- a/src/client/java/tobinio/visibleentities/settings/Config.java +++ b/src/client/java/tobinio/visibleentities/settings/Config.java @@ -7,6 +7,9 @@ import net.fabricmc.loader.api.FabricLoader; import net.minecraft.util.Identifier; import tobinio.visibleentities.VisibleEntities; +import java.util.ArrayList; +import java.util.List; + /** * Created: 01.09.24 * @@ -40,4 +43,15 @@ public class Config { public static final int TRANSPARENCY_DEFAULT = 38; @SerialEntry public int transparency = TRANSPARENCY_DEFAULT; + + @SerialEntry + public List entityKeys = new ArrayList<>(); + + @SerialEntry + public ListType listType = ListType.BLACKLIST; + + public enum ListType { + BLACKLIST, + WHITELIST, + } } diff --git a/src/client/java/tobinio/visibleentities/settings/ModMenuIntegration.java b/src/client/java/tobinio/visibleentities/settings/ModMenuIntegration.java index c63b922..8fe69c5 100644 --- a/src/client/java/tobinio/visibleentities/settings/ModMenuIntegration.java +++ b/src/client/java/tobinio/visibleentities/settings/ModMenuIntegration.java @@ -2,13 +2,12 @@ package tobinio.visibleentities.settings; import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ModMenuApi; -import dev.isxander.yacl3.api.ConfigCategory; -import dev.isxander.yacl3.api.Option; -import dev.isxander.yacl3.api.YetAnotherConfigLib; -import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; -import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; +import dev.isxander.yacl3.api.*; +import dev.isxander.yacl3.api.controller.*; import net.minecraft.text.Text; +import java.util.ArrayList; + /** * Created: 01.09.24 * @@ -20,21 +19,7 @@ public class ModMenuIntegration implements ModMenuApi { return parentScreen -> YetAnotherConfigLib.createBuilder() .title(Text.literal("Visible Entities")) .category(ConfigCategory.createBuilder() - .name(Text.literal("Visible Entities")) - .option(Option.createBuilder() - .name(Text.literal("Show ItemFrames")) - .binding(Config.SHOW_ITEM_FRAMES_DEFAULT, - () -> Config.HANDLER.instance().showItemFrames, - newVal -> Config.HANDLER.instance().showItemFrames = newVal) - .controller(opt -> BooleanControllerBuilder.create(opt).coloured(true)) - .build()) - .option(Option.createBuilder() - .name(Text.literal("Show Entities")) - .binding(Config.SHOW_ENTITIES_DEFAULT, - () -> Config.HANDLER.instance().showEntities, - newVal -> Config.HANDLER.instance().showEntities = newVal) - .controller(opt -> BooleanControllerBuilder.create(opt).coloured(true)) - .build()) + .name(Text.literal("General")) .option(Option.createBuilder() .name(Text.literal("Entity Transparency")) .binding(Config.TRANSPARENCY_DEFAULT, @@ -42,19 +27,66 @@ public class ModMenuIntegration implements ModMenuApi { newVal -> Config.HANDLER.instance().transparency = newVal) .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(0, 255).step(1)) .build()) + .build()) + .category(ConfigCategory.createBuilder() + .name(Text.literal("Invisible")) + .option(Option.createBuilder() + .name(Text.literal("Show Invisible")) + .description(OptionDescription.of(Text.literal( + "If invisible entities should be shown when the mod is active"))) + .binding(Config.SHOW_ENTITIES_DEFAULT, + () -> Config.HANDLER.instance().showEntities, + newVal -> Config.HANDLER.instance().showEntities = newVal) + .controller(TickBoxControllerBuilder::create) + .build()) + .option(Option.createBuilder() + .name(Text.literal("Filter List Type")) + .binding(Config.ListType.BLACKLIST, + () -> Config.HANDLER.instance().listType, + newVal -> Config.HANDLER.instance().listType = newVal) + .controller(opt -> EnumControllerBuilder.create(opt) + .enumClass(Config.ListType.class) + .formatValue(t -> Text.of(t.name().toLowerCase()))) + .build()) + .option(ListOption.createBuilder() + .name(Text.literal("Filter List")) + .description(OptionDescription.of(Text.literal( + "List of entity translation keys for rendering when transparent (blacklist/whitelist):\n 'entity.minecraft.chicken' or 'self' to refer to the player."))) + .binding(new ArrayList<>(), + () -> Config.HANDLER.instance().entityKeys, + newVal -> Config.HANDLER.instance().entityKeys = newVal) + .controller(StringControllerBuilder::create) + .initial("") + .build()) + .build()) + .category(ConfigCategory.createBuilder() + .name(Text.literal("Special")) + .option(Option.createBuilder() + .name(Text.literal("Show ItemFrames")) + .description(OptionDescription.of(Text.literal( + "If invisible ItemFrames should be shown when the mod is active"))) + .binding(Config.SHOW_ITEM_FRAMES_DEFAULT, + () -> Config.HANDLER.instance().showItemFrames, + newVal -> Config.HANDLER.instance().showItemFrames = newVal) + .controller(TickBoxControllerBuilder::create) + .build()) .option(Option.createBuilder() .name(Text.literal("Show Interactions")) + .description(OptionDescription.of(Text.literal( + "If Interactions should be shown when the mod is active"))) .binding(Config.SHOW_INTERACTIONS_DEFAULT, () -> Config.HANDLER.instance().showInteractions, newVal -> Config.HANDLER.instance().showInteractions = newVal) - .controller(opt -> BooleanControllerBuilder.create(opt).coloured(true)) + .controller(TickBoxControllerBuilder::create) .build()) .option(Option.createBuilder() .name(Text.literal("Show Marker")) + .description(OptionDescription.of(Text.literal( + "If Marker should be shown when the mod is active"))) .binding(Config.SHOW_MARKER_DEFAULT, () -> Config.HANDLER.instance().showMarker, newVal -> Config.HANDLER.instance().showMarker = newVal) - .controller(opt -> BooleanControllerBuilder.create(opt).coloured(true)) + .controller(TickBoxControllerBuilder::create) .build()) .build()) .save(() -> {