All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.command.tree.node.PositionNode Maven / Gradle / Ivy

package cn.nukkit.command.tree.node;

import cn.nukkit.api.PowerNukkitXOnly;
import cn.nukkit.api.Since;
import cn.nukkit.level.Location;
import cn.nukkit.level.Position;
import cn.nukkit.math.BVector3;
import cn.nukkit.math.Vector3;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 坐标节点基类
 */
@PowerNukkitXOnly
@Since("1.19.60-r1")
public abstract class PositionNode extends ParamNode {
    private final Pattern pattern;
    protected final double[] coordinate = new double[3];
    protected final List TMP = new ArrayList<>();
    private byte relative = 0b0000;
    protected byte index = 0;

    public PositionNode(Pattern pattern) {
        this.pattern = pattern;
    }

    @Override
    public  E get() {
        return this.get(this.parent.parent.getSender().getPosition());
    }

    @SuppressWarnings("unchecked")
    public  E get(Position basePos) {
        if (value == null) return null;
        if (this.getRelative(0)) {
            this.value.setX(this.value.x + basePos.getX());
        }
        if (this.getRelative(1)) {
            this.value.setY(this.value.y + basePos.getY());
        }
        if (this.getRelative(2)) {
            this.value.setZ(this.value.z + basePos.getZ());
        }
        return (E) this.value;
    }

    @Override
    public void fill(String arg) {
        TMP.clear();
        //check
        var matcher = pattern.matcher(arg);
        while (matcher.find()) {
            TMP.add(matcher.group());
        }
        var str = TMP.stream().reduce((s1, s2) -> s1 + s2);
        if (str.isEmpty()) this.error();
        else if (str.get().length() != arg.length()) this.error();
            //parse
        else {
            try {
                Location loc = this.parent.parent.getSender().getLocation();
                for (String s : TMP) {
                    if (s.charAt(0) == '~') {
                        this.setRelative(index);
                        String relativeCoordinate = s.substring(1);
                        if (relativeCoordinate.isEmpty()) {
                            coordinate[index] = 0;
                        } else {
                            if (relativeCoordinate.charAt(0) == '+')
                                relativeCoordinate = relativeCoordinate.substring(1);
                            coordinate[index] = Double.parseDouble(relativeCoordinate);
                        }
                    } else if (s.charAt(0) == '^') {
                        if (index == 0) {
                            coordinate[0] = 0;
                            coordinate[1] = 0;
                            coordinate[2] = 0;
                        }
                        this.setRelative(index);
                        String relativeAngleCoordinate = s.substring(1);
                        if (!relativeAngleCoordinate.isEmpty()) {
                            Vector3 vector3;
                            if (relativeAngleCoordinate.charAt(0) == '+')
                                relativeAngleCoordinate = relativeAngleCoordinate.substring(1);
                            switch (index) {
                                case 0 -> {
                                    vector3 = BVector3.fromLocation(loc).rotateYaw(-90).setPitch(0).setLength(Double.parseDouble(relativeAngleCoordinate)).addToPos();
                                    coordinate[0] += vector3.x;
                                    coordinate[1] += vector3.y;
                                    coordinate[2] += vector3.z;
                                }
                                case 1 -> {
                                    vector3 = BVector3.fromLocation(loc).rotatePitch(-90).setLength(Double.parseDouble(relativeAngleCoordinate)).addToPos();
                                    coordinate[0] += vector3.x;
                                    coordinate[1] += vector3.y;
                                    coordinate[2] += vector3.z;
                                }
                                case 2 -> {
                                    vector3 = BVector3.fromLocation(loc).setLength(Double.parseDouble(relativeAngleCoordinate)).addToPos();
                                    coordinate[0] += vector3.x;
                                    coordinate[1] += vector3.y;
                                    coordinate[2] += vector3.z;
                                }
                                default -> {
                                    this.error();
                                    return;
                                }
                            }
                        }
                    } else {
                        coordinate[index] = Double.parseDouble(s);
                    }
                    index++;
                }
                if (index == 3) {
                    this.value = new Position(coordinate[0], coordinate[1], coordinate[2], loc.getLevel());
                    index = 0;
                }
            } catch (NumberFormatException ignore) {
                this.error();
            }
        }
    }

    @Override
    public void reset() {
        super.reset();
        this.relative = 0b0000;
    }

    public void setRelative(byte index) {
        switch (index) {
            case 0 -> this.relative |= 0b0001;
            case 1 -> this.relative |= 0b0010;
            case 2 -> this.relative |= 0b0100;
            default -> {
            }
        }
    }

    public boolean getRelative(int index) {
        return switch (index) {
            case 0 -> (this.relative & 0b0001) == 1;
            case 1 -> (this.relative & 0b0010) == 2;
            case 2 -> (this.relative & 0b0100) == 4;
            default -> false;
        };
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy