link1107 / DonationExecutor

Плагин для ру-стримеров, генерирующий события на сервере Minecraft (Spigot/Paper) на основании донатов с "Donation Alerts"
GNU Affero General Public License v3.0
218 stars 22 forks source link

Code Clean Up #6

Open dokerplp opened 2 years ago

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/DonationAlerts/DonationAlerts.java#L32-L44

Советую почитать об функциональных интерфейсах. Listener именно такой, поэтому этот код можно заменить на

connectListener = arg0 -> logToConsole("Произведено успешное подключение!");

disconectListener = arg0 -> logToConsole("Соединение разорвано!");
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/DonationAlerts/DonationAlerts.java#L51

Вызываешь toString(), но никак не используешь то, что он возвращает

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/DonationAlerts/DonationAlerts.java#L46-L81

donationListener = arg0 -> {

            JSONObject json = new JSONObject((String) arg0[0]);

            new BukkitRunnable() {
                @Override
                public void run() {
                    if (!(json.isNull("username") || json.isNull("amount_formatted") || json.getString("amount_formatted").length() <= 1)) {
                        DonationExecutor.getInstance().listOfStreamerPlayers
                                .addToDonationsQueue(new Donation(Bukkit.getConsoleSender(),
                                        json.getString("username"),
                                        json.getString("amount_formatted"),
                                        json.getString("message")));
                    }
                }
            }.runTask(Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("DonationExecutor")));
        };
errorListener = arg0 -> logToConsole("Произошла ошибка подключения к Donation Alerts!");
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/DonationAlerts/DonationAlerts.java#L89-L98

В java не принято назвать методы с большой буквы. Почитай о правилах стиля.

Да пакеты тоже нужно с маленькой называть (DonationAlerts)

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/AbstractCommand.java#L24-L28

return execute(sender, label, args);
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/DonateSubCommand.java#L11-L14

Лучше не использовать new String(), тк в таком случае ты создаешь ДЕЙСТВИТЕЛЬНО новую строку, которая не будет ссылаться на существующую строку из стека

Лучше заменить на

String donationAmount;
String donationUsername = "";
String donationMessage = "";
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/DonateSubCommand.java#L9-L41

Конкатенация в этом случае это ОЧЕНЬ ОЧЕНЬ плохо, тк String - Immutable Object, любая попытка его изменить порождает новый экземпляр, что сильно вредит времени работы, лучше использовать StringBuilder или StringBuffer (работает медленнее чем StringBuilder, но зато потокобезопасна)

//Getting donation's amount
        String donationAmount = args[0];
        StringBuilder donationUsername = new StringBuilder();
        StringBuilder donationMessage = new StringBuilder();

        int i;
        //Получаем имя донатера
        for (i = 1; i <= args.length - 1; i++) {
            if (args[i].equals("##")) break;
            donationUsername.append(args[i]);
            if (i != 1) donationUsername.append(' ');
        }

        //Все, что после символов ## - это сообщение
        for (i = i + 1; i <= args.length - 1; i++) {
            donationMessage.append(args[i]);
            donationMessage.append(' ');
        }

        //Отправляем донат на исполнение
        DonationExecutor.getInstance().listOfStreamerPlayers.addToDonationsQueue(new Donation(sender, donationUsername.toString(), donationAmount+".00", donationMessage));
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/DonationExecutorCommand.java#L55-L59

Очень плохое логгирование

  1. НИКОГДА не используй e.printStackTrace();
  2. Не нужно городить велосипед, есть множество готовых логгеров, самый простой для тебя, вероятно будет SLF4J - подключается очень просто maven:
    <!--SLF4J-->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.0-alpha5</version>
        </dependency>

Дальше в коде пишешь

private final Logger logger = LoggerFactory.getLogger(YourClassName.class);

и все

Да, и еще - использовать 1 логгер на все приложение, это тоже очень плохо, лучше в каждом классе, в котором тебе необходимо логгирование прописывать конструкцию выше

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/DonationExecutorCommand.java#L55

Вообще ловить Exception это плохая затея, лучше ловить те ошибки, о которых ты знаешь - поясню: вот кинется тебе в коде NullPointerException - программа его поймает, это не правильно, тк NPE - это всегда ошибка программиста и лучше сделать так чтобы он вовсе не кидался, чем его ловить

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/DonationExecutorCommand.java#L24-L52

