package com.forgeessentials.playerlogger.command;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimerTask;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.network.play.server.S23PacketBlockChange;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
import com.forgeessentials.commons.selections.Selection;
import com.forgeessentials.playerlogger.ModulePlayerLogger;
import com.forgeessentials.playerlogger.entity.ActionBlock;
import com.forgeessentials.playerlogger.entity.ActionBlock.ActionBlockType;
import com.google.common.collect.Lists;
import cpw.mods.fml.common.registry.GameData;
public class RollbackInfo
{
EntityPlayerMP player;
private Selection area;
private Date time;
List<ActionBlock> changes;
private int timeStep = -60;
public PlaybackTask task;
public RollbackInfo(EntityPlayerMP player, Selection area)
{
this.player = player;
this.area = area;
this.setTime(new Date());
}
@SuppressWarnings("deprecation")
public void stepBackward()
{
timeStep *= timeStep < 0 ? 1.25 : -0.25;
timeStep -= 1;
getTime().setSeconds(getTime().getSeconds() + timeStep);
}
@SuppressWarnings("deprecation")
public void stepForward()
{
timeStep *= timeStep > 0 ? 1.25 : -0.25;
timeStep += 1;
getTime().setSeconds(getTime().getSeconds() + timeStep);
}
public void previewChanges()
{
List<ActionBlock> lastChanges = changes;
if (lastChanges == null)
lastChanges = new ArrayList<>();
changes = ModulePlayerLogger.getLogger().getBlockChanges(area, getTime());
if (lastChanges.size() < changes.size())
{
for (int i = lastChanges.size(); i < changes.size(); i++)
{
ActionBlock change = changes.get(i);
if (change.type == ActionBlockType.PLACE)
{
sendBlockChange(player, change, Blocks.air, 0);
// System.out.println(FEConfig.FORMAT_DATE_TIME_SECONDS.format(change.time) + " REMOVED " +
// change.block.name);
}
else if (change.type == ActionBlockType.BREAK || change.type == ActionBlockType.DETONATE)
{
sendBlockChange(player, change, GameData.getBlockRegistry().getObject(change.block.name), change.metadata);
// System.out.println(FEConfig.FORMAT_DATE_TIME_SECONDS.format(change.time) + " RESTORED " +
// change.block.name + ":" + change.metadata);
}
}
}
else if (lastChanges.size() > changes.size())
{
for (int i = lastChanges.size() - 1; i >= changes.size(); i--)
{
ActionBlock change = lastChanges.get(i);
if (change.type == ActionBlockType.PLACE)
{
sendBlockChange(player, change, GameData.getBlockRegistry().getObject(change.block.name), change.metadata);
// System.out.println(FEConfig.FORMAT_DATE_TIME_SECONDS.format(change.time) + " REPLACED " +
// change.block.name);
}
else if (change.type == ActionBlockType.BREAK || change.type == ActionBlockType.DETONATE)
{
sendBlockChange(player, change, Blocks.air, 0);
// System.out.println(FEConfig.FORMAT_DATE_TIME_SECONDS.format(change.time) + " REBROKE " +
// change.block.name + ":" + change.metadata);
}
}
}
}
public void confirm()
{
if (task != null)
task.cancel();
for (ActionBlock change : changes)
{
if (change.type == ActionBlockType.PLACE)
{
WorldServer world = DimensionManager.getWorld(change.world.id);
world.setBlockToAir(change.x, change.y, change.z);
System.out.println(change.time + " REMOVED " + change.block.name);
}
else if (change.type == ActionBlockType.BREAK || change.type == ActionBlockType.DETONATE)
{
WorldServer world = DimensionManager.getWorld(change.world.id);
world.setBlock(change.x, change.y, change.z, GameData.getBlockRegistry().getObject(change.block.name), change.metadata, 3);
System.out.println(change.time + " RESTORED " + change.block.name + ":" + change.metadata);
}
}
}
public void cancel()
{
if (task != null)
task.cancel();
for (ActionBlock change : Lists.reverse(changes))
player.playerNetServerHandler.sendPacket(new S23PacketBlockChange(change.x, change.y, change.z, DimensionManager.getWorld(change.world.id)));
}
public Date getTime()
{
return time;
}
public void setTime(Date time)
{
this.time = time;
}
/**
* Send a faked block-update to a player
*
* @param player
* @param change
* @param newBlock
* @param newMeta
*/
public static void sendBlockChange(EntityPlayerMP player, ActionBlock change, Block newBlock, int newMeta)
{
S23PacketBlockChange packet = new S23PacketBlockChange(change.x, change.y, change.z, DimensionManager.getWorld(change.world.id));
packet.field_148883_d = newBlock;
packet.field_148884_e = newMeta;
player.playerNetServerHandler.sendPacket(packet);
}
public static class PlaybackTask extends TimerTask
{
private RollbackInfo rb;
private int speed;
public PlaybackTask(RollbackInfo rb, int speed)
{
this.rb = rb;
this.speed = speed;
}
@Override
@SuppressWarnings("deprecation")
public void run()
{
rb.getTime().setSeconds(rb.getTime().getSeconds() - speed);
rb.previewChanges();
}
}
}