Разработка плагинов, бека, сайтов

Опыт
  1. 1 год
  2. 2 года
Портфолио (URL)
https://github.com/SakaPati/SpectraStats
Связь
https://t.me/k4vrix

Fozeton

Пользователь
Сообщения
2

📋 О себе​

Занимаюсь разработкой плагинов для Minecraft. В основном работаю на Java под Paper. Также умею делать сайты и несложный backend для Minecraft-проектов.

Сейчас ищу интересные проекты, где смогу развиваться, получать опыт и приносить реальную пользу серверу.

🔧 Что могу предложить​

Разработка плагинов​

Создание плагинов под ваши задачи:
  • игровые механики
  • системы команд
  • GUI

Веб-разработка​

Также могу помочь с:
  • созданием сайта для сервера
  • frontend на React
  • несложным backend
  • личными кабинетами / статистикой / API

🛠 Стек​

  • Java
  • PaperMC API
  • HTML / CSS / JavaScript / React

💼 Примеры работ​

SpectraStats​

Статистика Minecraft-сервера с разделением на:
  • PaperMC плагин
  • backend на Spring Boot
  • frontend на React
Функционал:
  • сбор и обработка игровой статистики
  • API для взаимодействия плагина и сайта
  • отображение данных на веб-интерфейсе
GitHub:

📌 Что ищу​

Интересные Minecraft-проекты, где нужны:
  • кастомные плагины
  • помощь с разработкой
  • сайт или веб-часть проекта
  • доработка существующего функционала
Особенно интересны нестандартные режимы и проекты с перспективой развития.

📞 Контакты​

Telegram: @k4vrix
Discord: saikad
 
Изучил код Вашего проекта - статистика для Minecraft (PaperMC плагин + Spring Boot + React).
Идея то хорошая, архитектура грамотная, НО есть серьёзные проблемы.

И так самое критишное:

1. Плагин↔Бэк не работает

Код:
// sender.postDate("/player/statistic/", json);

2. Credentials в публичном репозитории

backend/src/main/resources/application.properties
Код:
spring.datasource.password=root
Нет .env, нет application-local.properties в .gitignore. Пароль к БД в паблике и ещё какой сложный)

3. Хардкод URL

Код:
private final static String BASE_URL = "http://localhost:8080/api";
Нет config.yml == Поменять адрес backend без перекомпиляции невозможно.


Менее критишное:

4. Пустой onDisable()
При выключении сервера не закрывается HttpClient, не завершаются Virtual Threads, не сбрасывается накопленная статистика.
Утечки ресурсов ГАРАНТИРОВАНЫ.

5. Нет аутентификации на API
Любой желающий может POST'ить на /api/player/statistic и перезаписать статистику любого игрока. Ни API-ключа, ни токена, ни IP whitelist
Вам необходимо зарегистрироваться для просмотра изображений-вложений
.

6. Ник вместо UUID как primary key
PlayerStats идентифицируется по имени игрока, а не по UUID. Ники можно менять - при смене ника статистика игрока испарится.

7. session.getLast() без проверки
В методе disconnect() вызов player.getSession().getLast() без проверки на пустой список.
Вывод - При рестарте сервера или рассинхронизации - NoSuchElementException в рантайме.


Ну и самые мелочи

8. Нет Docker / docker-compose
Проект с PostgreSQL, Spring Boot и отдельным плагином - и ни одного docker-compose.yml. Поднять локально без дополнительных вопросов невозможно.

9. Нет тестов
Папка src/test присутствует, но судя по коммитам — пустая.


Возможно я в чём то не прав, но вроде расписал относительно логично.
 
Java:
    @JsonProperty("DROP")
    Map<@Size(max = 36) String, @Min(0) Object> drops;
    @JsonProperty("PICKUP")
    Map<@Size(max = 36) String, @Min(0) Object> pickups;
Map<String, Object> с аннотацией @Min(0). Это не сработает вообще, там нужен конкретный числовой тип типа Integer/примитив, а не Object. Как только Spring попробует это провалидировать — упадёт с ошибкой. Плюс drops и pickups у тебя не проинициализированы, в отличие от properties — если Jackson их не заполнит, будет null и потом NPE.

Java:
    OnlineSession session = player.getSession().getLast();
    session.setExitTime(LocalDateTime.now().toString());
Если у игрока нет ни одной сессии (например, дисконнект вызван без коннекта) — getLast() упадёт с исключением. Плюс нет гарантии, что это именно последняя по времени сессия, если коллекция нигде явно не отсортирована. И exitTime хранится как строка через toString() — так делать не стоит, нужен нормальный LocalDateTime в поле, а не строка.

Java:
@Transactional
    public void connect(String playerName) {
        Player player = playerRepo.findByPlayerName(playerName)
                .orElseGet(() -> {
                    Player regPlayer = new Player();
                    PlayerStats stats = new PlayerStats();
                    regPlayer.setPlayerName(playerName);
                    stats.setPlayer(regPlayer);
                    regPlayer.setStatistic(stats);
                    playerRepo.save(regPlayer);

                    return regPlayer;
                });

        OnlineSession session = new OnlineSession();
        session.setPlayer(player);
        onlineRepo.save(session);
    }
Нет проверки на уже открытую сессию. вот сервер крашнулся/перезагрузился без нормального шатдауна, и у части онлайна на тот момент disconnect так и не вызвался. При следующем коннекте таких игроков будет копиться "мусор" из незакрытых сессий, и со временем getLast() в disconnect() начнёт давать неверные результаты (или падать, если что-то пойдёт не так с порядком).

Java:
public record PlayerStatistic(
    String player,
    @Valid @NotNull WorldStat world,
На player нет @NotBlank/@NotNull. Если придёт null — упадёшь на statsRepo.findById(), а не на этапе валидации.


А так да, надо бы все в отдельные конфиги или .env файлы вынести, иначе каждому пользователю придется билдить твой проект чтобы поменять адрес БД.
 
Нет аутентификации на API
Пет-проект для портфолио же) Защита тут нужна примерно так же, как забор вокруг шалаша. Для продакшна, понятное дело, прикрутил бы JWT, а тут тупо лень было усложнять. А за остальные советы спасибо
 
Назад
Сверху Снизу