Лучше использовать switch (Не Nintendo)

switch (args[0]) {
                case "reload":
                    ...
                    break;
                case "donate":
                    ...
                    break;
                case "filter":
                    ...
                    break;
            }

А лучше и switch не использовать, а реализовать Command Pattern (но на твоем уровне программирования лучше switch :) )

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/FilterSubCommand.java#L11

if (args[0].equalsIgnoreCase("on")) {
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/donationexecutor/executionsstaff/Donation.java#L13

Плохое название переменных

_ убери

без него тоже будет работать

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/donationexecutor/executionsstaff/Donation.java#L14

Исправь на

this(Bukkit.getConsoleSender(), _username, _amount, _message);
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/donationexecutor/executionsstaff/Donation.java#L17-L26

public Donation(CommandSender sender, String username, String amount, String message) {
        this.sender = sender;
        if (username.equals("")) {
            this.username = "Аноним";
        } else {
            this.username = username;
        }
       this.amount = amount;
       this.message = message;
    }
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/donationexecutor/executionsstaff/Donation.java#L28-L50

Да в java довольно плохо все с getter-ами и setter-ами (неудобно), но мой тебе совет - используй Lombok Очень удобная штука

maven:

<!--Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
            <scope>provided</scope>
        </dependency>

Можешь сделать так

@Getter
@Setter
class BestClass {
...
}

Тогда для всех полей getter и setter сам сгенерится, либо же так

@Getter
@Setter
private String yourMomName;

Тогда getter и setter сгенерятся только для этого поля

dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/donationexecutor/executionsstaff/GiantMobManager.java#L27

Очень плохой класс, извини я не вывез его весь ревьють, поисправлял только предложения от IDE.

Много кода, который нигде не используется

Почитай про дженерики, зачем нужны как использовать ну и заодно про diamond operator

public class GiantMobManager {
    private final HashMap<String, HashMap<UUID, GiantMob>> listOfMobLists = new HashMap<>();

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //Конструктор класса. Регистрируем в нем слушателя событий GiantEventListener
    public GiantMobManager(Plugin thisPlugin) {
            Bukkit.getPluginManager().registerEvents(new GiantMobEventListener(this), thisPlugin);
            for (Player p : Bukkit.getOnlinePlayers()) {
                for (Entity ent : p.getWorld().getEntities()) {
                    if (ent instanceof Giant) {
                        this.addMob((LivingEntity) ent);
                    }
                }
            }
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //Добавление и удаление моба
    //Добавляем нового моба, которого нужно заспавнить
    public void addMob(@NotNull Location playerLocation, @NotNull String mobName) {
        addMobToList(new GiantMob(playerLocation, mobName));
    }

    //Добавляем нового моба, который уже был заспавнен
    public void addMob(@NotNull LivingEntity giantMob) {
        addMobToList(new GiantMob(giantMob));
    }

    //Удаляем моба
    public void removeMob(@NotNull LivingEntity giantMob) {
        removeMobFromList(giantMob);
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //Добавление и удаления из списка мобов

    //Добавляем моба в оответствующий его типу список
    private void addMobToList(@NotNull GiantMob newGiantMob) {
        if (listOfMobLists.containsKey(newGiantMob.getName())) {
            listOfMobLists.get(newGiantMob.getName()).put(newGiantMob.getUUID(), newGiantMob);
        } else {
            listOfMobLists.put(newGiantMob.getName(), new HashMap<>());
            listOfMobLists.get(newGiantMob.getName()).put(newGiantMob.getUUID(), newGiantMob);
        }
    }

    //Удаляем моба из соответствующего ему списка
    private void removeMobFromList(@NotNull LivingEntity giantMob) {
        listOfMobLists.get(giantMob.getName()).remove(giantMob.getUniqueId());
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //Класс гигантского моба
    private static class GiantMob {
        private int timesThisGiantMobIsOnOnePlace = 0;
        private String thisGiantMobPlayerCurrentTargetName = null;
        private int stepsAfterHiding = 0;
        private final LivingEntity giantMobLivingEntity;
        private UUID thisGiantMobUUID = null;

        private final int howManySnowballsMobLaunches = 4;
        private final Boolean SnowballsFollowingTarget = false;
        private final static int timeBeforeThisGiantMobForgetHisTarget = 5;
        private final static int ticksBetweenSnowballsShots = 7;

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //Конструктор гигантского моба

        //Создаем моба, заспавнив его и указав Имя-тип
        public GiantMob(@NotNull Location playerLocation, String mobName) {

            //Определяем направление игрока и спавним моба перед ним, повернутым к игроку лицом
            Vector playerDirection = playerLocation.getDirection();
            playerDirection.setY(0);
            playerDirection.normalize();
            this.giantMobLivingEntity = (LivingEntity) playerLocation.getWorld().spawnEntity(playerLocation.clone().add(playerDirection.clone().multiply(5)).setDirection(playerDirection.multiply(-1)), EntityType.GIANT);
            if (!(mobName == null)) {
                this.giantMobLivingEntity.setCustomName(mobName);
            }
            this.giantMobLivingEntity.setGravity(true);
            this.giantMobLivingEntity.setRemoveWhenFarAway(false);
            this.thisGiantMobUUID = giantMobLivingEntity.getUniqueId();
            this.giantMobLivingEntity.getEquipment().setItem(EquipmentSlot.HAND, new ItemStack(Material.IRON_SWORD));

            //Заставляем бегать и стрелять
            this.makeGiantMobAttackWithFireballs();
            this.forceGiantMobToMove();
            this.makeGiantMobAttackWithSnowballs();
        }

        //Добавляем существующего
        public GiantMob(@NotNull LivingEntity _stalinMob) {
            this.giantMobLivingEntity = _stalinMob;

            //Заставляем бегать и стрелять
            this.turnOnGiantMobAi();
        }

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //Геттеры

        //Отдает имя моба
        public String getName() {
            return this.giantMobLivingEntity.getName();
        }

        //Отдает UUID моба
        public UUID getUUID() {
            return this.thisGiantMobUUID;
        }

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //Поиск ближайшей цели
        private LivingEntity findGiantMobTarget() {
            //получаем список ближайших врагов dв радиусе sralinShootingRadius
            int giantMobTrackingRange = 40;
            List<Entity> listOfNearbyEntities = giantMobLivingEntity.getNearbyEntities(giantMobTrackingRange, giantMobTrackingRange, giantMobTrackingRange);
            List<LivingEntity> listOfNearbyPlayers = new ArrayList<>();
            List<LivingEntity> listOfNearbyLivingEntities = new ArrayList<>();

            //Пробегаемся и ищем игроков
            for (Entity e : listOfNearbyEntities) {
                RayTraceResult rtRes1;
                RayTraceResult rtRes2;
                RayTraceResult rtRes3;
                RayTraceResult rtRes4;
                RayTraceResult rtRes5;
                RayTraceResult rtRes6;
                RayTraceResult rtRes7;
                RayTraceResult rtRes8;

                if (e instanceof LivingEntity) {
                    //Позиции псевдоглаз вокруг головы с каждой стороны
                    Location rtGiantMobPseudoEyesPos1 = giantMobLivingEntity.getLocation().clone().add(2, 11, 0);
                    Location rtGiantMobPseudoEyesPos2 = giantMobLivingEntity.getLocation().clone().add(-2, 11, 0);
                    Location rtGiantMobPseudoEyesPos3 = giantMobLivingEntity.getLocation().clone().add(0, 11, 2);
                    Location rtGiantMobPseudoEyesPos4 = giantMobLivingEntity.getLocation().clone().add(0, 11, -2);

                    //Пускаем лучи из каждой точки псевдоглаз до верха и низа каждой сущности
                    rtRes1 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos1, genVec(rtGiantMobPseudoEyesPos1, ((LivingEntity) e).getEyeLocation()), rtGiantMobPseudoEyesPos1.distance(((LivingEntity) e).getEyeLocation()), FluidCollisionMode.NEVER, true);
                    rtRes2 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos2, genVec(rtGiantMobPseudoEyesPos2, ((LivingEntity) e).getEyeLocation()), rtGiantMobPseudoEyesPos2.distance(((LivingEntity) e).getEyeLocation()), FluidCollisionMode.NEVER, true);
                    rtRes3 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos3, genVec(rtGiantMobPseudoEyesPos3, ((LivingEntity) e).getEyeLocation()), rtGiantMobPseudoEyesPos3.distance(((LivingEntity) e).getEyeLocation()), FluidCollisionMode.NEVER, true);
                    rtRes4 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos4, genVec(rtGiantMobPseudoEyesPos4, ((LivingEntity) e).getEyeLocation()), rtGiantMobPseudoEyesPos4.distance(((LivingEntity) e).getEyeLocation()), FluidCollisionMode.NEVER, true);
                    rtRes5 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos1, genVec(rtGiantMobPseudoEyesPos1, e.getLocation()), rtGiantMobPseudoEyesPos1.distance(e.getLocation()), FluidCollisionMode.NEVER, true);
                    rtRes6 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos2, genVec(rtGiantMobPseudoEyesPos2, e.getLocation()), rtGiantMobPseudoEyesPos2.distance(e.getLocation()), FluidCollisionMode.NEVER, true);
                    rtRes7 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos3, genVec(rtGiantMobPseudoEyesPos3, e.getLocation()), rtGiantMobPseudoEyesPos3.distance(e.getLocation()), FluidCollisionMode.NEVER, true);
                    rtRes8 = giantMobLivingEntity.getWorld().rayTraceBlocks(rtGiantMobPseudoEyesPos4, genVec(rtGiantMobPseudoEyesPos4, e.getLocation()), rtGiantMobPseudoEyesPos4.distance(e.getLocation()), FluidCollisionMode.NEVER, true);

                    //Если Сталин может из любой позиции поврота голвоы увидеть верх или низ цели, то эта цель вносится в список кандидатов
                    if ((rtRes1 == null) || (rtRes2 == null) || (rtRes3 == null) || (rtRes4 == null) || (rtRes5 == null) || (rtRes6 == null) || (rtRes7 == null) || (rtRes8 == null)) {
                        if ((e instanceof Player) && (!(((Player) e).getGameMode() == GameMode.SPECTATOR)) && (!(((Player) e).getGameMode() == GameMode.CREATIVE))) {
                            listOfNearbyPlayers.add((LivingEntity) e);
                        } else if (!(e instanceof Player)) {
                            listOfNearbyLivingEntities.add((LivingEntity) e);
                        }
                    }
                }

            }

            //Создаем переменную будущей цели
            LivingEntity target = null;
            Double minDistance = null;

            if (!(listOfNearbyPlayers.isEmpty())) {

                //Если есть игроки - ищем среди них ближайшего
                for (LivingEntity e : listOfNearbyPlayers) {
                    if (target == null) {
                        target = e;
                        minDistance = giantMobLivingEntity.getLocation().distance(e.getLocation());
                    } else if (minDistance > giantMobLivingEntity.getLocation().distance(e.getLocation())) {
                        target = e;
                        minDistance = giantMobLivingEntity.getLocation().distance(e.getLocation());
                    }
                }

                //Если новая цель - сбрасываем счетчик забвения после скрытия из области видимости моба, и назначаем цель текущей целью моба
                if (!(target.getName().equals(thisGiantMobPlayerCurrentTargetName))) {
                    stepsAfterHiding = 0;
                    thisGiantMobPlayerCurrentTargetName = target.getName();
                }

            } else if (!(listOfNearbyLivingEntities.isEmpty()))  {
                    //Если игроков рядом не было, проверяем все живые сущности
                    for (LivingEntity e : listOfNearbyLivingEntities) {
                        if (target == null) {
                            target = e;
                            minDistance = this.giantMobLivingEntity.getLocation().distance(e.getLocation());
                        } else if (minDistance > this.giantMobLivingEntity.getLocation().distance(e.getLocation())) {
                            target = e;
                            minDistance = this.giantMobLivingEntity.getLocation().distance(e.getLocation());
                        }
                    }

            }

            if ( (!(target instanceof Player)) && (!(thisGiantMobPlayerCurrentTargetName == null)) ) {
                //Если прошлая цель-игрок существует, и он не мертв и находится в том же мире, что и наш моб
                if ( (!(getPlayer(thisGiantMobPlayerCurrentTargetName).isDead())) && (getPlayer(thisGiantMobPlayerCurrentTargetName).getWorld() == giantMobLivingEntity.getWorld()) ) {

                    //Если не подошло время забыть о нем и он не стал спектэйтором, фокусим моба на него
                    if ((stepsAfterHiding <= timeBeforeThisGiantMobForgetHisTarget * 2) && (!(getPlayer(thisGiantMobPlayerCurrentTargetName).getGameMode()==GameMode.SPECTATOR)) && (!(getPlayer(thisGiantMobPlayerCurrentTargetName).getGameMode()==GameMode.CREATIVE))){
                        target = getPlayer(thisGiantMobPlayerCurrentTargetName);
                        stepsAfterHiding++;
                    } else {
                        //если подошло время забыть про него - забываем
                        stepsAfterHiding = 0;
                        thisGiantMobPlayerCurrentTargetName = null;
                    }

                }
            }

            //Возвращаем ближайшее ентити (игрок в приоритете)
            return target;
        }

        private void turnOnGiantMobAi() {
            this.forceGiantMobToMove();
            this.makeGiantMobAttackWithFireballs();
            this.makeGiantMobAttackWithSnowballs();
        }

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //Заставляем нашего моба двигаться
        private void forceGiantMobToMove() {
            final GiantMob thisGiantMob = this;
            new BukkitRunnable() {
                @Override
                public void run() {
                    LivingEntity thisGiantMobLivingEntity = thisGiantMob.giantMobLivingEntity;

                    if ( (thisGiantMobLivingEntity.isDead()) || (!(DonationExecutor.isRunning)) ) {
                        //Если Сталин уже помер, отрубаем задание
                        this.cancel();
                    } else {
                        //Если не помер, находим ближайшую цель (игроки в приоритете)
                        LivingEntity target;
                        target = thisGiantMob.findGiantMobTarget();

                        //Если цели нет...
                        if (target == null) {
                            //Если моб не в воде, то прижимаем его к Земле, чтобы не улетел в небо на прыжке
                            if (!(thisGiantMobLivingEntity.getEyeLocation().clone().add(0,2,0).getBlock().getType()==Material.WATER)) {
                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLivingEntity.getLocation().getDirection().clone().normalize().setY(-4.5));
                            } else {
                                //сли над мобом вода - всплываем
                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLivingEntity.getLocation().getDirection().clone().normalize().setY(3));
                            }
                            return;
                        }

                        //Поворачиваем в плоскости XZ
                        float newYaw = (float) Math.toDegrees(
                                Math.atan2(
                                        target.getLocation().getZ() - thisGiantMobLivingEntity.getLocation().getZ(),
                                        target.getLocation().getX() - thisGiantMobLivingEntity.getLocation().getX()))
                                - 90;

                        //Поворачиваем по вертикальной оси Y (не работает из-за зачатков AI, которые сами крутят моба)
                        double xDiff = target.getEyeLocation().getX() - thisGiantMobLivingEntity.getEyeLocation().getX();
                        double yDiff = target.getEyeLocation().getY() - thisGiantMobLivingEntity.getEyeLocation().getY();
                        double zDiff = target.getEyeLocation().getZ() - thisGiantMobLivingEntity.getEyeLocation().getZ();

                        double distanceXZ = sqrt(xDiff * xDiff + zDiff * zDiff);
                        double distanceY = sqrt(distanceXZ * distanceXZ + yDiff * yDiff);

                        double yaw = Math.toDegrees(Math.acos(xDiff / distanceXZ));
                        double pitch = Math.toDegrees(Math.acos(yDiff / distanceY)) - 90.0D;
                        if (zDiff < 0.0D) {
                            yaw += Math.abs(180.0D - yaw) * 2.0D;
                        }

                        thisGiantMobLivingEntity.setRotation(newYaw, (float) pitch);

                        //Готовимся к совершению движения
                        Location thisGiantMobLoc = thisGiantMobLivingEntity.getLocation().clone();
                        Location thisGiantMobLocXZ = thisGiantMobLivingEntity.getLocation().clone();
                        thisGiantMobLocXZ.setY(0);
                        double thisGiantMobLocY = thisGiantMobLoc.clone().getY();

                        Location targetLoc = target.getLocation().clone();
                        Location targetLocXZ = target.getLocation().clone();
                        targetLocXZ.setY(0);
                        double targetY = targetLoc.clone().getY();

                        //Совершаем движение, если мы далеко от цели, либо если мы сильно под ней
                        if ((thisGiantMobLocXZ.distance(targetLocXZ) > 1) || (((targetY - thisGiantMobLocY) > 20) && (thisGiantMobLocY < targetY))) {
                            double oldX = thisGiantMobLoc.getX();
                            double oldZ = thisGiantMobLoc.getZ();
                            //sendSysMsgToPlayer(Bukkit.getPlayer("Evropejets"), "ДВИЖЕНИЕ! До цели " + (int) (Math.round(thisGiantMobLoc.distance(target.getLocation()))) + "\nЦЕЛЬ: " + target.getName());
                            //Стандартное движение к цели, если она за радиусом досягаемости
                            if (!(thisGiantMobLivingEntity.getEyeLocation().clone().add(0,1,0).getBlock().getType()==Material.WATER)) {
                                thisGiantMobLivingEntity.setRemainingAir(thisGiantMobLivingEntity.getMaximumAir());
                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().setY(-4.5));
                            } else {
                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().setY(1.4));
                                return;
                            }

                            new BukkitRunnable() {
                                @Override
                                public void run() {

                                    if ( (thisGiantMobLivingEntity.isDead()) || (!(DonationExecutor.isRunning)) ) {
                                        this.cancel();
                                        return;
                                    }

                                    //Если моб не сдвинулся за счет стандартного движения (разница между новыми и старыми кордами<2), и при этом он находится ниже цели по Y, но дальше по XZ, чем на 2.5 блока от нее (то есть ему есть куда стремиться до цели)...
                                    if ((Math.abs(thisGiantMobLivingEntity.getLocation().getX() - oldX) < 1) && (Math.abs(thisGiantMobLivingEntity.getLocation().getZ() - oldZ) < 1) && ((thisGiantMobLocY < targetY) || (thisGiantMobLocXZ.distance(targetLocXZ) > 2.5))) {
                                        thisGiantMob.timesThisGiantMobIsOnOnePlace++;
                                        if (thisGiantMob.timesThisGiantMobIsOnOnePlace > 2) {
                                            if (timesThisGiantMobIsOnOnePlace == 3) {
                                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().multiply(1).setY(4));
                                            } else if (timesThisGiantMobIsOnOnePlace == 6) {
                                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().rotateAroundY(0.9).multiply(2).setY(5));
                                            } else if (timesThisGiantMobIsOnOnePlace == 9) {
                                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().rotateAroundY(-0.9).multiply(2).setY(5));
                                            } else if (timesThisGiantMobIsOnOnePlace == 10) {
                                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().rotateAroundY(-0.9).multiply(2).setY(5));
                                            } else if (timesThisGiantMobIsOnOnePlace == 13) {
                                                thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().rotateAroundY(0.9).multiply(2).setY(5));
                                                thisGiantMob.timesThisGiantMobIsOnOnePlace = 0;
                                            }

                                        } else {
                                            //обычный прыжок
                                            thisGiantMobLivingEntity.setVelocity(thisGiantMobLoc.getDirection().clone().normalize().multiply(1).setY(1));
                                            // sendSysMsgToPlayer(Bukkit.getPlayer("Evropejets"), "HIGH");
                                        }

                                    } else {
                                        //если он сдвинулся, обнуляем счетчик нахождения на одном месте по XZ
                                        thisGiantMob.timesThisGiantMobIsOnOnePlace = 0;
                                    }

                                }
                            }.runTaskLater(DonationExecutor.getInstance(), 7);
                        }
                    }
                }
            }.runTaskTimer(DonationExecutor.getInstance(), 0, 10);
        }

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        //Заставляем моба стрелять файерболами
        private void makeGiantMobAttackWithFireballs() {
            final GiantMob thisGiantMob = this;
            new BukkitRunnable() {
                @Override
                public void run() {

                    LivingEntity thisGiantMobLivingEntity = thisGiantMob.giantMobLivingEntity;

                    //Если моб уже не существует, отменяем стрельбу
                    if ((thisGiantMobLivingEntity.isDead()) || (!(DonationExecutor.isRunning)) ) {
                        this.cancel();
                        return;
                    }

                    //Находим ближайшее ентити (игроки в приоритете), чтобы сделать из него цель для моба
                    LivingEntity target;
                    target = thisGiantMob.findGiantMobTarget();
                    if (target == null) {
                        return;
                    }

                    //Спавним файер болл на 2 блока ниже глаз (район между рук)
                    Fireball stalinBall;
                    stalinBall = (Fireball) thisGiantMobLivingEntity.getWorld().spawnEntity(thisGiantMobLivingEntity.getEyeLocation().clone()
                                    .add(genVec(thisGiantMobLivingEntity.getEyeLocation().clone(), target.getLocation()).clone().multiply(3.5)).clone()
                                    .add(0, -2, 0),
                            EntityType.FIREBALL);
                    stalinBall.setDirection(genVec(stalinBall.getLocation(), target.getLocation()).clone().multiply(2));

                }

            }.runTaskTimer(DonationExecutor.getInstance(), 0, 45);
        }

        private void makeGiantMobAttackWithSnowballs() {
            final GiantMob thisGiantMob = this;
            new BukkitRunnable() {
                @Override
                public void run() {
                    LivingEntity thisGiantMobLivingEntity = thisGiantMob.giantMobLivingEntity;

                    //Если моб уже не существует, отменяем стрельбу
                    if ( (thisGiantMobLivingEntity.isDead()) || (!(DonationExecutor.isRunning)) ) {
                        this.cancel();
                        return;
                    }

                    //Находим ближайшее ентити (игроки в приоритете), чтобы сделать из него цель для моба
                    LivingEntity target;
                    target = thisGiantMob.findGiantMobTarget();
                    if (target == null) {
                        return;
                    }

                    //Запускаем снежки в количестве howManySnowballsMobLaunches
                    for (int i = 0; i <= howManySnowballsMobLaunches; i++) {
                        final int finali = i;
                        final LivingEntity finalTarget = target;
                        new BukkitRunnable() {
                            @Override
                            public void run() {
                                if ( (thisGiantMob.giantMobLivingEntity.isDead())  || (!(DonationExecutor.isRunning)) ) {
                                    this.cancel();
                                    return;
                                }
                                Snowball snowball;
                                Location handHeightPoint;
                                handHeightPoint = thisGiantMobLivingEntity.getLocation().clone().add(0, 7, 0);
                                snowball = (Snowball) thisGiantMobLivingEntity.getWorld().spawnEntity(handHeightPoint.clone()
                                                .add(handHeightPoint.getDirection().rotateAroundY(0.7).multiply(3.5)),
                                        EntityType.SNOWBALL);
                                ItemStack itemStack = new ItemStack(Material.SNOWBALL, 1);
                                ItemMeta meta = snowball.getItem().getItemMeta();
                                meta.setLore(Collections.singletonList("Stalinball"));
                                itemStack.setItemMeta(meta);
                                snowball.setItem(itemStack);
                                snowball.setVelocity(genVec(snowball.getLocation(), finalTarget.getEyeLocation()).multiply(2.2));
                                snowball.getWorld().playSound(snowball.getLocation(), Sound.ENTITY_DRAGON_FIREBALL_EXPLODE, 3, 2);

                                //Каждый тик направляем снежок в игрока
                                if (SnowballsFollowingTarget) {
                                    new BukkitRunnable() {
                                        @Override
                                        public void run() {
                                            if ( (snowball.isDead()) || finalTarget.isDead() || (!(finalTarget.getWorld() == snowball.getWorld())) || (!(DonationExecutor.isRunning)) ) {
                                                this.cancel();
                                            } else {
                                                snowball.setVelocity(genVec(snowball.getLocation(), finalTarget.getEyeLocation()));
                                            }
                                        }
                                    }.runTaskTimer(DonationExecutor.getInstance(), finali * ticksBetweenSnowballsShots, 1);
                                }

                            }
                        }.runTaskLater(DonationExecutor.getInstance(), i * ticksBetweenSnowballsShots);
                    }
                }
            }.runTaskTimer(DonationExecutor.getInstance(), 0, 150);
        }
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //Проверка всех добавлений и удалений из мира, чтобы ловить и упаковывать подходящих гигантов или удалять их из списка
    private static class GiantMobEventListener implements Listener{

        GiantMobManager thisInstanceOfGiantMobManager;
        private GiantMobEventListener(GiantMobManager _thisInstanceOfGiantMobManager) {
            thisInstanceOfGiantMobManager = _thisInstanceOfGiantMobManager;
        }

    }
}
dokerplp commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/donationexecutor/DonationExecutor.java#L17-L21

