WorldGuardFork (Paper/Folia) | Рекомендуется на каждый современный сервер!

WorldGuardFork (Paper/Folia) | Рекомендуется на каждый современный сервер! 7.0.17-v1.5f

Создайте и подтвердите аккаунт для скачивания
то что школьники качают твои плагины на свои копии фантайма - это явно не то чем стоит гордиться. А про их полезность я бы очень поспорил, ведь за ихнее качество отвечает нейронка(я надеюсь хотя-бы не дипсик)
Мои плагины не для копий фантайма друг
Объединено

Шутки шутками и срачи срачами а у меня есть пара логичных придирок.

1) Почему вместо использования Caffeine cache, как альтернативы старой гуавы ( ), что было бы логично, в форке написана своя собственная реализация на конкурентных мапах. Работает я уверен это хуже, чем даже оригинальная гуава.
2) Если у нас форк нацелен на оптимизацию - почему до сих пор продолжается использование stream api даже в тех моментах, которые были изменены?
Банальный пример (первый попавшийся при сравнении):
List<LocalPlayer> wgPlayers = Bukkit.getServer().getOnlinePlayers().stream().map(player -> WorldGuardPlugin.inst().wrapPlayer((Player)player)).toList();
В оригинале там легаси collect(Collectors.toList());, так что замена очевидно была (при помощи инспеций Idea, пойдёт), но можно было бы пойти дальше и заменить на обычные циклы, что к слову было реализовано например в методе getBlocks, получается оптимизация какая-то выборочная
3) Иногда применение инспеций Idea не всегда хорошо
Очевидно - не стоило добавлять эти Objects.requireNotNull итп
Но другой момент - замена get(0) на getFisrt не имела смысла, поскольку под капотом он выполняет всю ту же работу, только добавляет околобессмысленную в нашей ситуации проверку на пустоту листа
Java:
default E getFirst() {
        if (this.isEmpty()) {
            throw new NoSuchElementException();
        } else {
            return this.get(0);
        }
    }
В целом get(0) при пустом листе и так и так бы высрал нам эксепшн, так что шило на мыло меняем (я знаю, что НУ ОЧЕВИДНО это влияет на производительность ПОЧТИ никак, но если заниматься байтоблядсвом то заниматься на полную)
4) Не ясно зачем было вырезать блеклист из WG целиком
Да, фича не самая полезная, но всё же может кто-то юзал! (как я)
5) Некоторые оптимизации не имеют смысла как таковые
Пример:
Код:
     public RegionResultSet(Set<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion) {
         this(NormativeOrders.fromSet(applicable), globalRegion, true);
         this.regionSet = switch (applicable.size()) {
             case 0 -> Collections.emptySet();
             case 1 -> Collections.singleton(applicable.iterator().next());
             default -> ImmutableSet.copyOf(applicable);
         };
     }
Что тут не так?
Реализация copy у ImmutableSet
Код:
public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
    /*
     * TODO(lowasser): consider checking for ImmutableAsList here
     * TODO(lowasser): consider checking for Multiset here
     */
    // Don't refer to ImmutableSortedSet by name so it won't pull in all that code
    if (elements instanceof ImmutableSet && !(elements instanceof SortedSet)) {
      @SuppressWarnings("unchecked") // all supported methods are covariant
      ImmutableSet<E> set = (ImmutableSet<E>) elements;
      if (!set.isPartialView()) {
        return set;
      }
    } else if (elements instanceof EnumSet) {
      EnumSet<?> clone = ((EnumSet<?>) elements).clone();
      ImmutableSet<?> untypedResult = ImmutableEnumSet.asImmutable(clone);
      /*
       * The result has the same type argument we started with. We just couldn't express EnumSet<E>
       * or ImmutableEnumSet<E> along the way because our own <E> isn't <E extends Enum<E>>.
       *
       * We are also performing a safe covariant cast to change <? extends E> to <E>.
       */
      @SuppressWarnings("unchecked")
      ImmutableSet<E> result = (ImmutableSet<E>) untypedResult;
      return result;
    }

    if (elements.isEmpty()) {
      // We avoid allocating anything.
      return of();
    }
    // Collection<E>.toArray() is required to contain only E instances, and all we do is read them.
    // TODO(cpovirk): Consider using Object[] anyway.
    @SuppressWarnings("unchecked")
    E[] array = (E[]) elements.toArray();
    /*
     * For a Set, we guess that it contains no duplicates. That's just a guess for purpose of
     * sizing; if the Set uses different equality semantics, it might contain duplicates according
     * to equals(), and we will deduplicate those properly, albeit at some cost in allocations.
     */
    int expectedSize =
        elements instanceof Set ? array.length : estimatedSizeForUnknownDuplication(array.length);
    return fromArrayWithExpectedSize(array, expectedSize);
  }
