Система временных эффектов (Замена Potion)

Система временных эффектов (Замена Potion)

Нет прав для скачивания
243
28
207
AustereTony добавил(а) новый ресурс:

Система временных эффектов (Замена Potion) - Те, кого не устраивают стандартные эффекты зелий - добро пожаловать!

Предисловие​

Здравствуйте. В данном туториале я опишу процесс создания собственной системы временных эффектов (баффов) для игрока. Работают они так же, как и ванильные эффекты зелий, однако имеют ряд улучшений и оптимизаций. Туториал написан под версию 1.7.10, и для реализации требуются настроенные EEP (заменить на Capability в более поздних версиях) и пакетная система, ну и знание классов стандартного пакета java util.

Данный туториал не содержит...​

Узнать больше об этом ресурсе...
 
Реализации по замене ванильной на такую не будет?
 
AustereTony обновил(а) ресурс Система временных эффектов (Замена Potion) новой записью:

Обновление #1

Обновлён BuffManager. Заменил обычный массив на ArrayList, добавил метод getBuff() для упрощения доступа к элементам. Теперь создание эффектов стало ещё проще, спасибо Agravaine за совет.

Узнать больше об этом обновлении...
 
Вау. Это действительно круто (подача отличная)!

@AustereTony, можете добавить иконку к ресурсу? Тогда будет совсем красота!
 
В эвенте не советую) В наследнике Potion можно переопределить все необходимые методы для применения чего угодно. А если по существу, то создание собственной системы позволяет слепить всё что угодно в зависимости от потребностей и не добавлять ничего лишнего.
Почему ж эвенте не советуешь? Там тоже можно установить разные промежутки времени благодаря ticksExisted
 
@Maxik001, несомненно.

Предполагаю, что проверяешь как-то так:
Java:
        if (player.isPotionActive(potion)) {   //Если potion активно.    

            if (player.ticksExisted % 20 == 0) {
                
                player.heal(3.0F);//хил 3 пункта раз в секунду.
            }
        }
Зачем лишний раз каждый тик проверять(делать запрос в HashMap), если главный цикл делает это вызывая isReady() и performEffect() в Potion (мы же создаём наследника и можем переопределить их). Вот как применять эффект не создавая дополнительной нагрузки:
Java:
    public void performEffect(EntityLivingBase entityliving, int tier) {
        
        //Вызывается только если isReady() вернёт true;
        
        if (entityliving.getHealth() < entityliving.getMaxHealth()) {
            
            entityliving.heal(3.0F);
        }
    }
    
    public boolean isReady(int duration, int tier) {
        
        return duration % 20 == 0;//вернёт true каждую секунду.
    }
Если же нужно что то добавить/удалить один раз, то нужно переопределять:
Java:
    public void applyAttributesModifiersToEntity(EntityLivingBase entitiLiving, BaseAttributeMap map, int tier) {
        
        //Вызывается однократно при применении эффекта.
    }
    
    public void removeAttributesModifiersFromEntity(EntityLivingBase entityLiving, BaseAttributeMap map, int tier) {
        
        //Вызывается однократно при удалении эффекта.
    }
Они так же вызываются однократно при добавлении/удалении эффекта. В самом деле, неужели лучше поступать так:
Java:
        if (player.getActivePotionEffect(potion).getDuration() == 1) {   
            
            //Удаление модификаторов.
        }
Поначалу я и сам использовал тик-эвенты, но через десяток другой проверок сервер стал подлагивать.
 
AustereTony обновил(а) ресурс Система временных эффектов (Замена Potion) новой записью:

Обновление #2

Туториал переписан для использования со всеми EntityLivingBase.

Вся работа с эффектами перенесена в BuffManager, класс с EEP можно создать и забыть.

Исправлены некоторые недочёты, добавлены новые методы.

Узнать больше об этом обновлении...
 
  • Like
Реакции: CMTV
Похоже, намечается супер-гайд. Что думаете?
 
Гайд, конечно, хороший, но слишком жирный для гайда. :unsure: Это можно было бы оформить, как либу (или просто как пачку классов для прямого копипаста), сделать немного по-красивее и больше функционала. У меня есть к чему придраться. Если интересно, могу высказать.
 