Ааааааааааааааа!!!!!!!

Игорь это ОЧЕНЬ ОЧЕНЬ ОЧЕНЬ плохо

Делать переменную public это уже огромная ошибка, но делать ее еще и static это одна из САМЫХ грубых ошибок вообще

dokerplp commented 2 years ago

Честно, после public static код уже не хочется смотреть

Совет: открой свой код в Inteliij Idea, (Community версии будет достаточно) и исправляй все, что она выделит желтым)))

noremac09 commented 2 years ago

Да в кубах почти 90% плагинов так по-уродски написано,. Для начала - вообще неплохо, и главное - работает. Для любителя пойдет, я видал и похуже код.

Имхо - ты очень сильно перегружаешь человека, суя ему в рот ломбок. Ему бы ООП освоить, понять для чего вообще геттеры/сеттеры нужны, немного их руками пописать, а потом уже упрощать себе жизнь этим ломбоком.

А так да, все написаное в треде - абслютно по факту.

noremac09 commented 2 years ago

И еще. НАХУЙ ЭТОТ ЕБУЧИЙ МАВЕН. ЮЗАЙ ПРАВОСЛАВНЫЙ, НОРМАЛЬНЫЙ ГРАДЛ.

dokerplp commented 2 years ago

Да, что-то я в раш пошел с ревью 😂, но про Lombok тоже неплохо почитать)

