nageyqma·git
HTTPS https://git.nageyqma.icu/nageyqma/blade-addons-next.git SSH git@git.nageyqma.icu:nageyqma/blade-addons-next.git

HTTPS 链接可直接 git clone;推送代码请使用 SSH。

9.5 KB · 256 行raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
package blade.addon.features.dungeon.f7.relic;

import blade.addon.utils.Location;
import blade.addon.utils.Misc;
import blade.addon.utils.config.values.Floor7;
import blade.addon.utils.data.EntityUtil;
import blade.addon.utils.data.ItemUtil;
import blade.addon.utils.data.TextUtil;
import blade.addon.utils.debug.Debug;
import blade.addon.utils.dungeon.Phase;
import blade.addon.utils.events.Events;
import blade.addon.utils.rendering.RenderUtils;
import blade.addon.utils.rendering.RenderingEvents;
import blade.addon.utils.times.PersonalBests;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.gizmos.GizmoStyle;
import net.minecraft.gizmos.Gizmos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.util.ARGB;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RelicSpawn {

    public enum Relic {
        GREEN(new AABB(49, 7, 44, 50, 8, 45), 0xff55ff55, "§cRed"),
        RED(new AABB(51, 7, 42, 52, 8, 43), 0xffff5555, "§aGreen"),
        PURPLE(new AABB(54, 7, 41, 55, 8, 42), 0xffff55ff, "§5Purple"),
        ORANGE(new AABB(57, 7, 42, 58, 8, 43), 0xffffaa00, "§6Orange"),
        BLUE(new AABB(59, 7, 44, 60, 8, 45), 0xff55ffff, "§bBlue");

        final AABB box;
        final int color;
        final String name;
        int placedTick = 0;

        Relic(AABB box, int color, String name) {
            this.box = box;
            this.color = color;
            this.name = name;
        }
    }

    private static final Pattern PATTERN = Pattern.compile("^(.+) picked the Corrupted (Red|Purple|Orange|Green|Blue) Relic!$");

    private static long phaseStartTime;
    private static Relic pickedupRelic = null;

    private static int tick = Floor7.relicSpawnTicks;
    private static int placeTick = 0;
    private static boolean sentRelicTimes = false;

    public static void init() {
        Events.ON_SERVER_TICK.register(() -> {

            if (!Location.inDungeon() || !Phase.inP5()) return false;

            tick = Math.max(tick - 1, -1);

            if (Phase.inP5()) {
                placeTick++;
            }

            return false;
        });

        Events.ON_LOCATION_CHANGE.register(_ -> {
            if (Location.inDungeon()) {
                reset();
            }
            return false;
        });

        Events.ON_PHASE_CHANGE.register(() -> {
            if (Phase.inP5()) {
                phaseStartTime = System.currentTimeMillis();
                tick = Floor7.relicSpawnTicks;
                placeTick = 0;
            }
            return false;
        });

        Events.ON_GAME_MESSAGE.register(message -> {
            if (!Location.inDungeon() || !Phase.inP5()) return false;
            String str = message.getString().replaceAll("§.", "");
            Matcher matcher = PATTERN.matcher(str);
            if (matcher.find()) {
                String name = matcher.group(1);
                String relicString = matcher.group(2);

                if (EntityUtil.isClientPlayer(name)) {
                    pickedupRelic = RelicSpawn.Relic.valueOf(relicString.toUpperCase());
                    Debug.sendDebugMessage(Component.literal("Picked up relic " + relicString));
                }
            }

            return false;
        });

        ClientTickEvents.END_LEVEL_TICK.register(world -> {
            if (!Location.inDungeon() || !Phase.inP5() || !Floor7.showAllRelicTimes || sentRelicTimes) return;

            Iterable<Entity> entities = world.entitiesForRendering();

            for (Entity entity : entities) {
                if (entity instanceof ArmorStand armorStand) {
                    ItemStack item = armorStand.getWeaponItem();
                    String id = ItemUtil.getId(item);

                    if (id == null || !id.contains("RELIC")) continue;
                    Debug.sendDebugMessage(Component.literal("item id is " + id));

                    double ax = armorStand.getX();
                    double az = armorStand.getZ();

                    for (Relic relic : RelicSpawn.Relic.values()) {
                        if (relic.placedTick != 0 && Misc.getDistance(relic.box.maxX, relic.box.maxZ, ax, az) < 1.5) {
                            relic.placedTick = placeTick;
                            Debug.sendDebugMessage(Component.literal("Set" + relic.name + " time to " + relic.placedTick + ", item id is " + id));
                        }
                    }
                }
            }

            if (allRelicsPlaced()) {
                for (Relic relic : RelicSpawn.Relic.values()) {
                    Misc.addChatMessage(Component.literal(relic.name + " &aRelic placed in &e" + TextUtil.formatTicks(relic.placedTick) + "s&a."));
                    sentRelicTimes = true;
                }
            }
        });


        Events.ON_BLOCK_INTERACTION.register(RelicSpawn::blockInteraction);
        RenderingEvents.FILLED.register(RelicSpawn::worldRender);

    }

    private static boolean blockInteraction(BlockHitResult result, ItemStack itemStack) {
        if ((!Location.inDungeon() || !Phase.inP5())) return false;

        if (pickedupRelic == null) return false;

        BlockPos pos = result.getBlockPos();

        if (!isARelicPos(pos)) return false;

        //skyblock menu check is there incase the item doesnt get updated
        if (!ItemUtil.itemHasName(itemStack, "Relic") && !ItemUtil.itemHasName(itemStack, "Skyblock Menu") && !ItemUtil.itemHasName(itemStack, "Arrow")) {
            if (Floor7.blockIncorrectRelicPlace) {
                Debug.sendDebugMessage(Component.literal("Name: " + itemStack.getHoverName() + " Item: " + itemStack));
                Misc.addChatMessage(Component.literal("Blocked a weird click"));
                return true;
            } else {
                return false;
            }
        }

        if (clickedRelic(pickedupRelic, pos)) {
            if (Floor7.enableRelicPlaceTime) {
                MutableComponent text = Component.literal("The ").withStyle(ChatFormatting.GREEN)
                        .append(Component.literal(pickedupRelic.name().toLowerCase()).withColor(pickedupRelic.color))
                        .append(" relic was placed in ").withStyle(ChatFormatting.GREEN);

                switch (pickedupRelic) {
                    case RED -> PersonalBests.redRelicTime.testNewTime(text, phaseStartTime);
                    case ORANGE -> PersonalBests.orangeRelicTime.testNewTime(text, phaseStartTime);
                    case BLUE -> PersonalBests.blueRelicTime.testNewTime(text, phaseStartTime);
                    case GREEN -> PersonalBests.greenRelicTime.testNewTime(text, phaseStartTime);
                    case PURPLE -> PersonalBests.purpleRelicTime.testNewTime(text, phaseStartTime);
                }

            }
            pickedupRelic = null;
        } else {
            if (Floor7.blockIncorrectRelicPlace) {
                Debug.sendDebugMessage(Component.literal("Relic: " + pickedupRelic));
                Misc.addChatMessage(Component.literal("incorrect click!"));
                return true;
            }
        }
        return false;
    }

    private static boolean isARelicPos(BlockPos pos) {
        try {
            for (Relic relic : RelicSpawn.Relic.values()) {
                if (clickedRelic(relic, pos)) return true;
            }
        } catch (Exception e) {
            Misc.addChatMessage(Component.literal("Relic not found!"));
        }
        return false;
    }

    private static boolean clickedRelic(Relic relic, BlockPos pos) {
        if (relic == null) return false;
        return (pos.getX() == relic.box.minX && (pos.getY() == relic.box.minY || pos.getY() == relic.box.minY - 1) && pos.getZ() == relic.box.minZ);
    }

    private static void reset() {
        tick = Floor7.relicSpawnTicks;
        pickedupRelic = null;
        for (Relic relic : RelicSpawn.Relic.values()) {
            relic.placedTick = 0;
        }
        sentRelicTimes = false;
        placeTick = 0;
    }

    private static boolean allRelicsPlaced() {
        for (Relic relic : RelicSpawn.Relic.values()) {
            if (relic.placedTick == 0) return false;
        }
        return true;
    }

    public static boolean testSetRelic(String name) {
        try {
            pickedupRelic = RelicSpawn.Relic.valueOf(name);
            Misc.addChatMessage(Component.literal("Relic is now: " + name));
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    public static void printRelic() {
        Misc.addChatMessage(Component.literal("Relic: " + pickedupRelic));
    }

    private static void worldRender(LevelRenderContext context, PoseStack matrixStack, VertexConsumer consumer) {
        if (pickedupRelic == null || !Floor7.renderRelicHighlight) return;

        AABB box = pickedupRelic.box;
        float[] color = RenderUtils.toFloats(pickedupRelic.color);
        Gizmos.cuboid(box, GizmoStyle.fill(ARGB.colorFromFloat(color[3], color[0], color[1], color[2])));
    }

    public static int getTick() {
        return tick;
    }
}