ScheduledExecutorService падает при повторной сборке в debug

Версия Minecraft
1.6.4
355
2
17
Собственно проблема в названии, когда во время дебага пересобираю билд - все ExecutorService падают. Сталкивался может кто с таким? Постоянно перезапускать клиент накладно.

И вообще уместно ли использовать эти сервисы на серверной части (а может даже и клиентской). А то я замечал моменты что они попросту отваливались и не работали.
 
Вот такую системку структур в отдельный поток выделить

Еще вот заметил, что выполняя setblock в этих потоках, они иногда видимо скипаются или просто не выполняются. Это видно на видео, там блок листвы остался, каждая рубка всегда какие-то блоки разные остаются.
 
Последнее редактирование:
Еще заметил такую странность, что при сете в потоке иногда блоки не сразу появляются на клиенте. Технически они там есть, но "визуально" багаются.
Пакеты медленно синхронизируются мб. Придумаешь решение - обязательно выложи сюда, буду признателен
 
Но ты от силы 20 блоков ставишь, что тут медленного в однопотоке?
Это лишь пример, тут в целом механика установки структуры любого размера. Просто отдельный поток, который ломает, а затем проверяет нужно ли восстановить структуру, если да, начинает её восстанавливать поблочно, в идеале снизу-вверх.

Просто на опыте установки больших схем, сервер провисает в это мгновение, а если учитывать что это деревья, которые могут рубить игроки, и деревья эти могут быть разных размеров, от маленького дуба, до огромной ёли, то лучше это все-таки вынести в отдельный поток. В бакките с этим справляются бакит-шедулеры, а тут я не особо вник.
 
Нельзя НЕ в главном потоке устанавливать блок. Это не thread safe метод. Можешь откладывать установку блока, но делай это в главном потоке. Вот баккито-подобный шедюлер как раз подойдет для этого.
 
Так а такие вообще имеются у форжа?
В новых версиях можно отложить таск на следующий тик. Полноценного шедюлера нет.

Типа разбить все блоки на несколько групп допустим по 100 блоков и устанавливать их каждый тик?
Почему нет? Можно и по блоку на тик, чтобы красивенько было, отсортировав при этом список позиций.
 
В новых версиях можно отложить таск на следующий тик
Это конечно хорошо, но у меня не новая версия и нужна аналогия этих вот шедулерров.
У меня сейчас по сути и текущий ScheduledExecutorService выполняет поставленную задачу, единственное что иногда визуальные приколы, якобы блок стоит но на клиенте не видно. Но для полноценной работы мне нужна четкая работа этого шедуллера, с возможность ребилда при дебаге.
 
Видать я явно что-то делал не так, ибо не завелось. Под версию 1.6.4
И насколько я понял, он основывается на ITickHandler, разве будь таких тасков чуть больше, они не будут тормозить друг друга и в целом сервер? Или сервер не ожидает окончания tickStart и идет дальше?

Java:
public final class Scheduler
{

    private static Scheduler server;
    private static Scheduler client;

    /**
     * <p>Return a Scheduler that executes tasks on the main server thread.</p>
     * @return a Scheduler
     */
    public static Scheduler server(){
        return server;
    }

    /**
     * <p>The Scheduler that executes tasks on the main client thread. On a dedicated server this method will return null.</p>
     * @return a Scheduler or null
     */
    public static Scheduler client(){
        return client;
    }

    /**
     * <p>Return {@link #client()} if {@code side} is {@code Side.CLIENT}, {@link #server()} otherwise.</p>
     * @param side the side
     * @return a Scheduler for the side
     */
    public static Scheduler forSide(Side side){
        return side.isClient() ? client : server;
    }

    public void execute(Runnable task){
        schedule(task, 0);
    }

    /**
     * <p>Execute the given task after {@code tickDelay} ticks have passed.</p>
     * @param task the task
     * @param tickDelay the delay, in ticks
     */
    public void schedule(Runnable task, long tickDelay){
        checkArgument(tickDelay >= 0);
        synchronized(ticker.queue)
        {
            ticker.queue.add(new Task(task, tickDelay + 1));
        }
    }

    static{
        if(FMLCommonHandler.instance().getSide().isClient()){
            client = new Scheduler(Side.CLIENT);
            TickRegistry.registerTickHandler(client.ticker, Side.CLIENT);
            //MinecraftForge.EVENT_BUS.register(client.ticker);
        }else{
            client = null;
        }

        server = new Scheduler(Side.SERVER);

        TickRegistry.registerTickHandler(server.ticker, Side.SERVER);
        //MinecraftForge.EVENT_BUS.register(server.ticker);
    }

    private final Ticker ticker;

    private Scheduler(Side side){
        ticker = new Ticker(side);
    }

    private static class Task{

        public final Runnable runnable;
        public long ticks;

        public Task(Runnable taskRunnable, long taskTicks){
            runnable = taskRunnable;
            ticks = taskTicks;
        }
    }

    private static class Ticker implements ITickHandler
    {

        private final List<Task> queue = new ArrayList<Task>();
        private final List<Task> scheduledNow = new ArrayList<Task>();

        private final EnumSet<TickType> tickTypes;

        public Ticker(Side side) {
            tickTypes = EnumSet.of(side.isClient() ? TickType.CLIENT : TickType.SERVER);
        }

        @Override
        public void tickStart(EnumSet<TickType> type, Object... tickData)
        {
            synchronized (queue) {
                int idx = queue.size();
                while (--idx >= 0) {
                    Task task = queue.get(idx);
                    if (--task.ticks == 0) {
                        queue.remove(idx);
                        scheduledNow.add(task);
                    }
                }
            }
            int idx = scheduledNow.size();
            while (--idx >= 0) {
                scheduledNow.remove(idx).runnable.run();
            }
        }

        @Override
        public void tickEnd(EnumSet<TickType> type, Object... tickData) { }

        @Override
        public EnumSet<TickType> ticks() {
            return tickTypes;
        }

        @Override
        public String getLabel() {
            return "SC|Scheduler";
        }
    }
}
 
Там ошибка. Вынеси код из статик блока в отдельный метод и вызови где-то в преИнит.
Тут же пробежалась по всем точкам, проверили нужно ли им выполняться и все. Ничего блочить не должно.
 
Назад
Сверху