Ну у него maven там, я и кидаю ему maven)))

s3ponia commented 2 years ago

В yml есть нормальные списки и не надо поля через запятую разделять

StreamersNamesList: Evropejets,mdenz3
StreamersNamesList: 
  - Evropejets
  - mdenz3
link1107 commented 2 years ago

В yml есть нормальные списки и не надо поля через запятую разделять

StreamersNamesList: Evropejets,mdenz3
StreamersNamesList: 
  - Evropejets
  - mdenz3

Списки есть, только о работе с ними в офиц гайдах спигота я не нашел. Скостылил просто строкой. Через зпт.

Честно, после public static код уже не хочется смотреть

Совет: открой свой код в Inteliij Idea, (Community версии будет достаточно) и исправляй все, что она выделит желтым)))

Спасибо за правки, по некоторым я и так в курсе был, просто на работе плагина оно не сказывалось, поэтому планировал позже доделать. Я о каких-то вещах в Джаве узнавал по ходу написания очередного класса, поэтому в некоторых классах есть тупые ошибки, которых нет уже в других классах. Энивей все это рефакторить надо, так что спасибо за конкретные советы.

YakymetsVova commented 2 years ago

https://github.com/link1107/DonationExecutor/blob/0645d8a449354105accbcfba10cc2212d17021d2/src/main/java/igorlink/command/DonationExecutorCommand.java#L55-L59

Очень плохое логгирование

  1. НИКОГДА не используй e.printStackTrace();
  2. Не нужно городить велосипед, есть множество готовых логгеров, самый простой для тебя, вероятно будет SLF4J - подключается очень просто maven:
<!--SLF4J-->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.0-alpha5</version>
        </dependency>

Дальше в коде пишешь

private final Logger logger = LoggerFactory.getLogger(YourClassName.class);

и все

Да, и еще - использовать 1 логгер на все приложение, это тоже очень плохо, лучше в каждом классе, в котором тебе необходимо логгирование прописывать конструкцию выше

In the case of using Lombok, consider using @Slf4j annotation

HackMemory commented 2 years ago

@dokerplp когда после лоулевела, ничего не осталось ревьюить))

dokerplp commented 2 years ago

@dokerplp когда после лоулевела, ничего не осталось ревьюить))

Есть такое)