diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..b01da52 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,37 @@ +# Automatically build the project and run any configured tests for every push +# and submitted pull request. This can help catch issues that only occur on +# certain platforms or Java versions, and provides a first line of defence +# against bad commits. + +name: build +on: [pull_request, push] + +jobs: + build: + strategy: + matrix: + # Use these Java versions + java: [ + 21, # Current Java LTS + ] + runs-on: ubuntu-22.04 + steps: + - name: checkout repository + uses: actions/checkout@v4 + - name: validate gradle wrapper + uses: gradle/wrapper-validation-action@v2 + - name: setup jdk ${{ matrix.java }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java }} + distribution: 'microsoft' + - name: make gradle wrapper executable + run: chmod +x ./gradlew + - name: build + run: ./gradlew build + - name: capture build artifacts + if: ${{ matrix.java == '21' }} # Only upload artifacts built from latest java + uses: actions/upload-artifact@v4 + with: + name: Artifacts + path: build/libs/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8ea44a4..6402a53 100644 --- a/build.gradle +++ b/build.gradle @@ -11,11 +11,14 @@ base { } 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 { + name 'Xander Maven' + url 'https://maven.isxander.dev/releases' + } + maven { + name = "Terraformers" + url = "https://maven.terraformersmc.com/" + } } dependencies { @@ -24,8 +27,9 @@ dependencies { mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "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 "dev.isxander:yet-another-config-lib:${project.yacl_version}" + modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}") } processResources { diff --git a/gradle.properties b/gradle.properties index 0f4cbcc..b64045d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,4 +14,6 @@ maven_group=tobinio.visibleentities archives_base_name=visible-entities # Dependencies -fabric_version=0.102.0+1.21 \ No newline at end of file +fabric_version=0.102.0+1.21 +yacl_version=3.5.0+1.21-fabric +modmenu_version=11.0.2 \ No newline at end of file diff --git a/src/main/java/tobinio/visibleentities/VisibleEntities.java b/src/main/java/tobinio/visibleentities/VisibleEntities.java index 4b1f8c6..71aa0f3 100644 --- a/src/main/java/tobinio/visibleentities/VisibleEntities.java +++ b/src/main/java/tobinio/visibleentities/VisibleEntities.java @@ -5,11 +5,19 @@ import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; +import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; +import net.minecraft.entity.EntityType; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.ColorHelper; import org.lwjgl.glfw.GLFW; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import tobinio.visibleentities.entity.InteractionEntityRenderer; +import tobinio.visibleentities.settings.Config; public class VisibleEntities implements ClientModInitializer { public static final String MOD_ID = "visible-entities"; @@ -25,8 +33,13 @@ public class VisibleEntities implements ClientModInitializer { @Override public void onInitializeClient() { + Config.HANDLER.load(); + EntityRendererRegistry.register(EntityType.INTERACTION, InteractionEntityRenderer::new); + ClientTickEvents.END_CLIENT_TICK.register(client -> { while (TOGGLE_KEY.wasPressed()) { + client.player.sendMessage(Text.translatable(isActive ? "visible-entities.disabled" : "visible-entities.enabled") + .formatted(Formatting.GRAY), true); isActive = !isActive; } }); diff --git a/src/main/java/tobinio/visibleentities/entity/InteractionEntityRenderer.java b/src/main/java/tobinio/visibleentities/entity/InteractionEntityRenderer.java new file mode 100644 index 0000000..2d2a057 --- /dev/null +++ b/src/main/java/tobinio/visibleentities/entity/InteractionEntityRenderer.java @@ -0,0 +1,48 @@ +package tobinio.visibleentities.entity; + +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.render.*; +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.decoration.InteractionEntity; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Box; +import org.joml.Matrix4f; +import tobinio.visibleentities.VisibleEntities; +import tobinio.visibleentities.settings.Config; + +/** + * Created: 01.09.24 + * + * @author Tobias Frischmann + */ +public class InteractionEntityRenderer extends EntityRenderer { + public InteractionEntityRenderer(EntityRendererFactory.Context ctx) { + super(ctx); + } + + @Override + public Identifier getTexture(InteractionEntity entity) { + return null; + } + + @Override + public void render(InteractionEntity entity, float yaw, float tickDelta, MatrixStack matrices, + VertexConsumerProvider vertexConsumers, int light) { + super.render(entity, yaw, tickDelta, matrices, vertexConsumers, light); + + if (VisibleEntities.isActive && Config.HANDLER.instance().showInteractions) { + var vertexConsumer = vertexConsumers.getBuffer(RenderLayer.LINES); + WorldRenderer.drawBox( + matrices, + vertexConsumer, + entity.getBoundingBox().offset(-entity.getX(), -entity.getY(), -entity.getZ()), + 1.0F, + 1.0F, + 1.0F, + 1.0F + ); + } + } +} diff --git a/src/main/java/tobinio/visibleentities/mixin/EntityMixin.java b/src/main/java/tobinio/visibleentities/mixin/EntityMixin.java index f623441..1e25098 100644 --- a/src/main/java/tobinio/visibleentities/mixin/EntityMixin.java +++ b/src/main/java/tobinio/visibleentities/mixin/EntityMixin.java @@ -7,6 +7,7 @@ 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.VisibleEntities; +import tobinio.visibleentities.settings.Config; /** * Created: 31.08.24 @@ -16,8 +17,8 @@ import tobinio.visibleentities.VisibleEntities; @Mixin (Entity.class) public class EntityMixin { @Inject (method = "isInvisibleTo", at = @At ("HEAD"), cancellable = true) - private void isInvisibleTo(PlayerEntity player, CallbackInfoReturnable cir) { - if (VisibleEntities.isActive) { + private void overwriteVisibility(PlayerEntity player, CallbackInfoReturnable cir) { + if (VisibleEntities.isActive && Config.HANDLER.instance().showEntities) { cir.setReturnValue(false); cir.cancel(); } diff --git a/src/main/java/tobinio/visibleentities/mixin/LivingEntityRendererMixin.java b/src/main/java/tobinio/visibleentities/mixin/LivingEntityRendererMixin.java new file mode 100644 index 0000000..55b5f3d --- /dev/null +++ b/src/main/java/tobinio/visibleentities/mixin/LivingEntityRendererMixin.java @@ -0,0 +1,29 @@ +package tobinio.visibleentities.mixin; + +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.model.EntityModel; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.ColorHelper; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import tobinio.visibleentities.settings.Config; + +/** + * Created: 01.09.24 + * + * @author Tobias Frischmann + */ +@Mixin (LivingEntityRenderer.class) +public class LivingEntityRendererMixin { + @Redirect (method = "render(Lnet/minecraft/entity/LivingEntity;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At (value = "INVOKE", target = "Lnet/minecraft/client/render/entity/model/EntityModel;render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;III)V")) + private void defineTransparency(EntityModel instance, MatrixStack matrixStack, VertexConsumer vertexConsumer, + int light, int overlay, int color) { + if (color != -1) { + color = ColorHelper.Argb.getArgb(Config.HANDLER.instance().transparency, 255, 255, 255); + } + + instance.render(matrixStack, vertexConsumer, light, overlay, color); + } +} diff --git a/src/main/java/tobinio/visibleentities/settings/Config.java b/src/main/java/tobinio/visibleentities/settings/Config.java new file mode 100644 index 0000000..b2fa8b3 --- /dev/null +++ b/src/main/java/tobinio/visibleentities/settings/Config.java @@ -0,0 +1,35 @@ +package tobinio.visibleentities.settings; + +import dev.isxander.yacl3.config.v2.api.ConfigClassHandler; +import dev.isxander.yacl3.config.v2.api.SerialEntry; +import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.util.Identifier; +import tobinio.visibleentities.VisibleEntities; + +/** + * Created: 01.09.24 + * + * @author Tobias Frischmann + */ +public class Config { + public static ConfigClassHandler HANDLER = ConfigClassHandler.createBuilder(Config.class) + .id(Identifier.of(VisibleEntities.MOD_ID, "config")) + .serializer(config -> GsonConfigSerializerBuilder.create(config) + .setPath(FabricLoader.getInstance().getConfigDir().resolve("visible_entities.json5")) + .setJson5(true) + .build()) + .build(); + + public static final boolean SHOW_ENTITIES_DEFAULT = true; + @SerialEntry + public boolean showEntities = SHOW_ENTITIES_DEFAULT; + + public static final boolean SHOW_INTERACTIONS_DEFAULT = true; + @SerialEntry + public boolean showInteractions = SHOW_INTERACTIONS_DEFAULT; + + public static final int TRANSPARENCY_DEFAULT = 28; + @SerialEntry + public int transparency = TRANSPARENCY_DEFAULT; +} diff --git a/src/main/java/tobinio/visibleentities/settings/ModMenuIntegration.java b/src/main/java/tobinio/visibleentities/settings/ModMenuIntegration.java new file mode 100644 index 0000000..24c6404 --- /dev/null +++ b/src/main/java/tobinio/visibleentities/settings/ModMenuIntegration.java @@ -0,0 +1,55 @@ +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.OptionDescription; +import dev.isxander.yacl3.api.YetAnotherConfigLib; +import dev.isxander.yacl3.api.controller.BooleanControllerBuilder; +import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; +import dev.isxander.yacl3.gui.controllers.slider.IntegerSliderController; +import dev.isxander.yacl3.gui.controllers.string.number.IntegerFieldController; +import net.minecraft.text.Text; + +/** + * Created: 01.09.24 + * + * @author Tobias Frischmann + */ +public class ModMenuIntegration implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parentScreen -> YetAnotherConfigLib.createBuilder() + .title(Text.literal("Visible Entities")) + .category(ConfigCategory.createBuilder() + .name(Text.literal("Visible Entities")) + .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()) + .option(Option.createBuilder() + .name(Text.literal("Entity Transparency")) + .binding(Config.TRANSPARENCY_DEFAULT, + () -> Config.HANDLER.instance().transparency, + newVal -> Config.HANDLER.instance().transparency = newVal) + .controller(opt -> IntegerSliderControllerBuilder.create(opt).range(0, 255).step(1)) + .build()) + .option(Option.createBuilder() + .name(Text.literal("Show Interactions")) + .binding(Config.SHOW_INTERACTIONS_DEFAULT, + () -> Config.HANDLER.instance().showInteractions, + newVal -> Config.HANDLER.instance().showInteractions = newVal) + .controller(opt -> BooleanControllerBuilder.create(opt).coloured(true)) + .build()) + .build()) + .save(() -> { + Config.HANDLER.save(); + }) + .build() + .generateScreen(parentScreen); + } +} diff --git a/src/main/resources/assets/visible-entities/lang/en_us.json b/src/main/resources/assets/visible-entities/lang/en_us.json new file mode 100644 index 0000000..880332b --- /dev/null +++ b/src/main/resources/assets/visible-entities/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "visible-entities.disabled": "[Visible Entities] Disabled", + "visible-entities.enabled": "[Visible Entities] Enabled", + "key.visible-entities.toggle": "Enabled/Disabled", + "category.visible-entities.visible-entities": "Visible Entities" +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 05fe695..1cb1712 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -17,6 +17,9 @@ "entrypoints": { "client": [ "tobinio.visibleentities.VisibleEntities" + ], + "modmenu": [ + "tobinio.visibleentities.settings.ModMenuIntegration" ] }, "mixins": [ @@ -26,9 +29,7 @@ "fabricloader": ">=0.16.3", "minecraft": "~1.21", "java": ">=21", - "fabric-api": "*" - }, - "suggests": { - "another-mod": "*" + "fabric-api": "*", + "yet_another_config_lib_v3": "*" } } \ No newline at end of file diff --git a/src/main/resources/visible-entities.mixins.json b/src/main/resources/visible-entities.mixins.json index 7e0516b..0904c19 100644 --- a/src/main/resources/visible-entities.mixins.json +++ b/src/main/resources/visible-entities.mixins.json @@ -3,7 +3,8 @@ "package": "tobinio.visibleentities.mixin", "compatibilityLevel": "JAVA_21", "client": [ - "EntityMixin" + "EntityMixin", + "LivingEntityRendererMixin" ], "injectors": { "defaultRequire": 1