Тобиш под капотом он точно так же проверяет на то не является ли коллекция, которую мы копируем пустой, а если является - возвращаем ImmutalbeList.of, который возвращает уже единый экземпляр RegularImmutableSet.EMPTY
Тобиш в итоге оптимизация не имеет смысла, новых аллокаций тут и так не было бы
Предположу, что это не единственный случай, я прошелся лишь поверхностно
Собственно очевидный вопрос - проверялись ли нововведения на вшивость путём бенчмарков?

Помимо этого я бы задал пару вопросов по тому, зачем было менять архитектуру выделяя отдельные методы но при этом не улучшать общую же логику, как к примеру с методом spreadFlag, который можно было БЫ заменить на switch вместо if лесенки, но это уже мелочи.

Если исправить всякие мелочи и описанные кейсы то получится добротно, но сейчас я бы скорее не стал использовать этот форк...
вот, это реальный разбор, щас прочитаю, спасибо
 
отлично. Этим можно описать всю вашу студию "нам всё равно на людей, главное бабки". Ты дал мне ответ на вопрос, параллельно показав всему форуму свою и сущность своей студии, думаю после такого адекватные люди не хотят иметь с вами дел. Думать о деньгах нужно, но в меру, а ты явно ими озабочен так ещё и съезжаешь с вопроса
Манипулятивно, но да ладно. Сущность - вот это ты завернул, ты меня ещё с гитлером сравни, ну ты приколист конечно. Про деньги - если для тебя это секрет, ну то сочуствую. Все сводится к деньгам, какой смысл тратить время и силы на то от чего не будет какой-либы отдачи? Люди что-то заказали за деньги - мы это сделали, что тут плохого то я так и не понял
 
Манипулятивно, но да ладно. Сущность - вот это ты завернул, ты меня ещё с гитлером сравни, ну ты приколист конечно. Про деньги - если для тебя это секрет, ну то сочуствую. Все сводится к деньгам, какой смысл тратить время и силы на то от чего не будет какой-либы отдачи? Люди что-то заказали за деньги - мы это сделали, что тут плохого то я так и не понял
да я понял твою роль - ты просто паразит, дай мне почитать адекватную критику и ответить на неё, а не спорить с диванным воином
 
ты меня ещё с гитлером сравни
offtop
  1. Берём ник ExTr1se.
  2. Понимаем, что 1 — это именно цифра «1», а не буква I.
  3. Считаем позиции латинских букв в алфавите:
    E = 5, X = 24, T = 20, R = 18, 1 = 1, S = 19, E = 5.
  4. Сумма:
    5 + 24 + 20 + 18 + 1 + 19 + 5 = 92.
  5. Сворачиваем:
    9 + 2 = 11.
  6. 11-я буква латинского алфавита — K.
  7. K — первая буква слова Kampf.
  8. Kampf — второе слово в названии «Mein Kampf».
  9. «Mein Kampf» — книга Адольфа Гитлера.
  10. Следовательно: ExTr1se → Гитлер.
 
Шутки шутками и срачи срачами а у меня есть пара логичных придирок.

1) Почему вместо использования Caffeine cache, как альтернативы старой гуавы ( ), что было бы логично, в форке написана своя собственная реализация на конкурентных мапах. Работает я уверен это хуже, чем даже оригинальная гуава.
2) Если у нас форк нацелен на оптимизацию - почему до сих пор продолжается использование stream api даже в тех моментах, которые были изменены?
Банальный пример (первый попавшийся при сравнении):
List<LocalPlayer> wgPlayers = Bukkit.getServer().getOnlinePlayers().stream().map(player -> WorldGuardPlugin.inst().wrapPlayer((Player)player)).toList();
В оригинале там легаси collect(Collectors.toList());, так что замена очевидно была (при помощи инспеций Idea, пойдёт), но можно было бы пойти дальше и заменить на обычные циклы, что к слову было реализовано например в методе getBlocks, получается оптимизация какая-то выборочная
3) Иногда применение инспеций Idea не всегда хорошо
Очевидно - не стоило добавлять эти Objects.requireNotNull итп
Но другой момент - замена get(0) на getFisrt не имела смысла, поскольку под капотом он выполняет всю ту же работу, только добавляет околобессмысленную в нашей ситуации проверку на пустоту листа
Java:
default E getFirst() {
        if (this.isEmpty()) {
            throw new NoSuchElementException();
        } else {
            return this.get(0);
        }
    }
