[1.7+] - Scheduler

tox1cozZ

aka Agravaine
8,453
599
2,906
Нашел неплохой Scheduler, похожий на баккитовский.
https://github.com/diesieben07/Seve...take_weiland/mods/commons/util/Scheduler.java
Переписал под 1.7+ и убрал лишние Deprecated методы.
Код:
import static com.google.common.base.Preconditions.checkArgument;

import java.util.ArrayList;
import java.util.List;

import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
import net.minecraftforge.fml.common.gameevent.TickEvent.Type;
import net.minecraftforge.fml.relauncher.Side;

/**
 * @author diesieben07
 */
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);
            FMLCommonHandler.instance().bus().register(client.ticker);
        }else{
            client = null;
        }

        server = new Scheduler(Side.SERVER);
        FMLCommonHandler.instance().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{

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

        private Side side;

        private Ticker(Side tickerSide){
            side = tickerSide;
        }

        @SubscribeEvent
        public void tick(TickEvent e){
            if(e.side == side && e.type == (side == Side.SERVER ? Type.SERVER : Type.CLIENT) && e.phase == Phase.START){
                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();
                }
            }
        }
    }
}
Возможно кому-то понадобится.
 
Не очень хороший скедулер, если честно. Каждый тик проверка на запуск равная O(N). Можно ведь сделать O(1), если добавить переменную времени (в какой тик запускать), там переписать всего ничего.
Ах да, и хранить таски в ArrayList, тогда на один тик можно будет повесить кучу тасков, при этом не меняя количество проверок на запуск этого списка тасков.
 
Назад
Сверху