package codes.biscuit.skyblockaddons.utils; import codes.biscuit.skyblockaddons.SkyblockAddons; import codes.biscuit.skyblockaddons.core.Feature; import codes.biscuit.skyblockaddons.listeners.PlayerListener; import lombok.Getter; import net.minecraft.client.Minecraft; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import org.apache.commons.lang3.mutable.MutableInt; import java.util.*; public class Scheduler { private SkyblockAddons main = SkyblockAddons.getInstance(); private long totalTicks = 0; private Map<Long, Set<Command>> queue = new HashMap<>(); /** * This class is a little something I came up with in order to schedule things * by client ticks reliably. * * @param commandType What you want to schedule * @param delaySeconds The delay in seconds (must be greater than 0) */ public void schedule(CommandType commandType, int delaySeconds, Object... data) { // If the delay isn't greater than zero, the command never gets executed. if (!(delaySeconds > 0)) { throw new IllegalArgumentException("Delay must be greater than zero!"); } long ticks = totalTicks+(delaySeconds*20); Set<Command> commands = queue.get(ticks); if (commands != null) { for (Command command : commands) { if (command.getCommandType() == commandType) { command.addCount(data); return; } } commands.add(new Command(commandType, data)); } else { Set<Command> commandSet = new HashSet<>(); commandSet.add(new Command(commandType, data)); queue.put(ticks, commandSet); } } /** * Removes all queued full inventory warnings. */ public void removeQueuedFullInventoryWarnings() { Iterator<Map.Entry<Long, Set<Command>>> queueIterator = queue.entrySet().iterator(); List<Long> resetTitleFeatureTicks = new LinkedList<>(); while (queueIterator.hasNext()) { Map.Entry<Long, Set<Command>> entry = queueIterator.next(); if (entry.getValue().removeIf(command -> CommandType.SHOW_FULL_INVENTORY_WARNING.equals(command.commandType))) { resetTitleFeatureTicks.add(entry.getKey() + main.getConfigValues().getWarningSeconds() * 20); main.getLogger().debug("Full Inventory Warning Task Removed!"); } // Remove the corresponding reset title feature command. if (resetTitleFeatureTicks.contains(entry.getKey())) { Set<Command> commands = entry.getValue(); Iterator<Command> commandIterator = commands.iterator(); while (commandIterator.hasNext()) { Command command = commandIterator.next(); if (command.commandType.equals(CommandType.RESET_TITLE_FEATURE)) { commandIterator.remove(); main.getLogger().debug("Full Inventory Warning Reset Task Removed!"); break; } } } } } private boolean delayingMagmaCall = false; // this addition should decrease the amount of calls by a lot @SubscribeEvent() public void ticker(TickEvent.ClientTickEvent e) { if (e.phase == TickEvent.Phase.START) { totalTicks++; Set<Command> commands = queue.get(totalTicks); if (commands != null) { for (Command command : commands) { for (int times = 0; times < command.getCount().getValue(); times++) { command.getCommandType().execute(command, times+1); } } queue.remove(totalTicks); } if (totalTicks % 12000 == 0 || delayingMagmaCall) { // check magma boss every 15 minutes if (main.getPlayerListener().getMagmaAccuracy() != EnumUtils.MagmaTimerAccuracy.EXACTLY) { if (main.getUtils().isOnSkyblock()) { delayingMagmaCall = false; main.getUtils().fetchMagmaBossEstimate(); } else if (!delayingMagmaCall) { delayingMagmaCall = true; } } } ChromaManager.increment(); // Run every tick } } @Getter private class Command { private CommandType commandType; private MutableInt count = new MutableInt(1); private Map<Integer, Object[]> countData = new HashMap<>(); private Command(CommandType commandType, Object... data) { this.commandType = commandType; if (data.length > 0) { countData.put(1, data); } } private void addCount(Object... data) { count.increment(); if (data.length > 0) { countData.put(count.getValue(), data); } } Object[] getData(int count) { return countData.get(count); } } public enum CommandType { RESET_MAGMA_PREDICTION, SUBTRACT_MAGMA_COUNT, SUBTRACT_BLAZE_COUNT, RESET_TITLE_FEATURE, RESET_SUBTITLE_FEATURE, ERASE_UPDATE_MESSAGE, SET_LAST_SECOND_HEALTH, DELETE_RECENT_CHUNK, SHOW_FULL_INVENTORY_WARNING, PROCESS_UPDATE_CHECK_RESULT; public void execute(Command command, int count) { SkyblockAddons main = SkyblockAddons.getInstance(); PlayerListener playerListener = main.getPlayerListener(); Object[] commandData = command.getData(count); if (this == SUBTRACT_MAGMA_COUNT) { playerListener.setRecentMagmaCubes(playerListener.getRecentMagmaCubes()-1); } else if (this == SUBTRACT_BLAZE_COUNT) { playerListener.setRecentBlazes(playerListener.getRecentBlazes()-1); } else if (this == RESET_MAGMA_PREDICTION) { if (playerListener.getMagmaAccuracy() == EnumUtils.MagmaTimerAccuracy.SPAWNED_PREDICTION) { playerListener.setMagmaAccuracy(EnumUtils.MagmaTimerAccuracy.ABOUT); playerListener.setMagmaTime(7200); } } else if (this == DELETE_RECENT_CHUNK) { int x = (int)commandData[0]; int z = (int)commandData[1]; IntPair intPair = new IntPair(x,z); playerListener.getRecentlyLoadedChunks().remove(intPair); } else if (this == SHOW_FULL_INVENTORY_WARNING) { Minecraft mc = Minecraft.getMinecraft(); if (mc.theWorld == null || mc.thePlayer == null || !main.getUtils().isOnSkyblock()) { return; } main.getInventoryUtils().showFullInventoryWarning(); // Schedule a repeat if needed. if (main.getConfigValues().isEnabled(Feature.REPEAT_FULL_INVENTORY_WARNING)) { main.getScheduler().schedule(Scheduler.CommandType.SHOW_FULL_INVENTORY_WARNING, 10); main.getScheduler().schedule(Scheduler.CommandType.RESET_TITLE_FEATURE, 10 + main.getConfigValues().getWarningSeconds()); } } else if (this == RESET_TITLE_FEATURE) { main.getRenderListener().setTitleFeature(null); } else if (this == RESET_SUBTITLE_FEATURE) { main.getRenderListener().setSubtitleFeature(null); } else if (this == ERASE_UPDATE_MESSAGE) { main.getRenderListener().setUpdateMessageDisplayed(true); } else if (this == SET_LAST_SECOND_HEALTH) { main.getPlayerListener().setLastSecondHealth((int) commandData[0]); } else if (this == PROCESS_UPDATE_CHECK_RESULT) { main.getUpdater().processUpdateCheckResult(); } } } }