В целом get(0) при пустом листе и так и так бы высрал нам эксепшн, так что шило на мыло меняем (я знаю, что НУ ОЧЕВИДНО это влияет на производительность ПОЧТИ никак, но если заниматься байтоблядсвом то заниматься на полную)
4) Не ясно зачем было вырезать блеклист из WG целиком
Да, фича не самая полезная, но всё же может кто-то юзал! (как я)
5) Некоторые оптимизации не имеют смысла как таковые
Пример:
Java:
     public RegionResultSet(Set<ProtectedRegion> applicable, @Nullable ProtectedRegion globalRegion) {
         this(NormativeOrders.fromSet(applicable), globalRegion, true);
         this.regionSet = switch (applicable.size()) {
             case 0 -> Collections.emptySet();
             case 1 -> Collections.singleton(applicable.iterator().next());
             default -> ImmutableSet.copyOf(applicable);
         };
     }
Что тут не так?
Реализация copy у ImmutableSet
Java:
public static <E> ImmutableSet<E> copyOf(Collection<? extends E> elements) {
    /*
     * TODO(lowasser): consider checking for ImmutableAsList here
     * TODO(lowasser): consider checking for Multiset here
     */
    // Don't refer to ImmutableSortedSet by name so it won't pull in all that code
    if (elements instanceof ImmutableSet && !(elements instanceof SortedSet)) {
      @SuppressWarnings("unchecked") // all supported methods are covariant
      ImmutableSet<E> set = (ImmutableSet<E>) elements;
      if (!set.isPartialView()) {
        return set;
      }
    } else if (elements instanceof EnumSet) {
      EnumSet<?> clone = ((EnumSet<?>) elements).clone();
      ImmutableSet<?> untypedResult = ImmutableEnumSet.asImmutable(clone);
      /*
       * The result has the same type argument we started with. We just couldn't express EnumSet<E>
       * or ImmutableEnumSet<E> along the way because our own <E> isn't <E extends Enum<E>>.
       *
       * We are also performing a safe covariant cast to change <? extends E> to <E>.
       */
      @SuppressWarnings("unchecked")
      ImmutableSet<E> result = (ImmutableSet<E>) untypedResult;
      return result;
    }

    if (elements.isEmpty()) {
      // We avoid allocating anything.
      return of();
    }
    // Collection<E>.toArray() is required to contain only E instances, and all we do is read them.
    // TODO(cpovirk): Consider using Object[] anyway.
    @SuppressWarnings("unchecked")
    E[] array = (E[]) elements.toArray();
    /*
     * For a Set, we guess that it contains no duplicates. That's just a guess for purpose of
     * sizing; if the Set uses different equality semantics, it might contain duplicates according
     * to equals(), and we will deduplicate those properly, albeit at some cost in allocations.
     */
    int expectedSize =
        elements instanceof Set ? array.length : estimatedSizeForUnknownDuplication(array.length);
    return fromArrayWithExpectedSize(array, expectedSize);
  }
Тобиш под капотом он точно так же проверяет на то не является ли коллекция, которую мы копируем пустой, а если является - возвращаем ImmutalbeList.of, который возвращает уже единый экземпляр RegularImmutableSet.EMPTY
Тобиш в итоге оптимизация не имеет смысла, новых аллокаций тут и так не было бы // We avoid allocating anything.
Предположу, что это не единственный случай, я прошелся лишь поверхностно
Собственно очевидный вопрос - проверялись ли нововведения на вшивость путём бенчмарков?

Помимо этого я бы задал пару вопросов по тому, зачем было менять архитектуру выделяя отдельные методы но при этом не улучшать общую же логику, как к примеру с методом spreadFlag, который можно было БЫ заменить на switch вместо if лесенки, но это уже мелочи.

Если исправить всякие мелочи и описанные кейсы то получится добротно, но сейчас я бы скорее не стал использовать этот форк...
важно: полноценных бенчмарков пока-что я не запускал, но планировалось начать ПОСЛЕ того как я реализую уже весь планируемый функционал, пока-что оптимизации я делал исключительно исходя из спарка замера over-ticks 30 и обычного постоянного профайлера (плагин выпущен недавно, думаю на данный момент не сильно критично)

