mirror of
https://github.com/TheDeus-Group/TFM-4.3-Reloaded.git
synced 2024-05-15 22:31:17 +00:00
317 lines
8.8 KiB
Java
317 lines
8.8 KiB
Java
package me.StevenLawson.TotalFreedomMod.world;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.ListIterator;
|
|
import java.util.Map;
|
|
|
|
import me.StevenLawson.TotalFreedomMod.Log;
|
|
import me.StevenLawson.TotalFreedomMod.TotalFreedomMod;
|
|
import me.StevenLawson.TotalFreedomMod.util.DeprecationUtil;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
|
|
public class RollbackManager
|
|
{
|
|
private static final Map<String, List<RollbackEntry>> PLAYER_HISTORY = new HashMap<String, List<RollbackEntry>>();
|
|
private static final List<String> REMOVE_ROLLBACK_HISTORY = new ArrayList<String>();
|
|
|
|
private RollbackManager()
|
|
{
|
|
throw new AssertionError();
|
|
}
|
|
|
|
public static void blockPlace(org.bukkit.event.block.BlockPlaceEvent event)
|
|
{
|
|
storeEntry(event.getPlayer(), new RollbackEntry(event.getPlayer().getName(), event.getBlock(), EntryType.BLOCK_PLACE));
|
|
}
|
|
|
|
public static void blockBreak(org.bukkit.event.block.BlockBreakEvent event)
|
|
{
|
|
storeEntry(event.getPlayer(), new RollbackEntry(event.getPlayer().getName(), event.getBlock(), EntryType.BLOCK_BREAK));
|
|
}
|
|
|
|
private static void storeEntry(Player player, RollbackEntry entry)
|
|
{
|
|
List<RollbackEntry> playerEntryList = getEntriesByPlayer(player.getName());
|
|
|
|
if (playerEntryList != null)
|
|
{
|
|
playerEntryList.add(0, entry);
|
|
}
|
|
}
|
|
|
|
// May return null
|
|
public static String findPlayer(String partial)
|
|
{
|
|
partial = partial.toLowerCase();
|
|
|
|
for (String player : PLAYER_HISTORY.keySet())
|
|
{
|
|
if (player.toLowerCase().equals(partial))
|
|
{
|
|
return player;
|
|
}
|
|
}
|
|
|
|
for (String player : PLAYER_HISTORY.keySet())
|
|
{
|
|
if (player.toLowerCase().contains(partial))
|
|
{
|
|
return player;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static int purgeEntries()
|
|
{
|
|
Iterator<List<RollbackEntry>> it = PLAYER_HISTORY.values().iterator();
|
|
while (it.hasNext())
|
|
{
|
|
List<RollbackEntry> playerEntryList = it.next();
|
|
if (playerEntryList != null)
|
|
{
|
|
playerEntryList.clear();
|
|
}
|
|
}
|
|
return PLAYER_HISTORY.size();
|
|
}
|
|
|
|
public static int purgeEntries(String playerName)
|
|
{
|
|
List<RollbackEntry> playerEntryList = getEntriesByPlayer(playerName);
|
|
|
|
if (playerEntryList == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int count = playerEntryList.size();
|
|
playerEntryList.clear();
|
|
return count;
|
|
|
|
}
|
|
|
|
public static boolean canRollback(String playerName)
|
|
{
|
|
return PLAYER_HISTORY.containsKey(playerName.toLowerCase()) && !PLAYER_HISTORY.get(playerName.toLowerCase()).isEmpty();
|
|
}
|
|
|
|
public static boolean canUndoRollback(String playerName)
|
|
{
|
|
return REMOVE_ROLLBACK_HISTORY.contains(playerName.toLowerCase());
|
|
}
|
|
|
|
public static int rollback(final String playerName)
|
|
{
|
|
final List<RollbackEntry> entries = getEntriesByPlayer(playerName);
|
|
if (entries == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int count = entries.size();
|
|
for (RollbackEntry entry : entries)
|
|
{
|
|
if (entry != null)
|
|
{
|
|
entry.restore();
|
|
}
|
|
}
|
|
|
|
if (!REMOVE_ROLLBACK_HISTORY.contains(playerName.toLowerCase()))
|
|
{
|
|
REMOVE_ROLLBACK_HISTORY.add(playerName.toLowerCase());
|
|
}
|
|
|
|
new BukkitRunnable()
|
|
{
|
|
@Override
|
|
public void run()
|
|
{
|
|
if (REMOVE_ROLLBACK_HISTORY.contains(playerName.toLowerCase()))
|
|
{
|
|
REMOVE_ROLLBACK_HISTORY.remove(playerName.toLowerCase());
|
|
purgeEntries(playerName);
|
|
}
|
|
}
|
|
}.runTaskLater(TotalFreedomMod.plugin, 40L * 20L);
|
|
return count;
|
|
}
|
|
|
|
public static int undoRollback(String playerName)
|
|
{
|
|
final List<RollbackEntry> entries = getEntriesByPlayer(playerName);
|
|
|
|
if (entries == null)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
final int count = entries.size();
|
|
|
|
final ListIterator<RollbackEntry> it = entries.listIterator(count);
|
|
while (it.hasPrevious())
|
|
{
|
|
RollbackEntry entry = it.previous();
|
|
if (entry != null)
|
|
{
|
|
entry.redo();
|
|
}
|
|
}
|
|
|
|
REMOVE_ROLLBACK_HISTORY.remove(playerName.toLowerCase());
|
|
|
|
return count;
|
|
}
|
|
|
|
public static List<RollbackEntry> getEntriesAtLocation(final Location location)
|
|
{
|
|
final int testX = location.getBlockX();
|
|
final short testY = (short) location.getBlockY();
|
|
final int testZ = location.getBlockZ();
|
|
final String testWorldName = location.getWorld().getName();
|
|
|
|
List<RollbackEntry> entries = new ArrayList<RollbackEntry>();
|
|
for (String playername : PLAYER_HISTORY.keySet())
|
|
{
|
|
for (RollbackEntry entry : PLAYER_HISTORY.get(playername.toLowerCase()))
|
|
{
|
|
if (testX == entry.x && testY == entry.y && testZ == entry.z && testWorldName.equals(entry.worldName))
|
|
{
|
|
entries.add(0, entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
|
|
private static List<RollbackEntry> getEntriesByPlayer(String playerName)
|
|
{
|
|
playerName = playerName.toLowerCase();
|
|
List<RollbackEntry> playerEntryList = PLAYER_HISTORY.get(playerName.toLowerCase());
|
|
if (playerEntryList == null)
|
|
{
|
|
playerEntryList = new ArrayList<RollbackEntry>();
|
|
PLAYER_HISTORY.put(playerName.toLowerCase(), playerEntryList);
|
|
}
|
|
return playerEntryList;
|
|
}
|
|
|
|
public enum EntryType
|
|
{
|
|
BLOCK_PLACE("placed"),
|
|
BLOCK_BREAK("broke");
|
|
private final String action;
|
|
|
|
EntryType(String action)
|
|
{
|
|
this.action = action;
|
|
}
|
|
|
|
@Override
|
|
public String toString()
|
|
{
|
|
return this.action;
|
|
}
|
|
}
|
|
|
|
public static class RollbackEntry
|
|
{
|
|
// Use of primitives to decrease overhead
|
|
public final String author;
|
|
public final String worldName;
|
|
public final int x;
|
|
public final short y;
|
|
public final int z;
|
|
public final byte data;
|
|
public final Material blockMaterial;
|
|
private final boolean isBreak;
|
|
|
|
private RollbackEntry(String author, Block block, EntryType entryType)
|
|
{
|
|
final Location location = block.getLocation();
|
|
|
|
this.x = location.getBlockX();
|
|
this.y = (short) location.getBlockY();
|
|
this.z = location.getBlockZ();
|
|
this.worldName = location.getWorld().getName();
|
|
this.author = author;
|
|
|
|
if (entryType == EntryType.BLOCK_BREAK)
|
|
{
|
|
this.blockMaterial = block.getType();
|
|
this.data = DeprecationUtil.getData_Block(block);
|
|
this.isBreak = true;
|
|
}
|
|
else
|
|
{
|
|
this.blockMaterial = block.getType();
|
|
this.data = DeprecationUtil.getData_Block(block);
|
|
this.isBreak = false;
|
|
}
|
|
}
|
|
|
|
public Location getLocation()
|
|
{
|
|
try
|
|
{
|
|
return new Location(Bukkit.getWorld(worldName), x, (int) y, z);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.warning("Could not get location of rollback entry at (" + worldName + ":" + x + "," + y + "," + x + ")!");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public Material getMaterial()
|
|
{
|
|
return blockMaterial;
|
|
}
|
|
|
|
public EntryType getType()
|
|
{
|
|
return (isBreak ? EntryType.BLOCK_BREAK : EntryType.BLOCK_PLACE);
|
|
}
|
|
|
|
public void restore()
|
|
{
|
|
final Block block = Bukkit.getWorld(worldName).getBlockAt(x, y, z);
|
|
if (isBreak)
|
|
{
|
|
block.setType(getMaterial());
|
|
DeprecationUtil.setData_Block(block, data);
|
|
}
|
|
else
|
|
{
|
|
block.setType(Material.AIR);
|
|
}
|
|
}
|
|
|
|
public void redo()
|
|
{
|
|
final Block block = Bukkit.getWorld(worldName).getBlockAt(x, y, z);
|
|
|
|
if (isBreak)
|
|
{
|
|
block.setType(Material.AIR);
|
|
}
|
|
else
|
|
{
|
|
block.setType(getMaterial());
|
|
DeprecationUtil.setData_Block(block, data);
|
|
}
|
|
}
|
|
}
|
|
}
|