Перейти к публикации

ENG_1


Рекомендованные сообщения

Вероятно исправлено, причинно-следственная цепочка очень длинная и сложная, поэтому есть вероятность что был исправлен какой-то соседний баг.

 

Описание для красноглазых задротов:

Скрытый текст

Для понимания процесса вы должны хотя бы примерно понимать что такое Bukkit и как работает сервер Minecraft.

При создании игры, сундуки на островах заполняются. В конце игры все сундуки очищаются и игра завершается. Однако во время очистки сундуков возникала ошибки и игра продолжалась вечно.

Для каждого сундука у нас хранится его локация в виде объекта Block и для его очистки/заполнения используется block.getState() метод. Все выглядит отлично, однако иногда при окончании игры на месте сундука почему-то не существовало сундука, хоть и block.getType() == Material.CHEST. Проблема оказалась в реализации Block (CraftBlock) и Chunk (CraftChunk).

public CraftBlock(CraftChunk chunk, int x, int y, int z) {
  this.x = x;
  this.y = y;
  this.z = z;
  this.chunk = chunk;
}

Block хранит свои координаты и чанк, в котором он находится, а не мир, как все думают.

Что происходит если этот чанк больше не используется, и он выгружается из памяти? Он удаляется из мира, но все блоки все также хранят ссылку на старый CraftChunk. Что же происходит когда в этом чанке появляется игрок и он снова загружается? Чанк добавляется в мир и существует без проблем.

Возникает ситуация, что у нас одновременно существует 2 копии чанка, одна из них старая (которая сохранилась в CraftBlock) и новая, текущая, где находится игрок и где он ломает сундук. Метод Block.getType() получает информацию о блоке из своего чанка, а метод Block.getState() получает "содержимое" блока из мира, где информация всегда актуальная.

CraftChunk немного пытается исправить ситуацию используя WeakReference<nms.Chunk>, вместо обычной ссылки на нмс чанк, однако этот "кеш" очищается и обновляется текущей копией из мира только во время полной сборки мусора (full gc). Это сложная тема и объяснить ее в нескольких предложениях невозможно, вкратце - кеш очищается в рандомное время, а не при выгрузке чанка из мира.

В качестве фикса, CraftChunk теперь всегда проверяет что у него в кеше находится актуальная версия нмс чанка, иначе он обновляется из мира.

 

Ссылка на комментарий

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас
  • Сейчас на странице   0 пользователей

    • Нет пользователей, просматривающих эту страницу.
×
×
  • Создать...