Ускоритель мира

Версия Minecraft
1.7.10
API
Forge
236
4
22
Доброе утро всем. Подскажите пожалуйста, как в Forge можно реализовать "ускорение тайлов"? Я конечно понимаю, что для этого я должен чаще вызывать метод updateEntity() всем тайлам в мире, но вопрос, как получить все тайлы во всех загруженных чанках? На сколько я понял, мне нужно будет ловить ворлд тик ивент и в нём уже нужное кол-во раз вызывать updateEntity() для каждого тайла. Вообще, я нашёл 1 List в World и попробовал пройтись циклом, но в ближайшие 10 минут я получил краш с ошибкой ConcurentModificationExeption.
TickHandler:
@SubscribeEvent
    public void onTick(TickEvent.WorldTickEvent event)
    {
        if(event.phase == TickEvent.Phase.END || event.world.provider.dimensionId != ConfigurationHandler.dimensionId) return;
        for(int count = 0; count<ConfigurationHandler.worldTickSpeed; count++)
        {
            for (TileEntity tileentity : (Iterable<TileEntity>)event.world.loadedTileEntityList)
            {
                if (!tileentity.isInvalid() && tileentity.hasWorldObj() && event.world.blockExists(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord))
                {
                    try{tileentity.updateEntity();}catch(Throwable ignore){}
                }
            }
        }
    }
Других способов получить все активные тайлы я пока, увы, не нашёл :(. Также, как по мне, код выше - нагрузочный. Можно ли его сделать менее убойным для игры? Заранее всем спасибо за ответы!
 
А если использовать fori, то не будет шанса словить out of bounds? Если к списку всегда обращаются в одном потоке, то его никто не изменяет и ConcurentModificationExeption не должен бросаться, почему тогда for each не работает?
 
Как минимум get() из List с пределом границы просто вернёт null без исключений
Нет))

Если к списку всегда обращаются в одном потоке, то его никто не изменяет и ConcurentModificationExeption не должен бросаться
Сразу видно зеленого хоха)) Эта штука вылезает не только из-за этого. Если ты бежишь по списку через for-each и в этот же момент редактируешь список, то тебе кинет эксепшн. И неважно когда это происходит, в одном потоке или другом.
Правило простое: хочешь во время итерации изменять список - используй итератор явно.
В данном случае майн удаляет где-то из списка какой-то тайл, а ты в этом время по этому списку итерируешься. Вот и крашится. Тут либо реализацию листа менять на CopyOnWriteArrayList, либо делать ручками копию списка перез итерацией.
 
Да знаю я про эту особенность for each и итераторов, хех) Так у него в первом варианте кода не было модификации листа внутри цикла
~~~
В данном случае майн удаляет где-то из списка какой-то тайл
Так он это чтоли параллельно в другом потоке делает?
В коде же нет передачи управления майну. Разве что тайл сам себя удаляет
Java:
for (TileEntity tileentity : (Iterable<TileEntity>)event.world.loadedTileEntityList)
    if (!tileentity.isInvalid() && tileentity.hasWorldObj() && event.world.blockExists(tileentity.xCoord, tileentity.yCoord, tileentity.zCoord))
        try{tileentity.updateEntity();}catch(Throwable ignore){}
 
Последнее редактирование:
Это просто заплатка. Проблему оно не решит: если один тайл с индексом меньше текущего был удален из списка при итерации, то обработка какой-то тайла будет пропущена. А если был добавлен тайл с индексом меньше текущего, то текущий тайл будет обработан дважды
 
Так он это чтоли параллельно в другом потоке делает?
Блок может сломаться и удаляться тайл посередине тика, как раз в тот момент когда мы в ивенте пробегаем по списку.
 
Назад
Сверху