1. Самописные кэши появились не случайно, они реально работают быстрее Guava решения, но кстати Caffeine cache интересное решение, насчёт него я утром посмотрю
2. Это было просто изменение синтаксиса, а не изменение направленное на оптимизацию, а в целом да, касаемо Stream API я пройдусь по коду и искореню его там, где он реально может что-то решать (к примеру в командах смысла будет от этого 0, но в обработчиках думаю прирост будет)
3. Полностью согласен, будет исправлено
4. Вообще честно я думал вырезать или нет, и я решил первоначально вырезать, а уже позже добавить аналоговую систему со своей реализацией, поэтому это будет, но в обновлениях
5. Касаемо RegionResultSet - согласен, исправлю.
6. spreadFlag менялся тупо потому что наглый CodeFactor видел в нём проблему и давал мне A (Вместо A+), а не с целью оптимизации. И по факту полностью переключить его на switch нельзя без переключения всех типов материалов грибов скалк и т.п., а это заморочка, но что-то придумать с этим думаю можно будет

и в заключение - спасибо за помощь в развитии форка, всё вышеописанное я учёл, в 1.6 уже буду замерять бенчмарком каждую микрооптимизацию) И касаемо пункта 6, что думаешь? Есть какие идеи?
 
Думаю перевод на свич будет логичным, да и должен быть побыстрее
окей, завтра-послезавтра начну работу, посмотрим что получится, ещё раз спасибо за конструктивный разбор
 
а я отвечу - НИКАКОЙ. Я о тебе нигде, никогда, ни откуда не слышал. Вся информация что по тебе есть - ты один из CakeStudio (Достижения круче не придумать, это же целая студия по охватам собирающая меньше моей когда я соло кодер, ок).

а вот лично я уже давно этим занимаюсь и успел выпустить кучу полезных плагинов для народа (бесплатных) и выпускаю платные чтобы как-то монетизировать своё творчество, ну, а судя по вашей кейкстудио из вклада у вас лишь заработанные деньги, нет ни 1 реально интересного бесплатного продукта, к примеру как мой hNear (Превосходящий ваш неар), как мой WorldGuardFork которому у вас даже близко ничего равноценного нет.

даже если разбирать не конкретно тебя, а всю твою студию и её активность всё что вы делаете - отмываете деньги и устраиваете в данный момент глупый срач буквально ни о чём, кстати странно за что IBotus дали разработчика+, всего 4 бесплатных плагина из которых 1 уступает моему аналогу, а эндерчест фильтров как и скупщиков расплодилось столько, что на каждый вкус и цвет. Единственный плагин который реально я нигде не видел и он действительно полезный это на чары, и то плагин до жути простой, что не оправдывает статус разработчика+. Впрочем, мне всё равно, но ты ж там чёт зарекнулся на мою роль, поэтому вы как-то менее подходите на эту плашку чем я, увы
Если тебе так интересно, почему мне выдали и за что, и да, мне выдали ещё очень давно
 

Вложения

  • Screenshot_20261005-011314~2.jpg
    Screenshot_20261005-011314~2.jpg
    55.9 KB · Просмотры: 5
offtop
  1. Берём ник ExTr1se.
  2. Понимаем, что 1 — это именно цифра «1», а не буква I.
  3. Считаем позиции латинских букв в алфавите:
    E = 5, X = 24, T = 20, R = 18, 1 = 1, S = 19, E = 5.
  4. Сумма:
    5 + 24 + 20 + 18 + 1 + 19 + 5 = 92.
  5. Сворачиваем:
    9 + 2 = 11.
  6. 11-я буква латинского алфавита — K.
  7. K — первая буква слова Kampf.
  8. Kampf — второе слово в названии «Mein Kampf».
  9. «Mein Kampf» — книга Адольфа Гитлера.
  10. Следовательно: ExTr1se → Гитлер.
Штирлиц ещё никогда не был так близко к провалу...
Объединено

да я понял твою роль - ты просто паразит, дай мне почитать адекватную критику и ответить на неё, а не спорить с диванным воином
Сущность, паразит, диванный воин - ух ты какой у тебя словарный запас, в школе небось одни пятерки
 
Последнее редактирование:
Назад
Сверху Снизу