Open Dymeth opened 5 months ago
Для решения части из этих проблем я делал форк paper с изменённой логикой загрузки/сохранения чанков в мире. Но, скорее всего, этот вариант вас не устроит, т.к. вы ориентируетесь на самодостаточность плагина и отсутствие зависимости от конкретной платформы
По второй проблеме, если телепортировать игроков не асинхронно, а использовать классический метод Player#teleport
? В теории это не должно сильно повлиять на производительность, т.к. чанки спавна зачастую будут погружены (благодаря той же настройке World#setKeepSpawnInMemory(true)
)
По второй проблеме, если телепортировать игроков не асинхронно, а использовать классический метод
Player#teleport
? В теории это не должно сильно повлиять на производительность, т.к. чанки спавна зачастую будут погружены (благодаря той же настройкеWorld#setKeepSpawnInMemory(true)
)
Даже при синхронной телепортации требуется задержка минимум в 1 тик (возможно и больше, пока не тестировал это досконально). А если нужна задержка - это шедулер. А если шедулер - то 3-я проблема по-прежнему актуальна
В бакките творится какой-то ад с управлением мирами и сохранением отдельных чанков. В итоге не удаётся отменять сохранение ненужных чанков. Ниже пойдёт речь о проблемах в коде выгрузки и миров, реализованной в данном менеджере: https://github.com/Slomix/ParkourBeat/blob/main/src/main/java/ru/sortix/parkourbeat/world/WorldsManager.java
Проблема №1:
ChunkUnloadEvent
НЕ вызываются при отгрузке миров. Это касается абсолютно любых чанков - и тех, которые могут быть выгружены "вручную", и тех, которые не могут быть выгружены сейчас по тем или иным причинам. Из-за этого приходится перед выгрузкой миров пытаться вручную выгружать все чанки мира - для того, чтобы вызыватьChunkUnloadEvent
'ы и отключить сохранение отдельных чанков. Однако стоит учесть, чтоChunkUnloadEvent
НЕ вызывается, если чанк используется, и не может быть отгружен в данный момент. Поэтому наша задача подготовить все чанки к выгрузке - например, телепортировать всех игроков в другой мир.Существует ещё один способ отменять сохранение лишь отдельных чанков - передавать в метод
World.unloadChunk()
булин, отвечающий за сохранение. Данный вариант пока не тестировался. Стоит попытаться использовать этот способ - возможно так удастся решить перечисленные ниже проблемы. Однако с технической точки зрения этот способ значительно менее удобен, чем вариант сChunkUnloadEvent
, поскольку придётся передаватьPredicate
прям в метод отгрузки мира, мы лишаемся всей гибкости системы событий баккита.Проблема №2: Мир и конкретные чанки НЕ могут быть отгружены, если в них находится хотя бы один игрок. Поэтому при отгрузке все игроки телепортируются на спаун. Однако даже после завершения телепортаций чанки не могут быть отгружены в этот тик. Из-за этого приходится запускать отгрузку чанков в шедулере. Более того, даже задержки в 1 тик не всегда хватает. Бывает, что даже 3-х тиков мало - ощущение, что это какой-то рандом. Подозреваю, это связанно с асинхронными телепортациями игроков (даже несмотря на то, что мы дожидаемся завершения всех CompletableFuture).
Проблема №3: Шедулеры при выключении плагина использовать нельзя - они автоматически завершаются. Даже шедулер с задержкой в 1 тик выполнен не будет, если он был запущен в
onDisable()
. Таким образом, при выключении плагина мы и вовсе теряем возможность гибко управлять сохранением отдельных чанков. Мы можем отказаться от выгрузки миров при выключении плагина, но точно НЕ можем отказаться от запрета сохранения отдельных чанков, поскольку неизвестно, перезагружается ли только плагин или сервер целиком. Как решать данный вопрос - пока неясно.Проблема №4: Некоторые чанки не выгружаются даже через секунду после телепортации игроков. Телепортация и шедулер с задержкой позволяют выгрузить лишь ~30% всех чанков мира, для всех остальных метод
World#unloadChunk()
возвращаетfalse
по неизвестной причине. Была попытка использоватьWorld#setKeepSpawnInMemory(false)
, однако никакого результата она не дала. Возможно на применение этой опции тоже требуется минимум один тик. Пока не пытался запускать действия после этого с задержкой в 1 тик. Поэтому пока неясно, как управлять сохранением оставшихся ~70% чанков даже при каких-либо внутриигровых действиях, не связанных с выключением плагинаПроблема №5: В апи нет возможности сохранять лишь какие-то отдельные чанки - можешь лишь сохранить абсолютно все. Частичное сохранение пригодилось бы для регулярного сохранения данных уровня в режиме редактирования. Можно было бы просто включить автосохранение миров в ядре, но не существует никакого
UPD: Создал issue в гите PaperMC по 5-й проблеме
ChunkSaveEvent
, чтобы это сохранение при необходимости отменять. Существует лишьWorldSaveEvent
, который не подходит для решения данной задачи.Итог: 1) Мы абсолютно НЕ можем контролировать сохранение чанков при выгрузке плагина 2) При обычных геймплейных механиках мы можем контролировать сохранение лишь ~30% всех чанков
P.S. В данной теме на форуме человек утверждает, что отмена сохранения чанка приводит к невозможности его выгрузки, но подтвердить или опровергнуть эту теорию пока не удалось. ~70% чанков НЕ выгружаются, даже если ни для одного из чанков НЕ отключать сохранение.
P.P.S. Если не удастся в полной мере исправить управление сохранением чанков (в т.ч. при выключении плагина), то необходимо будет протестировать это всё на последнем билде Paper. Если проблема останется актуальной - необходимо написать багрепорты