diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index ee541175..77acdad5 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -93,6 +93,14 @@ public class Storage { @Setter private int activeServices = 0; + @Getter + @Setter + private String bombLocation; + + @Getter + @Setter + private LocalDateTime bombPlantTimestamp; + @Getter @Setter private boolean carLocked = true; @@ -104,19 +112,19 @@ public class Storage { @Getter @Setter - private int lastReceivedSmsNumber = -1; + private double hydration = -1.0; @Getter @Setter - private MinecartEntity minecartEntityToHighlight; + private int lastReceivedSmsNumber = -1; @Getter @Setter - private int moneyAtmAmount = 0; + private MinecartEntity minecartEntityToHighlight; @Getter @Setter - private double hydration = -1.0; + private int moneyAtmAmount = 0; @Getter @Setter @@ -169,6 +177,10 @@ public void print() { LOGGER.info("wantedEntries[{}]: {}", this.wantedEntries.size(), this.wantedEntries); // activeServices LOGGER.info("activeServices: {}", this.activeServices); + // bombLocation + LOGGER.info("bombLocation: {}", this.bombLocation); + // bombPlantTime + LOGGER.info("bombPlantTime: {}", this.bombPlantTimestamp); // carLocked LOGGER.info("carLocked: {}", this.carLocked); // currentJob diff --git a/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java b/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java index ef379c50..92c12d78 100644 --- a/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java +++ b/src/main/java/de/rettichlp/ucutils/common/registry/Registry.java @@ -3,49 +3,28 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import de.rettichlp.ucutils.common.models.Sound; -import de.rettichlp.ucutils.listener.IAbsorptionGetListener; import de.rettichlp.ucutils.listener.IBlockRightClickListener; -import de.rettichlp.ucutils.listener.ICommandSendListener; -import de.rettichlp.ucutils.listener.IEnterVehicleListener; import de.rettichlp.ucutils.listener.IEntityRenderListener; -import de.rettichlp.ucutils.listener.IEntityRightClickListener; -import de.rettichlp.ucutils.listener.IHudRenderListener; -import de.rettichlp.ucutils.listener.IKeyPressListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import de.rettichlp.ucutils.listener.IMessageSendListener; -import de.rettichlp.ucutils.listener.IMoveListener; import de.rettichlp.ucutils.listener.INaviSpotReachedListener; -import de.rettichlp.ucutils.listener.IScreenOpenListener; import de.rettichlp.ucutils.listener.ITickListener; import de.rettichlp.ucutils.listener.IUCUtilsListener; -import de.rettichlp.ucutils.listener.callback.PlayerEnterVehicleCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; 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.message.v1.ClientSendMessageEvents; -import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderEvents; -import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.fabricmc.fabric.api.event.player.UseEntityCallback; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; import java.util.Objects; import java.util.Set; import static de.rettichlp.ucutils.UCUtils.LOGGER; -import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static java.util.Collections.emptySet; -import static java.util.Objects.isNull; -import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toSet; import static java.util.stream.StreamSupport.stream; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; -import static net.minecraft.entity.effect.StatusEffects.ABSORPTION; import static net.minecraft.registry.Registries.SOUND_EVENT; import static net.minecraft.registry.Registry.register; import static net.minecraft.util.ActionResult.PASS; @@ -59,8 +38,6 @@ public class Registry { private final Set listenerInstances = getListenerInstances(); private boolean initialized = false; - private BlockPos lastPlayerPos = null; - private boolean lastAbsorptionState = false; public void registerSounds() { for (Sound value : Sound.values()) { @@ -116,63 +93,11 @@ public void registerListeners() { return showMessage; }); - ClientSendMessageEvents.ALLOW_CHAT.register(s -> { - boolean sendMessage = getListenersImplementing(IMessageSendListener.class).stream() - .allMatch(iMessageSendListener -> iMessageSendListener.onMessageSend(s)); - - if (!sendMessage) { - LOGGER.info("UCUtils blocked message sending: {}", s); - } - - return sendMessage; - }); - - ClientSendMessageEvents.ALLOW_COMMAND.register(commandWithoutPrefix -> { - boolean executeCommand = getListenersImplementing(ICommandSendListener.class).stream() - .allMatch(iCommandSendListener -> iCommandSendListener.onCommandSend(commandWithoutPrefix)); - - if (!executeCommand) { - LOGGER.info("UCUtils blocked command execution: /{}", commandWithoutPrefix); - } - - return executeCommand; - }); - ClientTickEvents.END_CLIENT_TICK.register((server) -> { // handle tick getListenersImplementing(ITickListener.class).forEach(ITickListener::onTick); - - // handle on move - BlockPos blockPos = player.getBlockPos(); - if (isNull(this.lastPlayerPos) || !this.lastPlayerPos.equals(blockPos)) { - this.lastPlayerPos = blockPos; - getListenersImplementing(IMoveListener.class).forEach(iMoveListener -> iMoveListener.onMove(blockPos)); - } - - // handle absorption - boolean hasAbsorption = ofNullable(player) - .map(clientPlayerEntity -> clientPlayerEntity.hasStatusEffect(ABSORPTION)) - .orElse(false); - - if (!this.lastAbsorptionState && hasAbsorption) { - getListenersImplementing(IAbsorptionGetListener.class).forEach(IAbsorptionGetListener::onAbsorptionGet); - } - - this.lastAbsorptionState = hasAbsorption; - - // handle key press - KeyBinding swapHandsKey = MinecraftClient.getInstance().options.swapHandsKey; - if (swapHandsKey.isPressed()) { - getListenersImplementing(IKeyPressListener.class).forEach(IKeyPressListener::onSwapHandsKeyPress); - } }); - HudRenderCallback.EVENT.register((drawContext, tickCounter) -> getListenersImplementing(IHudRenderListener.class).forEach(iHudRenderListener -> iHudRenderListener.onHudRender(drawContext, tickCounter))); - - PlayerEnterVehicleCallback.EVENT.register(vehicle -> getListenersImplementing(IEnterVehicleListener.class).forEach(iEnterVehicleListener -> iEnterVehicleListener.onEnterVehicle(vehicle))); - - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> getListenersImplementing(IScreenOpenListener.class).forEach(iScreenOpenListener -> iScreenOpenListener.onScreenOpen(screen, scaledWidth, scaledHeight))); - UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> { if (hand != OFF_HAND && world.isClient()) { getListenersImplementing(IBlockRightClickListener.class).forEach(iBlockRightClickListener -> iBlockRightClickListener.onBlockRightClick(world, hand, hitResult)); @@ -181,14 +106,6 @@ public void registerListeners() { return PASS; }); - UseEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> { - if (hand != OFF_HAND && world.isClient()) { - getListenersImplementing(IEntityRightClickListener.class).forEach(iEntityRightClickListener -> iEntityRightClickListener.onEntityRightClick(world, hand, entity, hitResult)); - } - - return PASS; - }); - WorldRenderEvents.AFTER_ENTITIES.register(context -> getListenersImplementing(IEntityRenderListener.class).forEach(iEntityRenderListener -> iEntityRenderListener.onEntityRender(context))); // prevent multiple registrations of listeners diff --git a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java index 969aae7a..f7d559bf 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/RenderService.java @@ -7,6 +7,7 @@ import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget; import de.rettichlp.ucutils.common.gui.widgets.base.UCUtilsWidget; import lombok.Getter; +import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.tooltip.Tooltip; @@ -14,17 +15,12 @@ import net.minecraft.client.gui.widget.CyclingButtonWidget; import net.minecraft.client.gui.widget.DirectionalLayoutWidget; 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.Entity; import net.minecraft.item.Item; import net.minecraft.text.Text; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; -import net.minecraft.world.entity.EntityLike; import org.jetbrains.annotations.NotNull; -import org.joml.Matrix4f; import java.awt.Color; import java.util.LinkedHashSet; @@ -38,8 +34,6 @@ import static java.util.stream.StreamSupport.stream; import static net.minecraft.client.font.TextRenderer.TextLayerType.SEE_THROUGH; import static net.minecraft.client.gui.widget.DirectionalLayoutWidget.horizontal; -import static net.minecraft.client.render.RenderLayer.getDebugQuads; -import static net.minecraft.client.render.RenderLayer.getLines; import static net.minecraft.item.Items.COMPARATOR; import static net.minecraft.util.math.RotationAxis.POSITIVE_Y; import static org.atteo.classindex.ClassIndex.getAnnotated; @@ -51,170 +45,26 @@ public class RenderService { @Getter private LinkedHashSet> widgets = new LinkedHashSet<>(); - public boolean isDebugEnabled() { - return false; - } - - public void drawOutline(@NotNull MatrixStack matrices, - @NotNull VertexConsumerProvider vertexConsumers, - @NotNull EntityLike entity, - double expandBoundingBox) { - Box box = entity.getBoundingBox().expand(expandBoundingBox); - drawOutline(matrices, vertexConsumers, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, new Color(255, 255, 0, 150)); - } - - public void drawOutline(@NotNull MatrixStack matrices, - @NotNull VertexConsumerProvider vertexConsumers, - double x1, - double y1, - double z1, - double x2, - double y2, - double z2, - Color color) { - Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera(); - double camX = camera.getPos().x; - double camY = camera.getPos().y; - double camZ = camera.getPos().z; - - float minX = (float) (x1 - camX); - float minY = (float) (y1 - camY); - float minZ = (float) (z1 - camZ); - float maxX = (float) (x2 - camX); - float maxY = (float) (y2 - camY); - float maxZ = (float) (z2 - camZ); - - VertexConsumer consumer = vertexConsumers.getBuffer(getLines()); - Matrix4f matrix = matrices.peek().getPositionMatrix(); - - drawLine(consumer, matrix, minX, minY, minZ, maxX, minY, minZ, color); - drawLine(consumer, matrix, maxX, minY, minZ, maxX, minY, maxZ, color); - drawLine(consumer, matrix, maxX, minY, maxZ, minX, minY, maxZ, color); - drawLine(consumer, matrix, minX, minY, maxZ, minX, minY, minZ, color); - - drawLine(consumer, matrix, minX, maxY, minZ, maxX, maxY, minZ, color); - drawLine(consumer, matrix, maxX, maxY, minZ, maxX, maxY, maxZ, color); - drawLine(consumer, matrix, maxX, maxY, maxZ, minX, maxY, maxZ, color); - drawLine(consumer, matrix, minX, maxY, maxZ, minX, maxY, minZ, color); - - drawLine(consumer, matrix, minX, minY, minZ, minX, maxY, minZ, color); - drawLine(consumer, matrix, maxX, minY, minZ, maxX, maxY, minZ, color); - drawLine(consumer, matrix, maxX, minY, maxZ, maxX, maxY, maxZ, color); - drawLine(consumer, matrix, minX, minY, maxZ, minX, maxY, maxZ, color); - } - - public void drawArea(@NotNull MatrixStack matrices, - @NotNull VertexConsumerProvider vertexConsumers, - @NotNull Direction direction, - float x, - float y, - float z, - @NotNull Color color) { - Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera(); - double camX = camera.getPos().x; - double camY = camera.getPos().y; - double camZ = camera.getPos().z; - - float modifiedX = (float) (x - camX); - float modifiedY = (float) (y - camY); - float modifiedZ = (float) (z - camZ); - - VertexConsumer consumer = vertexConsumers.getBuffer(getDebugQuads()); - Matrix4f matrix = matrices.peek().getPositionMatrix(); - - Color alphaColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 50); - - switch (direction) { - case UP -> { - consumer.vertex(matrix, modifiedX, modifiedY + 1, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY + 1, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY + 1, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY + 1, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - } - case DOWN -> { - consumer.vertex(matrix, modifiedX, modifiedY, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - } - case NORTH -> { - consumer.vertex(matrix, modifiedX, modifiedY, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY + 1, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY + 1, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - } - case EAST -> { - consumer.vertex(matrix, modifiedX + 1, modifiedY, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY + 1, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY + 1, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - } - case SOUTH -> { - consumer.vertex(matrix, modifiedX, modifiedY, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX + 1, modifiedY + 1, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY + 1, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - } - case WEST -> { - consumer.vertex(matrix, modifiedX, modifiedY, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY + 1, modifiedZ).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY + 1, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, modifiedX, modifiedY, modifiedZ + 1).color(alphaColor.getRed(), alphaColor.getGreen(), alphaColor.getBlue(), alphaColor.getAlpha()).normal(0, 1, 0); - } - } - } - - public void drawLine(@NotNull VertexConsumer consumer, - Matrix4f matrix, - float x1, - float y1, - float z1, - float x2, - float y2, - float z2) { - Color color = new Color(255, 255, 0, 150); - drawLine(consumer, matrix, x1, y1, z1, x2, y2, z2, color); - } - - public void drawLine(@NotNull VertexConsumer consumer, - Matrix4f matrix, - float x1, - float y1, - float z1, - float x2, - float y2, - float z2, - @NotNull Color color) { - consumer.vertex(matrix, x1, y1, z1).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).normal(0, 1, 0); - consumer.vertex(matrix, x2, y2, z2).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).normal(0, 1, 0); - } - - public void renderTextAboveEntity(@NotNull MatrixStack matrices, - VertexConsumerProvider vertexConsumers, - @NotNull Entity entity, - Text text) { - renderTextAboveEntity(matrices, vertexConsumers, entity, text, 0.025F); - } - - public void renderTextAboveEntity(@NotNull MatrixStack matrices, - VertexConsumerProvider vertexConsumers, + public void renderTextAboveEntity(WorldRenderContext context, @NotNull Entity entity, Text text, float scale) { - renderTextAt(matrices, vertexConsumers, entity.getX(), entity.getY() + 1.35, entity.getZ(), text, scale); + renderTextAt(context, entity.getX(), entity.getY() + 1.35, entity.getZ(), text, scale); } - public void renderTextAt(@NotNull MatrixStack matrices, - VertexConsumerProvider vertexConsumers, + public void renderTextAt(WorldRenderContext context, double x, double y, double z, Text text, float scale) { + MatrixStack matrices = context.matrices(); + VertexConsumerProvider vertexConsumers = context.consumers(); + // save the current matrix state matrices.push(); - Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera(); + Camera camera = context.gameRenderer().getCamera(); double camX = camera.getPos().x; double camY = camera.getPos().y; double camZ = camera.getPos().z; diff --git a/src/main/java/de/rettichlp/ucutils/listener/IAbsorptionGetListener.java b/src/main/java/de/rettichlp/ucutils/listener/IAbsorptionGetListener.java deleted file mode 100644 index 558cba50..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IAbsorptionGetListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.rettichlp.ucutils.listener; - -public interface IAbsorptionGetListener extends IUCUtilsListener { - - void onAbsorptionGet(); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/ICommandSendListener.java b/src/main/java/de/rettichlp/ucutils/listener/ICommandSendListener.java deleted file mode 100644 index a8302e06..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/ICommandSendListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import org.jetbrains.annotations.NotNull; - -public interface ICommandSendListener extends IUCUtilsListener { - - boolean onCommandSend(@NotNull String command); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IEnterVehicleListener.java b/src/main/java/de/rettichlp/ucutils/listener/IEnterVehicleListener.java deleted file mode 100644 index 70e82649..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IEnterVehicleListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import net.minecraft.entity.Entity; - -public interface IEnterVehicleListener extends IUCUtilsListener { - - void onEnterVehicle(Entity vehicle); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IEntityRightClickListener.java b/src/main/java/de/rettichlp/ucutils/listener/IEntityRightClickListener.java deleted file mode 100644 index ccc0ac9d..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IEntityRightClickListener.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import net.minecraft.entity.Entity; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.EntityHitResult; -import net.minecraft.world.World; - -public interface IEntityRightClickListener extends IUCUtilsListener { - - void onEntityRightClick(World world, Hand hand, Entity entity, EntityHitResult hitResult); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java b/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java deleted file mode 100644 index 2d02c639..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IHudRenderListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.RenderTickCounter; - -public interface IHudRenderListener extends IUCUtilsListener { - - void onHudRender(DrawContext drawContext, RenderTickCounter renderTickCounter); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IKeyPressListener.java b/src/main/java/de/rettichlp/ucutils/listener/IKeyPressListener.java deleted file mode 100644 index 4badaba5..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IKeyPressListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.rettichlp.ucutils.listener; - -public interface IKeyPressListener extends IUCUtilsListener { - - void onSwapHandsKeyPress(); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IMessageSendListener.java b/src/main/java/de/rettichlp/ucutils/listener/IMessageSendListener.java deleted file mode 100644 index 0161ea8e..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IMessageSendListener.java +++ /dev/null @@ -1,6 +0,0 @@ -package de.rettichlp.ucutils.listener; - -public interface IMessageSendListener extends IUCUtilsListener { - - boolean onMessageSend(String message); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IMoveListener.java b/src/main/java/de/rettichlp/ucutils/listener/IMoveListener.java deleted file mode 100644 index 8777bb08..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IMoveListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import net.minecraft.util.math.BlockPos; - -public interface IMoveListener extends IUCUtilsListener { - - void onMove(BlockPos blockPos); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/IScreenOpenListener.java b/src/main/java/de/rettichlp/ucutils/listener/IScreenOpenListener.java deleted file mode 100644 index 0a501bcf..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/IScreenOpenListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.rettichlp.ucutils.listener; - -import net.minecraft.client.gui.screen.Screen; - -public interface IScreenOpenListener extends IUCUtilsListener { - - void onScreenOpen(Screen screen, int scaledWidth, int scaledHeight); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/callback/PlayerEnterVehicleCallback.java b/src/main/java/de/rettichlp/ucutils/listener/callback/PlayerEnterVehicleCallback.java deleted file mode 100644 index 5978084d..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/callback/PlayerEnterVehicleCallback.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.rettichlp.ucutils.listener.callback; - -import net.fabricmc.fabric.api.event.Event; -import net.minecraft.entity.Entity; - -import static net.fabricmc.fabric.api.event.EventFactory.createArrayBacked; - -public interface PlayerEnterVehicleCallback { - - Event EVENT = createArrayBacked(PlayerEnterVehicleCallback.class, listeners -> vehicle -> { - for (PlayerEnterVehicleCallback listener : listeners) { - listener.onEnter(vehicle); - } - }); - - void onEnter(Entity vehicle); -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java index fe573591..f9c7d1a8 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/CarListener.java @@ -1,20 +1,11 @@ package de.rettichlp.ucutils.listener.impl; import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.listener.IEnterVehicleListener; import de.rettichlp.ucutils.listener.IEntityRenderListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import de.rettichlp.ucutils.listener.IScreenOpenListener; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.Entity; -import net.minecraft.entity.vehicle.MinecartEntity; import net.minecraft.text.Text; import java.util.regex.Matcher; @@ -22,56 +13,29 @@ import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.configuration; -import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.renderService; import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.UCUtils.utilService; import static java.lang.Integer.parseInt; -import static java.util.Objects.nonNull; import static java.util.Optional.ofNullable; import static java.util.regex.Pattern.compile; -import static net.minecraft.screen.slot.SlotActionType.PICKUP; import static net.minecraft.util.Formatting.AQUA; @UCUtilsListener -public class CarListener - implements IEnterVehicleListener, IEntityRenderListener, IMessageReceiveListener, IScreenOpenListener { +public class CarListener implements IEntityRenderListener, IMessageReceiveListener { private static final Pattern CAR_UNLOCK_PATTERN = compile("^\\[Car] Du hast deinen .+ aufgeschlossen\\.$"); private static final Pattern CAR_LOCK_PATTERN = compile("^\\[Car] Du hast deinen .+ abgeschlossen\\.$"); private static final Pattern CAR_LOCKED_OWN_PATTERN = compile("^\\[Car] Dein Fahrzeug ist abgeschlossen\\.$"); private static final Pattern CAR_FIND_PATTERN = compile("^\\[Car] Das Fahrzeug befindet sich bei » X: (?-?\\d+) \\| Y: (?-?\\d+) \\| Z: (?-?\\d+)$"); - @Override - public void onEnterVehicle(Entity vehicle) { - // the entity is a car - if (!(vehicle instanceof MinecartEntity)) { - return; - } - - storage.setMinecartEntityToHighlight(null); - - if (configuration.getOptions().car().automatedStart()) { - // start the car with a small delay to ensure the player is fully in the vehicle - utilService.delayedAction(() -> commandService.sendCommand("car start"), 500); - } - - // lock the car after 1 second and the small delay if not already locked - if (!storage.isCarLocked() && configuration.getOptions().car().automatedLock()) { - utilService.delayedAction(() -> commandService.sendCommand("car lock"), 1500); - } - } - @Override public void onEntityRender(WorldRenderContext context) { - MatrixStack matrices = context.matrices(); - VertexConsumerProvider vertexConsumers = context.consumers(); ClientWorld world = MinecraftClient.getInstance().world; if (world != null && configuration.getOptions().car().highlight()) { ofNullable(storage.getMinecartEntityToHighlight()) .map(minecartEntity -> world.getEntityById(minecartEntity.getId())) - .ifPresent(minecartEntity -> renderService.renderTextAboveEntity(matrices, vertexConsumers, minecartEntity, Text.of("🚗").copy().formatted(AQUA), 0.05F)); + .ifPresent(minecartEntity -> renderService.renderTextAboveEntity(context, minecartEntity, Text.of("🚗").copy().formatted(AQUA), 0.05F)); } } @@ -106,26 +70,4 @@ public boolean onMessageReceive(Text text, String message) { return true; } - - @Override - public void onScreenOpen(Screen screen, int scaledWidth, int scaledHeight) { - ClientPlayerInteractionManager interactionManager = MinecraftClient.getInstance().interactionManager; - - if (nonNull(interactionManager) && screen instanceof GenericContainerScreen genericContainerScreen) { - String titleString = genericContainerScreen.getTitle().getString(); - - switch (titleString) { - case "CarControl" -> { - if (configuration.getOptions().car().fastLock()) { - interactionManager.clickSlot(genericContainerScreen.getScreenHandler().syncId, 0, 0, PICKUP, player); - } - } - case "Fahrzeuge" -> { - if (configuration.getOptions().car().fastFind()) { - interactionManager.clickSlot(genericContainerScreen.getScreenHandler().syncId, 0, 0, PICKUP, player); - } - } - } - } - } } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/CommandListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/CommandListener.java deleted file mode 100644 index aaba2e06..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/CommandListener.java +++ /dev/null @@ -1,58 +0,0 @@ -package de.rettichlp.ucutils.listener.impl; - -import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.listener.ICommandSendListener; -import org.jetbrains.annotations.NotNull; - -import java.util.StringJoiner; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static de.rettichlp.ucutils.UCUtils.commandService; -import static java.lang.Character.isUpperCase; -import static java.util.regex.Pattern.compile; - -@UCUtilsListener -public class CommandListener implements ICommandSendListener { - - private static final Pattern COMMAND_NAVI_HOUSE_NUMBER_PATTERN = compile("^navi (?\\d+)$"); - - @Override - public boolean onCommandSend(@NotNull String command) { - String[] parts = command.split(" ", 2); // split the message into command label and arguments - String commandLabel = parts[0]; // get the command label - - if (containsUppercase(commandLabel)) { - String labelLowerCase = commandLabel.toLowerCase(); // get the lowercase command label - - StringJoiner stringJoiner = new StringJoiner(" "); - stringJoiner.add(labelLowerCase); - - if (parts.length > 1) { - stringJoiner.add(parts[1]); - } - - commandService.sendCommand(stringJoiner.toString()); - return false; - } - - Matcher commandNaviHouseNumberMatcher = COMMAND_NAVI_HOUSE_NUMBER_PATTERN.matcher(command); - if (commandNaviHouseNumberMatcher.find()) { - String number = commandNaviHouseNumberMatcher.group("number"); - commandService.sendCommand("navi Haus:" + number); - return false; - } - - return true; - } - - private boolean containsUppercase(@NotNull String input) { - for (char c : input.toCharArray()) { - if (isUpperCase(c)) { - return true; - } - } - - return false; - } -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java index b492aed6..569f1d22 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/PlayerListener.java @@ -2,7 +2,6 @@ import de.rettichlp.ucutils.common.models.Countdown; import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.listener.IAbsorptionGetListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; import de.rettichlp.ucutils.listener.ITickListener; import net.minecraft.network.ClientConnection; @@ -35,7 +34,7 @@ import static net.minecraft.util.Formatting.RED; @UCUtilsListener -public class PlayerListener implements IAbsorptionGetListener, IMessageReceiveListener, ITickListener { +public class PlayerListener implements IMessageReceiveListener, ITickListener { private static final String SHUTDOWN_TIMEOUT = "5"; private static final int PRAY_DELAY_IN_SECONDS = 30; @@ -58,11 +57,6 @@ public class PlayerListener implements IAbsorptionGetListener, IMessageReceiveLi // pray private static final Pattern PRAY_START_PATTERN = compile("^\\[Kirche] Du fängst an für (?:\\[UC])?(?[a-zA-Z0-9_]+) zu beten\\.$"); - @Override - public void onAbsorptionGet() { - storage.getCountdowns().add(new Countdown("Absorption", ofMinutes(3))); - } - @Override public boolean onMessageReceive(Text text, String message) { Matcher deadAReviveMatcher = DEAD_AREVIVE_PATTERN.matcher(message); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java deleted file mode 100644 index 119cdcb8..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/RenderListener.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.rettichlp.ucutils.listener.impl; - -import de.rettichlp.ucutils.common.gui.widgets.CountdownWidget; -import de.rettichlp.ucutils.common.gui.widgets.NotificationWidget; -import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; -import de.rettichlp.ucutils.common.models.Countdown; -import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.common.services.NotificationService; -import de.rettichlp.ucutils.listener.IHudRenderListener; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.RenderTickCounter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Unmodifiable; - -import java.util.ArrayList; -import java.util.List; - -import static de.rettichlp.ucutils.UCUtils.notificationService; -import static de.rettichlp.ucutils.UCUtils.renderService; -import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; - -@UCUtilsListener -public class RenderListener implements IHudRenderListener { - - @Override - public void onHudRender(DrawContext drawContext, RenderTickCounter renderTickCounter) { - renderNotifications(drawContext); - renderWidgets(drawContext); - } - - private void renderNotifications(DrawContext drawContext) { - ArrayList> widgets = new ArrayList<>(); - widgets.addAll(getCountdownWidgets()); - widgets.addAll(getNotificationWidgets()); - - for (int i = 0; i < widgets.size(); i++) { - AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); - int x = MinecraftClient.getInstance().getWindow().getScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; - int y = 19 * i + 4; - abstractUCUtilsProgressTextWidget.draw(drawContext, x, y, RIGHT); - } - } - - private @NotNull @Unmodifiable List getCountdownWidgets() { - return storage.getCountdowns().stream() - .filter(Countdown::isActive) - .map(Countdown::toWidget) - .toList(); - } - - private @NotNull @Unmodifiable List getNotificationWidgets() { - return notificationService.getActiveNotifications().stream() - .map(NotificationService.Notification::toWidget) - .toList(); - } - - private void renderWidgets(DrawContext drawContext) { - renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(drawContext)); - } -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java index ff712ebe..4644bf39 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java @@ -1,38 +1,23 @@ package de.rettichlp.ucutils.listener.impl.faction; -import de.rettichlp.ucutils.common.Storage; -import de.rettichlp.ucutils.common.models.BlackMarket; -import de.rettichlp.ucutils.common.models.Dealer; import de.rettichlp.ucutils.common.models.FactionMember; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import de.rettichlp.ucutils.listener.IMessageSendListener; -import de.rettichlp.ucutils.listener.IMoveListener; import lombok.NonNull; import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.text.Text; import net.minecraft.text.TextColor; import net.minecraft.util.Formatting; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; import java.util.List; import java.util.Optional; -import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static de.rettichlp.ucutils.UCUtils.LOGGER; -import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.common.Storage.ToggledChat.NONE; import static de.rettichlp.ucutils.common.configuration.options.Options.ReinforcementType.UNICACITYADDON; -import static java.lang.System.currentTimeMillis; -import static java.time.LocalDateTime.now; -import static java.util.Arrays.stream; import static java.util.Optional.ofNullable; import static java.util.regex.Pattern.compile; import static net.minecraft.text.Text.empty; @@ -46,7 +31,7 @@ import static net.minecraft.util.Formatting.RED; @UCUtilsListener -public class FactionListener implements IMessageReceiveListener, IMessageSendListener, IMoveListener { +public class FactionListener implements IMessageReceiveListener { private static final Pattern REINFORCEMENT_PATTERN = compile("^(?:(?.+)! )?(?.+) (?:\\[UC])?(?[a-zA-Z0-9_]+) benötigt Unterstützung in der Nähe von (?.+)! \\((?\\d+) Meter entfernt\\)$"); private static final Pattern REINFORCEMENT_BUTTON_PATTERN = compile("^ §7» §cRoute anzeigen §7\\| §cUnterwegs$"); @@ -71,8 +56,6 @@ public class FactionListener implements IMessageReceiveListener, IMessageSendLis .append(of(distance + "m").copy().formatted(DARK_AQUA)) .append(of(")").copy().formatted(GRAY)); - private long lastBlackMarketAndDealerCheck = 0; - @Override public boolean onMessageReceive(Text text, String message) { Matcher reinforcementMatcher = REINFORCEMENT_PATTERN.matcher(message); @@ -162,67 +145,6 @@ public boolean onMessageReceive(Text text, String message) { return true; } - @Override - public boolean onMessageSend(String message) { - Storage.ToggledChat toggledChat = storage.getToggledChat(); - if (toggledChat != NONE) { - commandService.sendCommand(toggledChat.getCommand() + " " + message); - return false; - } - - return true; - } - - @Override - public void onMove(BlockPos blockPos) { - // mark the black market spot as visited if within 60 blocks - if (currentTimeMillis() - this.lastBlackMarketAndDealerCheck >= 3000) { // every 3 seconds to reduce performance impact - this.lastBlackMarketAndDealerCheck = currentTimeMillis(); - - stream(BlackMarket.Type.values()) - .filter(type -> type.getBlockPos().isWithinDistance(blockPos, 60)) - .forEach(type -> { - // remove old type association if exists - storage.getBlackMarkets().removeIf(blackMarket -> blackMarket.getType() == type); - - // check if black market was found there - Box box = player.getBoundingBox().expand(60); - Predicate isBlackMarket = villagerEntity -> ofNullable(villagerEntity.getCustomName()) - .map(text -> text.getString().contains("Schwarzmarkt")) - .orElse(false); - - assert MinecraftClient.getInstance().world != null; // cannot be null at this point - boolean found = !MinecraftClient.getInstance().world.getEntitiesByClass(VillagerEntity.class, box, isBlackMarket).isEmpty(); - - // add new black market entry - BlackMarket blackMarket = new BlackMarket(type, now(), found); - storage.getBlackMarkets().add(blackMarket); - LOGGER.info("Marked black market spot as visited: {}", type); - }); - - stream(Dealer.Type.values()) - .filter(type -> type.getBlockPos().isWithinDistance(blockPos, 60)) - .forEach(type -> { - // remove old type association if exists - storage.getDealers().removeIf(dealer -> dealer.getType() == type); - - // check if black market was found there - Box box = player.getBoundingBox().expand(60); - Predicate isBlackMarket = villagerEntity -> ofNullable(villagerEntity.getCustomName()) - .map(text -> text.getString().contains("Dealer")) - .orElse(false); - - assert MinecraftClient.getInstance().world != null; // cannot be null at this point - boolean found = !MinecraftClient.getInstance().world.getEntitiesByClass(VillagerEntity.class, box, isBlackMarket).isEmpty(); - - // add new black market entry - Dealer dealer = new Dealer(type, now(), found); - storage.getDealers().add(dealer); - LOGGER.info("Marked dealer spot as visited: {}", type); - }); - } - } - private boolean messageMatchesColor(@NonNull List siblings, Formatting primaryFormatting, Formatting secondaryFormatting) { TextColor primaryFormattingCurrent = siblings.get(0).getStyle().getColor(); TextColor secondaryFormattingCurrent = siblings.get(2).getStyle().getColor(); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MajorEventListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MajorEventListener.java index 1e5a7f48..241d38d1 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MajorEventListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/MajorEventListener.java @@ -2,15 +2,9 @@ import de.rettichlp.ucutils.common.models.Faction; import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.listener.IHudRenderListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.RenderTickCounter; import net.minecraft.text.Text; -import java.time.LocalDateTime; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,29 +13,16 @@ import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.common.models.Sound.BANK_ROBBERY; import static de.rettichlp.ucutils.common.models.Sound.BOMB_SOUND; -import static java.lang.String.format; -import static java.time.Duration.between; import static java.time.LocalDateTime.now; -import static java.util.Objects.isNull; -import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.regex.Pattern.compile; -import static net.minecraft.text.Text.empty; -import static net.minecraft.text.Text.literal; -import static net.minecraft.util.Formatting.BOLD; -import static net.minecraft.util.Formatting.GOLD; -import static net.minecraft.util.Formatting.GRAY; -import static net.minecraft.util.Formatting.RED; @UCUtilsListener -public class MajorEventListener implements IMessageReceiveListener, IHudRenderListener { +public class MajorEventListener implements IMessageReceiveListener { private static final Pattern BANK_ROBBERY_PATTERN = compile("^News: Es wurde ein Raub in der Staatsbank gemeldet!$"); private static final Pattern BOMB_FOUND_PATTERN = compile("^News: ACHTUNG! Es wurde eine Bombe in der Nähe von (?.+) gefunden!$"); private static final Pattern BOMB_STOP_PATTERN = compile("^News: Die Bombe konnte (erfolgreich|nicht) entschärft werden!"); - private LocalDateTime bombPlantedTime = null; - private String bombLocationString = ""; - @Override public boolean onMessageReceive(Text text, String message) { Faction playerFaction = storage.getFaction(player.getGameProfile().name()); @@ -53,8 +34,8 @@ public boolean onMessageReceive(Text text, String message) { Matcher bombFoundMatcher = BOMB_FOUND_PATTERN.matcher(message); if (bombFoundMatcher.find()) { - this.bombPlantedTime = now(); - this.bombLocationString = bombFoundMatcher.group("location"); + storage.setBombLocation(bombFoundMatcher.group("location")); + storage.setBombPlantTimestamp(now()); if (configuration.getOptions().sound().bomb().verify(playerFaction)) { BOMB_SOUND.play(); @@ -65,42 +46,11 @@ public boolean onMessageReceive(Text text, String message) { Matcher bombStopMatcher = BOMB_STOP_PATTERN.matcher(message); if (bombStopMatcher.find()) { - this.bombPlantedTime = null; - this.bombLocationString = ""; + storage.setBombLocation(null); + storage.setBombPlantTimestamp(null); return true; } return true; } - - @Override - public void onHudRender(DrawContext drawContext, RenderTickCounter renderTickCounter) { - if (isNull(this.bombPlantedTime)) { - return; - } - - long elapsedTimeInMillis = between(this.bombPlantedTime, now()).toMillis(); - long minutes = MILLISECONDS.toMinutes(elapsedTimeInMillis); - long seconds = MILLISECONDS.toSeconds(elapsedTimeInMillis) % 60; - - if (minutes >= 20) { - this.bombPlantedTime = null; - } - - Text timerText = empty() - .append(literal("Bombe").formatted(RED)) - .append(literal(":").formatted(GRAY)).append(" ") - .append(literal(this.bombLocationString).formatted(GOLD)).append(" ") - .append(literal("|").formatted(GRAY)).append(" ") - .append(literal(format("%02d:%02d", minutes, seconds)).formatted(RED, BOLD)); - - MinecraftClient client = MinecraftClient.getInstance(); - TextRenderer textRenderer = client.textRenderer; - - int textWidth = textRenderer.getWidth(timerText); - int x = (client.getWindow().getScaledWidth() - textWidth) / 2; - int y = 15; - - drawContext.drawTextWithShadow(textRenderer, timerText, x, y, 0xFFFFFFFF); - } } diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/PlantListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/PlantListener.java index 3a028066..fd5e3339 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/PlantListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/PlantListener.java @@ -5,12 +5,8 @@ import de.rettichlp.ucutils.listener.IBlockRightClickListener; import de.rettichlp.ucutils.listener.IEntityRenderListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import de.rettichlp.ucutils.listener.IScreenOpenListener; import net.fabricmc.fabric.api.client.rendering.v1.world.WorldRenderContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; -import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; @@ -41,11 +37,8 @@ import static net.minecraft.block.Blocks.FERN; import static net.minecraft.block.Blocks.PODZOL; import static net.minecraft.entity.EquipmentSlot.MAINHAND; -import static net.minecraft.item.Items.BONE_MEAL; import static net.minecraft.item.Items.PUMPKIN_SEEDS; -import static net.minecraft.item.Items.WATER_BUCKET; import static net.minecraft.item.Items.WHEAT_SEEDS; -import static net.minecraft.screen.slot.SlotActionType.PICKUP; import static net.minecraft.text.Text.empty; import static net.minecraft.text.Text.of; import static net.minecraft.util.Formatting.AQUA; @@ -56,9 +49,8 @@ import static net.minecraft.util.Formatting.RED; @UCUtilsListener -public class PlantListener implements IBlockRightClickListener, IEntityRenderListener, IMessageReceiveListener, IScreenOpenListener { +public class PlantListener implements IBlockRightClickListener, IEntityRenderListener, IMessageReceiveListener { - private static final String PLANT_TEXT = "Plantage"; private static final Pattern PLANT_PLANT_PATTERN = compile("^\\[Plantage] (?:\\[UC])?(?[a-zA-Z0-9_]+) hat eine (Kräuter|Pulver)-Plantage gelegt\\. \\[\\d+/10]$"); private static final Pattern PLANT_WATER_PATTERN = compile("^\\[Plantage] Eine (Kräuter|Pulver)-Plantage wurde von (?:\\[UC])?(?[a-zA-Z0-9_]+) gewässert\\.$"); private static final Pattern PLANT_FERTILIZE_PATTERN = compile("^\\[Plantage] Eine (Kräuter|Pulver)-Plantage wurde von (?:\\[UC])?(?[a-zA-Z0-9_]+) gedüngt\\.$"); @@ -138,8 +130,8 @@ public void onEntityRender(WorldRenderContext context) { fertilizeText = of("↓").copy().formatted(AQUA); } - renderService.renderTextAt(matrices, vertexConsumers, x, y + 0.75, z, waterText, 0.015f); - renderService.renderTextAt(matrices, vertexConsumers, x, y + 0.6, z, fertilizeText, 0.015f); + renderService.renderTextAt(context, x, y + 0.75, z, waterText, 0.015f); + renderService.renderTextAt(context, x, y + 0.6, z, fertilizeText, 0.015f); }); } } @@ -181,22 +173,6 @@ public boolean onMessageReceive(Text text, String message) { return true; } - @Override - public void onScreenOpen(Screen screen, int scaledWidth, int scaledHeight) { - ClientPlayerInteractionManager interactionManager = MinecraftClient.getInstance().interactionManager; - - if (nonNull(interactionManager) && screen instanceof GenericContainerScreen genericContainerScreen && PLANT_TEXT.equals(genericContainerScreen.getTitle().getString())) { - ItemStack mainHandStack = player.getEquippedStack(MAINHAND); - - int syncId = genericContainerScreen.getScreenHandler().syncId; - if (mainHandStack.isOf(WATER_BUCKET)) { - interactionManager.clickSlot(syncId, 1, 0, PICKUP, player); - } else if (mainHandStack.isOf(BONE_MEAL)) { - interactionManager.clickSlot(syncId, 7, 0, PICKUP, player); - } - } - } - private Formatting getTextColor(long millis) { if (millis < 0) { return RED; diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java index c4610d1f..dac213bb 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java @@ -4,7 +4,6 @@ import de.rettichlp.ucutils.common.models.Job; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import de.rettichlp.ucutils.listener.IMoveListener; import de.rettichlp.ucutils.listener.INaviSpotReachedListener; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; @@ -20,7 +19,6 @@ import static de.rettichlp.ucutils.UCUtils.utilService; import static de.rettichlp.ucutils.common.models.Job.PIZZA_DELIVERY; import static de.rettichlp.ucutils.common.models.Job.TOBACCO_PLANTATION; -import static de.rettichlp.ucutils.common.models.Job.URANIUM_TRANSPORT; import static java.lang.Integer.parseInt; import static java.time.Duration.between; import static java.time.LocalDateTime.now; @@ -30,7 +28,7 @@ import static java.util.regex.Pattern.compile; @UCUtilsListener -public class JobListener implements IMessageReceiveListener, IMoveListener, INaviSpotReachedListener { +public class JobListener implements IMessageReceiveListener, INaviSpotReachedListener { private static final String MINING_BOOSTER_COUNTDOWN_TITLE = "Mining XP-Booster"; private static final Pattern TRANSPORT_DELIVER_PATTERN = compile("^\\[Transport] Du hast (eine Holz Lieferung|eine Kiste|eine Waffenkiste|ein Weizen Paket|eine Schwarzpulverkiste) abgeliefert( bei .+)?\\.$"); @@ -89,17 +87,6 @@ public boolean onMessageReceive(Text text, String message) { return true; } - @Override - public void onMove(BlockPos blockPos) { - if (isNull(storage.getCurrentJob())) { - return; - } - - if (storage.getCurrentJob() == URANIUM_TRANSPORT && player.getBlockPos().isWithinDistance(new BlockPos(1132, 68, 396), 2)) { - commandService.sendCommand("dropuran"); - } - } - @Override public void onNaviSpotReached() { if (isNull(storage.getCurrentJob())) { diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java new file mode 100644 index 00000000..a34ee1d5 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayNetworkHandlerMixin.java @@ -0,0 +1,89 @@ +package de.rettichlp.ucutils.mixin; + +import de.rettichlp.ucutils.common.Storage; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import org.jetbrains.annotations.NotNull; +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; + +import java.util.StringJoiner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static de.rettichlp.ucutils.UCUtils.LOGGER; +import static de.rettichlp.ucutils.UCUtils.commandService; +import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.Storage.ToggledChat.NONE; +import static java.lang.Character.isUpperCase; +import static java.util.regex.Pattern.compile; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class ClientPlayNetworkHandlerMixin { + + @Unique + private static final Pattern COMMAND_NAVI_HOUSE_NUMBER_PATTERN = compile("^navi (?\\d+)$"); + + @Inject(method = "sendChatMessage", at = @At("HEAD"), cancellable = true) + private void ucutils$sendChatMessageHead(String content, CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + Storage.ToggledChat toggledChat = storage.getToggledChat(); + if (toggledChat != NONE) { + commandService.sendCommand(toggledChat.getCommand() + " " + content); + LOGGER.info("UCUtils blocked message sending: {}", content); + ci.cancel(); + } + } + + @Inject(method = "sendChatCommand", at = @At("HEAD"), cancellable = true) + private void ucutils$sendChatCommandHead(String command, CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + // allow uppercase command labes and migrate them to lowercase + String[] parts = command.split(" ", 2); // split the message into command label and arguments + String commandLabel = parts[0]; // get the command label + + if (containsUppercase(commandLabel)) { + String labelLowerCase = commandLabel.toLowerCase(); // get the lowercase command label + + StringJoiner stringJoiner = new StringJoiner(" "); + stringJoiner.add(labelLowerCase); + + if (parts.length > 1) { + stringJoiner.add(parts[1]); + } + + commandService.sendCommand(stringJoiner.toString()); + LOGGER.info("UCUtils blocked command execution: /{}", command); + ci.cancel(); + return; + } + + // support /navi + Matcher commandNaviHouseNumberMatcher = COMMAND_NAVI_HOUSE_NUMBER_PATTERN.matcher(command); + if (commandNaviHouseNumberMatcher.find()) { + String number = commandNaviHouseNumberMatcher.group("number"); + commandService.sendCommand("navi Haus:" + number); + LOGGER.info("UCUtils blocked command execution: /{}", command); + ci.cancel(); + } + } + + @Unique + private boolean containsUppercase(@NotNull String input) { + for (char c : input.toCharArray()) { + if (isUpperCase(c)) { + return true; + } + } + + return false; + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java index c48a2ea9..e294c679 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/ClientPlayerEntityMixin.java @@ -1,19 +1,33 @@ package de.rettichlp.ucutils.mixin; +import de.rettichlp.ucutils.common.models.BlackMarket; +import de.rettichlp.ucutils.common.models.Dealer; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.MovementType; +import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; 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; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; +import java.util.function.Predicate; import static de.rettichlp.ucutils.UCUtils.LOGGER; -import static de.rettichlp.ucutils.UCUtils.networkHandler; +import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.models.Job.URANIUM_TRANSPORT; +import static java.lang.System.currentTimeMillis; +import static java.time.LocalDateTime.now; +import static java.util.Arrays.stream; +import static java.util.Optional.ofNullable; import static net.minecraft.item.Items.GLASS_BOTTLE; @Mixin(ClientPlayerEntity.class) @@ -25,6 +39,9 @@ public abstract class ClientPlayerEntityMixin { new BlockPos(1049, 69, -189) ); + @Unique + private long lastBlackMarketAndDealerCheck = 0; + @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) private void ucutils$dropSelectedItemHead(boolean entireStack, CallbackInfoReturnable cir) { if (!storage.isUnicaCity()) { @@ -36,8 +53,70 @@ public abstract class ClientPlayerEntityMixin { cir.setReturnValue(null); // execute command - LOGGER.info("UCUtils executing command: sell pfand"); - networkHandler.sendChatCommand("sell pfand"); + commandService.sendCommand("sell pfand"); + } + } + + @Inject(method = "move", at = @At("HEAD")) + private void ucutils$moveHead(MovementType type, Vec3d movement, CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + BlockPos playerPos = player.getBlockPos(); + + // mark the black market and dealer spots as visited if within 60 blocks + if (currentTimeMillis() - this.lastBlackMarketAndDealerCheck >= 3000) { // every 3 seconds to reduce performance impact + this.lastBlackMarketAndDealerCheck = currentTimeMillis(); + + stream(BlackMarket.Type.values()) + .filter(t -> t.getBlockPos().isWithinDistance(playerPos, 60)) + .forEach(t -> { + // remove old type association if exists + storage.getBlackMarkets().removeIf(blackMarket -> blackMarket.getType() == t); + + // check if black market was found there + Box box = player.getBoundingBox().expand(60); + Predicate isBlackMarket = villagerEntity -> ofNullable(villagerEntity.getCustomName()) + .map(text -> text.getString().contains("Schwarzmarkt")) + .orElse(false); + + assert MinecraftClient.getInstance().world != null; // cannot be null at this point + boolean found = !MinecraftClient.getInstance().world.getEntitiesByClass(VillagerEntity.class, box, isBlackMarket).isEmpty(); + + // add new black market entry + BlackMarket blackMarket = new BlackMarket(t, now(), found); + storage.getBlackMarkets().add(blackMarket); + LOGGER.info("Marked black market spot as visited: {}", t); + }); + + stream(Dealer.Type.values()) + .filter(t -> t.getBlockPos().isWithinDistance(playerPos, 60)) + .forEach(t -> { + // remove old type association if exists + storage.getDealers().removeIf(dealer -> dealer.getType() == t); + + // check if black market was found there + Box box = player.getBoundingBox().expand(60); + Predicate isBlackMarket = villagerEntity -> ofNullable(villagerEntity.getCustomName()) + .map(text -> text.getString().contains("Dealer")) + .orElse(false); + + assert MinecraftClient.getInstance().world != null; // cannot be null at this point + boolean found = !MinecraftClient.getInstance().world.getEntitiesByClass(VillagerEntity.class, box, isBlackMarket).isEmpty(); + + // add new black market entry + Dealer dealer = new Dealer(t, now(), found); + storage.getDealers().add(dealer); + LOGGER.info("Marked dealer spot as visited: {}", t); + }); + } + + // job specific stuff + if (storage.getCurrentJob() != null) { + if (storage.getCurrentJob() == URANIUM_TRANSPORT && player.getBlockPos().isWithinDistance(new BlockPos(1132, 68, 396), 2)) { + commandService.sendCommand("dropuran"); + } } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java index 5a878bb6..cae9d3d6 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/EntityMixin.java @@ -1,6 +1,5 @@ package de.rettichlp.ucutils.mixin; -import de.rettichlp.ucutils.listener.callback.PlayerEnterVehicleCallback; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; @@ -16,9 +15,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import static de.rettichlp.ucutils.UCUtils.commandService; +import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.nameTagService; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.UCUtils.utilService; import static net.minecraft.item.Items.SKELETON_SKULL; import static net.minecraft.item.Items.WITHER_SKELETON_SKULL; import static net.minecraft.text.Text.empty; @@ -43,8 +45,18 @@ public abstract class EntityMixin { } UniquelyIdentifiable self = (Entity) (Object) this; - if (self.getUuid().equals(player.getUuid())) { - PlayerEnterVehicleCallback.EVENT.invoker().onEnter(vehicle); + if (self.getUuid().equals(player.getUuid()) && vehicle instanceof MinecartEntity) { + storage.setMinecartEntityToHighlight(null); + + if (configuration.getOptions().car().automatedStart()) { + // start the car with a small delay to ensure the player is fully in the vehicle + utilService.delayedAction(() -> commandService.sendCommand("car start"), 500); + } + + // lock the car after 1 second and the small delay if not already locked + if (!storage.isCarLocked() && configuration.getOptions().car().automatedLock()) { + utilService.delayedAction(() -> commandService.sendCommand("car lock"), 1500); + } } } diff --git a/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java index 57d78730..a4592353 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/GameMenuScreenMixin.java @@ -22,14 +22,11 @@ protected GameMenuScreenMixin(Text title) { super(title); } - @Inject( - method = "initWidgets", + @Inject(method = "initWidgets", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/GridWidget$Adder;add(Lnet/minecraft/client/gui/widget/Widget;ILnet/minecraft/client/gui/widget/Positioner;)Lnet/minecraft/client/gui/widget/Widget;", - ordinal = 0 - ) - ) + ordinal = 0)) private void ucutils$initWidgetsInvoke(CallbackInfo ci, @Local @NotNull GridWidget gridWidget, @Local GridWidget.@NotNull Adder adder) { diff --git a/src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java new file mode 100644 index 00000000..7d263c28 --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/HandledScreenMixin.java @@ -0,0 +1,64 @@ +package de.rettichlp.ucutils.mixin; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.GameMenuScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.item.ItemStack; +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 static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.player; +import static net.minecraft.entity.EquipmentSlot.MAINHAND; +import static net.minecraft.item.Items.BONE_MEAL; +import static net.minecraft.item.Items.WATER_BUCKET; +import static net.minecraft.screen.slot.SlotActionType.PICKUP; + +@Mixin(GameMenuScreen.class) +public abstract class HandledScreenMixin extends Screen { + + protected HandledScreenMixin(Text title) { + super(title); + } + + @Inject(method = "render", at = @At("TAIL")) + private void ucutils$renderTail(DrawContext context, int mouseX, int mouseY, float deltaTicks, CallbackInfo ci) { + HandledScreen self = (HandledScreen) (Object) this; + + ClientPlayerInteractionManager interactionManager = MinecraftClient.getInstance().interactionManager; + + if (interactionManager == null || !(self instanceof GenericContainerScreen genericContainerScreen)) { + return; + } + + String title = genericContainerScreen.getTitle().getString(); + switch (title) { + case "CarControl" -> { + if (configuration.getOptions().car().fastLock()) { + interactionManager.clickSlot(genericContainerScreen.getScreenHandler().syncId, 0, 0, PICKUP, player); + } + } + case "Fahrzeuge" -> { + if (configuration.getOptions().car().fastFind()) { + interactionManager.clickSlot(genericContainerScreen.getScreenHandler().syncId, 0, 0, PICKUP, player); + } + } + case "Plantage" -> { + ItemStack mainHandStack = player.getEquippedStack(MAINHAND); + int syncId = genericContainerScreen.getScreenHandler().syncId; + if (mainHandStack.isOf(WATER_BUCKET)) { + interactionManager.clickSlot(syncId, 1, 0, PICKUP, player); + } else if (mainHandStack.isOf(BONE_MEAL)) { + interactionManager.clickSlot(syncId, 7, 0, PICKUP, player); + } + } + } + } +} diff --git a/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java index 83051bd5..b05d8cf5 100644 --- a/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java +++ b/src/main/java/de/rettichlp/ucutils/mixin/InGameHudMixin.java @@ -1,26 +1,56 @@ package de.rettichlp.ucutils.mixin; import com.llamalad7.mixinextras.sugar.Local; +import de.rettichlp.ucutils.common.gui.widgets.CountdownWidget; +import de.rettichlp.ucutils.common.gui.widgets.NotificationWidget; +import de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsProgressTextWidget; +import de.rettichlp.ucutils.common.models.Countdown; +import de.rettichlp.ucutils.common.services.NotificationService; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.render.RenderTickCounter; import net.minecraft.entity.LivingEntity; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.profiler.Profilers; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; +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.callback.CallbackInfo; +import java.util.ArrayList; +import java.util.List; + import static de.rettichlp.ucutils.UCUtils.MOD_ID; import static de.rettichlp.ucutils.UCUtils.configuration; +import static de.rettichlp.ucutils.UCUtils.notificationService; import static de.rettichlp.ucutils.UCUtils.player; +import static de.rettichlp.ucutils.UCUtils.renderService; import static de.rettichlp.ucutils.UCUtils.storage; +import static de.rettichlp.ucutils.common.gui.widgets.base.AbstractUCUtilsWidget.Alignment.RIGHT; import static java.lang.Math.ceil; import static java.lang.Math.clamp; import static java.lang.Math.round; +import static java.lang.String.format; +import static java.time.Duration.between; +import static java.time.LocalDateTime.now; +import static java.util.Optional.ofNullable; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static net.minecraft.client.gl.RenderPipelines.GUI_TEXTURED; import static net.minecraft.registry.tag.FluidTags.WATER; +import static net.minecraft.text.Text.empty; +import static net.minecraft.text.Text.literal; +import static net.minecraft.util.Formatting.BOLD; +import static net.minecraft.util.Formatting.GOLD; +import static net.minecraft.util.Formatting.GRAY; +import static net.minecraft.util.Formatting.RED; import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER; @Mixin(InGameHud.class) @@ -35,14 +65,54 @@ public abstract class InGameHudMixin { @Unique private static final Identifier HYDRATION_FULL_TEXTURE = Identifier.of(MOD_ID, "textures/hud/hydration_full.png"); - @Inject( - method = "renderStatusBars", + @Shadow + @Final + private MinecraftClient client; + + @Shadow + public abstract TextRenderer getTextRenderer(); + + @Inject(method = "renderBossBarHud", at = @At("HEAD")) + private void ucutils$renderBossBarHudHead(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { + if (!storage.isUnicaCity()) { + return; + } + + renderNotifications(context); + renderWidgets(context); + + if (storage.getBombPlantTimestamp() == null) { + return; + } + + long elapsedTimeInMillis = between(storage.getBombPlantTimestamp(), now()).toMillis(); + long minutes = MILLISECONDS.toMinutes(elapsedTimeInMillis); + long seconds = MILLISECONDS.toSeconds(elapsedTimeInMillis) % 60; + + if (minutes >= 20) { + storage.setBombLocation(null); + storage.setBombPlantTimestamp(null); + } + + Text timerText = empty() + .append(literal("Bombe").formatted(RED)) + .append(literal(":").formatted(GRAY)).append(" ") + .append(literal(ofNullable(storage.getBombLocation()).orElse("Unbekannt")).formatted(GOLD)).append(" ") + .append(literal("|").formatted(GRAY)).append(" ") + .append(literal(format("%02d:%02d", minutes, seconds)).formatted(RED, BOLD)); + + int textWidth = getTextRenderer().getWidth(timerText); + int x = (this.client.getWindow().getScaledWidth() - textWidth) / 2; + int y = 15; + + context.drawTextWithShadow(getTextRenderer(), timerText, x, y, 0xFFFFFFFF); + } + + @Inject(method = "renderStatusBars", at = @At( value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;renderHealthBar(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/entity/player/PlayerEntity;IIIIFIIIZ)V", - shift = AFTER - ) - ) + shift = AFTER)) private void ucutils$renderStatusBarsInvoke(DrawContext context, CallbackInfo ci, @Local(ordinal = 3) int m, @@ -60,6 +130,40 @@ public abstract class InGameHudMixin { Profilers.get().pop(); } + @Unique + private void renderNotifications(DrawContext drawContext) { + ArrayList> widgets = new ArrayList<>(); + widgets.addAll(getCountdownWidgets()); + widgets.addAll(getNotificationWidgets()); + + for (int i = 0; i < widgets.size(); i++) { + AbstractUCUtilsProgressTextWidget abstractUCUtilsProgressTextWidget = widgets.get(i); + int x = MinecraftClient.getInstance().getWindow().getScaledWidth() - abstractUCUtilsProgressTextWidget.getWidth() - 4; + int y = 19 * i + 4; + abstractUCUtilsProgressTextWidget.draw(drawContext, x, y, RIGHT); + } + } + + @Unique + private @NotNull @Unmodifiable List getCountdownWidgets() { + return storage.getCountdowns().stream() + .filter(Countdown::isActive) + .map(Countdown::toWidget) + .toList(); + } + + @Unique + private @NotNull @Unmodifiable List getNotificationWidgets() { + return notificationService.getActiveNotifications().stream() + .map(NotificationService.Notification::toWidget) + .toList(); + } + + @Unique + private void renderWidgets(DrawContext drawContext) { + renderService.getWidgets().forEach(ucUtilsWidgetInstance -> ucUtilsWidgetInstance.draw(drawContext)); + } + @Unique private void renderHydration(DrawContext context, int top, int left) { double maxHydrated = 20; diff --git a/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java b/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java new file mode 100644 index 00000000..e71e5f4f --- /dev/null +++ b/src/main/java/de/rettichlp/ucutils/mixin/LivingEntityMixin.java @@ -0,0 +1,30 @@ +package de.rettichlp.ucutils.mixin; + +import de.rettichlp.ucutils.common.models.Countdown; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.effect.StatusEffectInstance; +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; + +import static de.rettichlp.ucutils.UCUtils.storage; +import static java.time.Duration.ofMillis; +import static net.minecraft.entity.effect.StatusEffects.HERO_OF_THE_VILLAGE; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin { + + @Inject(method = "addStatusEffect(Lnet/minecraft/entity/effect/StatusEffectInstance;)Z", at = @At("RETURN")) + private void ucutils$addStatusEffectReturn(StatusEffectInstance effect, CallbackInfoReturnable cir) { + if (!storage.isUnicaCity()) { + return; + } + + if (cir.getReturnValue() && effect.getEffectType().equals(HERO_OF_THE_VILLAGE)) { + int durationInTicks = effect.getDuration(); + int durationInMillis = durationInTicks * 50; + storage.getCountdowns().add(new Countdown("Absorption", ofMillis(durationInMillis))); + } + } +} diff --git a/src/main/resources/ucutils.mixins.json b/src/main/resources/ucutils.mixins.json index 0b923a40..78a7b413 100644 --- a/src/main/resources/ucutils.mixins.json +++ b/src/main/resources/ucutils.mixins.json @@ -5,6 +5,7 @@ "mixins": [ "EntityMixin", "ItemStackMixin", + "LivingEntityMixin", "MinecartEntityMixin", "PlayerEntityMixin" ], @@ -17,7 +18,9 @@ "client": [ "ChatScreenMixin", "ClientPlayerEntityMixin", + "ClientPlayNetworkHandlerMixin", "GameMenuScreenMixin", + "HandledScreenMixin", "InGameHudMixin", "PlayerEntityRendererMixin", "PlayerListHudMixin"