package speedytools.serverside.actions; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.WorldServer; import speedytools.common.selections.VoxelSelectionWithOrigin; import speedytools.serverside.worldmanipulation.AsynchronousToken; import speedytools.serverside.worldmanipulation.UniqueTokenID; import speedytools.serverside.worldmanipulation.WorldHistory; /** * User: The Grey Ghost * Date: 3/08/2014 */ public abstract class AsynchronousActionBase implements AsynchronousToken { public AsynchronousActionBase(WorldServer i_worldServer, EntityPlayerMP i_player, WorldHistory i_worldHistory, int i_sequenceNumber) { worldServer = i_worldServer; entityPlayerMP = i_player; worldHistory = i_worldHistory; sequenceNumber = i_sequenceNumber; interruptTimeNS = INFINITE_TIMEOUT; fractionComplete = 0; cumulativeTaskDurationWeight = 0.0; completed = false; } @Override public boolean isTaskComplete() { return completed; } @Override public boolean isTaskAborted() { return aborting && isTaskComplete();} @Override public boolean isTimeToInterrupt() { return (interruptTimeNS == IMMEDIATE_TIMEOUT || (interruptTimeNS != INFINITE_TIMEOUT && System.nanoTime() >= interruptTimeNS)); } @Override public void setTimeOfInterrupt(long timeToStopNS) { interruptTimeNS = timeToStopNS; } @Override public void abortProcessing() { aborting = true; } /** attempt to rollback the changes being made by the current action. * * @param i_rollbackSequenceNumber */ public void rollback(int i_rollbackSequenceNumber) { startRollback = true; rollingBack = true; rollbackSequenceNumber = i_rollbackSequenceNumber; } @Override public double getFractionComplete() { return fractionComplete; } public VoxelSelectionWithOrigin getLockedRegion() {return null;} @Override public UniqueTokenID getUniqueTokenID() { return transactionID; } /** * Set the task to be executed next * @param token the next task * @param taskDurationWeight the estimated relative duration of this task as a fraction of the whole task duration; 0.0 - 1.0; * @param resetCumulativeDuration */ public void setSubTask(AsynchronousToken token, double taskDurationWeight, boolean resetCumulativeDuration) { if (resetCumulativeDuration) { cumulativeTaskDurationWeight = 0; } else { cumulativeTaskDurationWeight += subTaskDurationWeight; } subTaskDurationWeight = taskDurationWeight; subTask = token; } /** execute the current subtask * @return true if subTask is completed */ public boolean executeSubTask() { if (subTask.isTaskComplete()) return true; subTask.setTimeOfInterrupt(interruptTimeNS); subTask.continueProcessing(); double stageCompletion = subTask.isTaskComplete() ? 1.0 : subTask.getFractionComplete(); fractionComplete = cumulativeTaskDurationWeight + subTaskDurationWeight * stageCompletion; // System.out.println("AsynchronousActionBase.executeSubTask stageCompletion " + stageCompletion + " : " + fractionComplete); return subTask.isTaskComplete(); } /** abort the current subTask (keep executing until acknowledged) * @return true if subTask is completed */ public boolean executeAbortSubTask() { if (subTask.isTaskComplete()) return true; subTask.abortProcessing(); subTask.setTimeOfInterrupt(interruptTimeNS); subTask.continueProcessing(); double stageCompletion = subTask.isTaskComplete() ? 1.0 : subTask.getFractionComplete(); fractionComplete = cumulativeTaskDurationWeight + subTaskDurationWeight * stageCompletion; return subTask.isTaskComplete(); } protected boolean completed; protected boolean aborting = false; protected boolean rollingBack = false; protected boolean startRollback = false; protected long interruptTimeNS; protected double fractionComplete; protected WorldServer worldServer; protected WorldHistory worldHistory; protected EntityPlayerMP entityPlayerMP; protected int sequenceNumber; protected int rollbackSequenceNumber; private AsynchronousToken subTask; private double subTaskDurationWeight; private double cumulativeTaskDurationWeight; private final UniqueTokenID transactionID = new UniqueTokenID(); }