@Dahaka, выкладывай, буду принимать меры. Насчёт либы подумаю, но на мой взгляд ради трёх классов нет смысла.
 
Окей.
1. Manager в названии класса BuffManager ни к месту. Это не Manager. Назови лучше просто Buff. А ActiveBuff переименуй в BuffState.
2. Метод BuffManager#getBuff переименуй в BuffManager#of. BuffManager.of(5) выглядит красивее, чем BuffManager.getBuff(5).
3. В методах onActive, isReady ты пробрасываешь через параметры tier, duration. Пробрасывай лучше весь ActiveBuff.
4. Почему BuffManager#applyBuffEffect и BuffManager#removeBuffEffect статические - мне непонятно.
5. BuffManager#getDurationForDisplay тоже почему-то статический. По идее, если нужен бесконечный баф, то можно было бы переопределить этот метод, чтобы выводить --:--.
6. То что майн и ты завязали текущий стейт на простом ActiveBuff - не очень удобно. А что если понадобится еще один динамический параметр? Решение - создавать ActiveBuff через BuffManager, т.е. немного изменить класс
Java:
public class BuffManager<T extends ActiveBuff> {
    ...

    public T newState(int tier, int duration) {
        return new ActiveBuff(id, tier, duration);
    }

    ...
}
И естественно везде ActiveBuff заменить на T. Таким образом можно будет создавать кастомные стейты. Но тогда придется изменить readBuffFromNBT. Нужно будет сначала читать id, создавать ActiveBuff при помощи BuffManager, а затем вызывать ActiveBuff#readFromNBT.
7. private Map<Integer, ActiveBuff> activeBuffs сделай final.
8. В BuffsLivingBase #haveActiveBuffs нет смысла в проверке на null.
9. BuffsLivingBase#activeBuffsIdSet должен возвращать Set<Integer>.
10. BuffsLivingBase#activeBuffsCollection должен возвращать Set<ActiveBuff>.
11. Замени везде итераторы на foreach циклы.
Java:
for (ActiveBuff buff : activeBuffsCollection()) {
    ...
}
12. new BuffsOverlay(). Создай объект один раз, а потов вызывай какой-нибудь draw.
13. То что ты никогда не синхронишь кулдаун с сервера на клиент немного странно. Что если на сервере лаги? Тогда эффект на клиенте пропадет значительно раньше. Лаги на клиенте - аналогично. По факту эффект пропадет, но игрок будет думать, что баф наложен.
 
А тут есть над чем поработать) Идея в пункте 6 - вот это интересно. Заменять итераторы на foreach такое себе. Конечно удобочитаемость кода повысится, но в производительности выигрыша не будет, да и не все итераторы у меня просто перебирают элементы, а foreach не даст модифицировать мапу в процессе. Но заменить все остальные стоит, это да. На счёт синхронизации - эффекты удаляет только сервер и шлёт игроку пакет об этом, так что проблем не должно возникать (если не лагает сервер). Всё остальное подправлю.

Ну и собираюсь добавить информацию по адаптации на 1.12.2.
 
  • Like
Реакции: CMTV
@Dahaka, поправил.

1. BuffManager на Buff, ActiveBuff оставил как есть.
2. Сделано.
3. Сделано.
4. Совсем забыл, что они не переопределяются. Исправил.
5. Поправил. Добавил новый флаг для создания постоянного эффекта за одно.
6. Над дженерик-стейтами буду работать.
7. Исправлено.
8. Исправлено.
9. Исправлено.
10. Может всё таки Collection?
11. Заменил, где можно.
12. Сделано.
13. Было норм, но не было синхронизации при добавлении с сервера, добавил.
 
  • Like
Реакции: CMTV
AustereTony обновил(а) ресурс Система временных эффектов (Замена Potion) новой записью:

Обновление #3

Туториал дополнен информацией по адаптации на 1.12.2, а так же добавлена ссылка на исходники для обеих версий.

Множественные правки кода, фикс недоработок.

Узнать больше об этом обновлении...
 
Сегодня вечером выложу гайд на сайт + досрочно достижение супер-гайд 2018.
 
@AustereTony приложи, пожалуйста, рабочие исходники или ссылку на GitHub.
 
Назад
Сверху