package org.ultramine.mods.hawkeye;
import java.util.Iterator;
import org.ultramine.mods.hawkeye.Rollback.RollbackType;
import org.ultramine.mods.hawkeye.database.DataManager;
import org.ultramine.mods.hawkeye.entry.DataEntry;
import org.ultramine.mods.hawkeye.util.HawkUtil;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.server.S23PacketBlockChange;
import net.minecraftforge.common.util.BlockSnapshot;
/**
* Runnable class for reversing a {@link Rollback}. This class should always be
* run in a separate thread to avoid impacting on server performance
*
* @author oliverw92
*/
public class Undo
{
private final PlayerSession session;
private Iterator<DataEntry> undoQueue;
private int counter = 0;
private RollbackType undoType = RollbackType.GLOBAL;
/**
* @param session
* {@link PlayerSession} to retrieve undo results from
*/
public Undo(RollbackType undoType, PlayerSession session)
{
this.undoType = undoType;
this.session = session;
undoQueue = session.getRollbackResults().iterator();
//Check if already rolling back
if(session.doingRollback())
{
HawkUtil.sendMessage(session.getSender(), "&cYour previous rollback is still processing, please wait before performing an undo!");
return;
}
//Check that we actually have results
if(!undoQueue.hasNext())
{
HawkUtil.sendMessage(session.getSender(), "&cNo results found to undo");
return;
}
HawkUtil.debug("Starting undo of " + session.getRollbackResults().size() + " results");
//Start undo
session.setDoingRollback(true);
HawkUtil.sendMessage(session.getSender(), "&cAttempting to undo &7" + session.getRollbackResults().size() + "&c rollback edits");
FMLCommonHandler.instance().bus().register(this);
}
/**
* Run the undo. Contains appropriate methods of catching errors and
* notifying the player
*/
@SubscribeEvent
public void onServerTick(TickEvent.ServerTickEvent e)
{
if(e.phase == TickEvent.Phase.END)
return;
//Start rollback process
int i = 0;
while(i < 200 && undoQueue.hasNext())
{
//If undo doesn't exist
DataEntry entry = undoQueue.next();
if(entry.getUndoState() == null)
continue;
//Global undo
if(undoType == RollbackType.GLOBAL)
{
BlockSnapshot block = entry.getUndoState();
block.world.restoringBlockSnapshots = true;
block.restore(true);
block.world.restoringBlockSnapshots = false;
//Add back into database if delete data is on
if(HawkEye.instance.config.general.deleteDataOnRollback)
DataManager.addEntry(entry);
}
//Player undo
else
{
EntityPlayerMP player = (EntityPlayerMP) session.getSender();
BlockSnapshot block = entry.getUndoState();
S23PacketBlockChange p = new S23PacketBlockChange(block.x, block.y, block.z, block.world);
p.field_148883_d = block.getReplacedBlock();
p.field_148884_e = block.meta;
player.playerNetServerHandler.sendPacket(p);
}
counter++;
}
//Check if undo is finished
if(!undoQueue.hasNext())
{
//End timer
FMLCommonHandler.instance().bus().unregister(this);
session.setDoingRollback(false);
session.setRollbackResults(null);
HawkUtil.sendMessage(session.getSender(), "&cUndo complete, &7" + counter + " &cedits performed");
HawkUtil.debug("Undo complete, " + counter + " edits performed");
}
}
}