mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2025-03-02 11:21:20 +01:00
History on disk rollback command
Useful for undoing specific edits.
This commit is contained in:
parent
652a983907
commit
bf7d066520
@ -24,6 +24,9 @@ commands:
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
|
@ -30,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -315,4 +316,14 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
public String getPlatform() {
|
||||
return "bukkit";
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String name) {
|
||||
return Bukkit.getOfflinePlayer(name).getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
return Bukkit.getOfflinePlayer(uuid).getName();
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ commands:
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.command.FixLighting;
|
||||
import com.boydti.fawe.command.Reload;
|
||||
import com.boydti.fawe.command.Rollback;
|
||||
import com.boydti.fawe.command.Stream;
|
||||
import com.boydti.fawe.command.Wea;
|
||||
import com.boydti.fawe.command.WorldEditRegion;
|
||||
@ -201,6 +202,7 @@ public class Fawe {
|
||||
this.IMP.setupCommand("stream", new Stream());
|
||||
this.IMP.setupCommand("wrg", new WorldEditRegion());
|
||||
this.IMP.setupCommand("fawe", new Reload());
|
||||
this.IMP.setupCommand("frb", new Rollback());
|
||||
}
|
||||
|
||||
public void setupConfigs() {
|
||||
|
@ -10,6 +10,7 @@ import com.sk89q.worldedit.EditSession;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface IFawe {
|
||||
public void debug(final String s);
|
||||
@ -39,4 +40,8 @@ public interface IFawe {
|
||||
public Set<FawePlayer> getPlayers();
|
||||
|
||||
public String getPlatform();
|
||||
|
||||
public UUID getUUID(String name);
|
||||
|
||||
public String getName(UUID uuid);
|
||||
}
|
||||
|
160
core/src/main/java/com/boydti/fawe/command/Rollback.java
Normal file
160
core/src/main/java/com/boydti/fawe/command/Rollback.java
Normal file
@ -0,0 +1,160 @@
|
||||
package com.boydti.fawe.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Rollback extends FaweCommand {
|
||||
|
||||
public Rollback() {
|
||||
super("fawe.rollback");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(final FawePlayer player, final String... args) {
|
||||
if (args.length < 1) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb <info|undo> u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
}
|
||||
World world = player.getWorld();
|
||||
switch (args[0]) {
|
||||
default: {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb info u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
}
|
||||
case "i":
|
||||
case "info": {
|
||||
if (args.length < 2) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb <info|undo> u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
}
|
||||
player.deleteMeta("rollback");
|
||||
final FaweLocation origin = player.getLocation();
|
||||
rollback(player, Arrays.copyOfRange(args, 1, args.length), new RunnableVal<List<DiskStorageHistory>>() {
|
||||
@Override
|
||||
public void run(List<DiskStorageHistory> edits) {
|
||||
long total = 0;
|
||||
player.sendMessage("&d=== Edits ===");
|
||||
for (DiskStorageHistory edit : edits) {
|
||||
int[] headerAndFooter = edit.readHeaderAndFooter(new RegionWrapper(origin.x, origin.x, origin.z, origin.z));
|
||||
RegionWrapper region = new RegionWrapper(headerAndFooter[0], headerAndFooter[2], headerAndFooter[1], headerAndFooter[3]);
|
||||
int dx = region.distanceX(origin.x);
|
||||
int dz = region.distanceZ(origin.z);
|
||||
String name = Fawe.imp().getName(edit.getUUID());
|
||||
long seconds = (System.currentTimeMillis() - edit.getBDFile().lastModified()) / 1000;
|
||||
total += edit.getBDFile().length();
|
||||
player.sendMessage(name + " : " + dx + "," + dz + " : " + MainUtil.secToTime(seconds));
|
||||
}
|
||||
player.sendMessage("&d=============");
|
||||
player.sendMessage("&dSize: " + (((double) (total / 1024)) / 1000) + "MB");
|
||||
player.sendMessage("&dTo rollback: /frb undo");
|
||||
player.sendMessage("&d=============");
|
||||
player.setMeta("rollback", edits);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "undo":
|
||||
case "revert": {
|
||||
final List<DiskStorageHistory> edits = (List<DiskStorageHistory>) player.getMeta("rollback");
|
||||
player.deleteMeta("rollback");
|
||||
if (edits == null) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb info u:<uuid> r:<radius> t:<time>");
|
||||
return false;
|
||||
}
|
||||
final Runnable task = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (edits.size() == 0) {
|
||||
player.sendMessage("&d" + BBC.PREFIX.s() + " Rollback complete!");
|
||||
return;
|
||||
}
|
||||
DiskStorageHistory edit = edits.remove(0);
|
||||
player.sendMessage("&d" + edit.getBDFile());
|
||||
EditSession session = edit.toEditSession(null);
|
||||
session.undo(session);
|
||||
edit.deleteFiles();
|
||||
SetQueue.IMP.addTask(this);
|
||||
}
|
||||
};
|
||||
TaskManager.IMP.async(task);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void rollback(final FawePlayer player, final String[] args, final RunnableVal<List<DiskStorageHistory>> result) {
|
||||
TaskManager.IMP.async(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UUID user = null;
|
||||
int radius = Integer.MAX_VALUE;
|
||||
long time = Long.MAX_VALUE;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String[] split = args[i].split(":");
|
||||
if (split.length != 2) {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb <info|undo> u:<uuid> r:<radius> t:<time>");
|
||||
return;
|
||||
}
|
||||
switch (split[0].toLowerCase()) {
|
||||
case "username":
|
||||
case "user":
|
||||
case "u": {
|
||||
try {
|
||||
if (split[1].length() > 16) {
|
||||
user = UUID.fromString(split[1]);
|
||||
} else {
|
||||
user = Fawe.imp().getUUID(split[1]);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {}
|
||||
if (user == null) {
|
||||
player.sendMessage("&dInvalid user: " + split[1]);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "r":
|
||||
case "radius": {
|
||||
if (!MathMan.isInteger(split[1])) {
|
||||
player.sendMessage("&dInvalid radius: " + split[1]);
|
||||
return;
|
||||
}
|
||||
radius = Integer.parseInt(split[1]);
|
||||
break;
|
||||
}
|
||||
case "t":
|
||||
case "time": {
|
||||
time = MainUtil.timeToSec(split[1]) * 1000;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BBC.COMMAND_SYNTAX.send(player, "/frb <info|undo> u:<uuid> r:<radius> t:<time>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
FaweLocation origin = player.getLocation();
|
||||
List<DiskStorageHistory> edits = MainUtil.getBDFiles(origin, user, radius, time);
|
||||
if (edits.size() == 0) {
|
||||
player.sendMessage("No edits found!");
|
||||
return;
|
||||
}
|
||||
result.run(edits);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.boydti.fawe.command;
|
||||
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
|
||||
public class Undolist extends FaweCommand {
|
||||
|
||||
public Undolist() {
|
||||
super("fawe.undolist");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(final FawePlayer player, final String... args) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
@ -32,6 +35,15 @@ public class FaweLocation {
|
||||
return ((this.x == other.x) && (this.y == other.y) && (this.z == other.z) && (this.world.equals(other.world)));
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
for (World world : WorldEdit.getInstance().getServer().getWorlds()) {
|
||||
if (world.getName().equals(this.world)) {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.x << (8 + this.z) << (4 + this.y);
|
||||
|
@ -15,8 +15,10 @@ import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ -30,7 +32,7 @@ public abstract class FawePlayer<T> {
|
||||
*/
|
||||
private volatile ConcurrentHashMap<String, Object> meta;
|
||||
|
||||
public static <T> FawePlayer<T> wrap(final Object obj) {
|
||||
public static <V> FawePlayer<V> wrap(final Object obj) {
|
||||
return Fawe.imp().wrap(obj);
|
||||
}
|
||||
|
||||
@ -71,7 +73,7 @@ public abstract class FawePlayer<T> {
|
||||
return;
|
||||
}
|
||||
UUID uuid = getUUID();
|
||||
ArrayDeque<Integer> editIds = new ArrayDeque<>();
|
||||
List<Integer> editIds = new ArrayList<>();
|
||||
File folder = new File(Fawe.imp().getDirectory(), "history" + File.separator + world.getName() + File.separator + uuid);
|
||||
if (folder.isDirectory()) {
|
||||
for (File file : folder.listFiles()) {
|
||||
@ -81,6 +83,7 @@ public abstract class FawePlayer<T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(editIds);
|
||||
if (editIds.size() > 0) {
|
||||
Fawe.debug(BBC.PREFIX.s() + " Indexing " + editIds.size() + " history objects for " + getName());
|
||||
for (int index : editIds) {
|
||||
@ -169,20 +172,20 @@ public abstract class FawePlayer<T> {
|
||||
|
||||
/**
|
||||
* Get the metadata for a key.
|
||||
* @param <T>
|
||||
* @param <V>
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> T getMeta(String key) {
|
||||
public <V> V getMeta(String key) {
|
||||
if (this.meta != null) {
|
||||
return (T) this.meta.get(key);
|
||||
return (V) this.meta.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getMeta(String key, T def) {
|
||||
public <V> V getMeta(String key, V def) {
|
||||
if (this.meta != null) {
|
||||
T value = (T) this.meta.get(key);
|
||||
V value = (V) this.meta.get(key);
|
||||
return value == null ? def : value;
|
||||
}
|
||||
return def;
|
||||
|
@ -26,6 +26,45 @@ public class RegionWrapper {
|
||||
return ((x >= this.minX) && (x <= this.maxX) && (z >= this.minZ) && (z <= this.maxZ));
|
||||
}
|
||||
|
||||
public int distanceX(int x) {
|
||||
if (x >= minX) {
|
||||
if (x <= maxX) {
|
||||
return 0;
|
||||
}
|
||||
return maxX - x;
|
||||
}
|
||||
return minX - x;
|
||||
}
|
||||
|
||||
public int distanceZ(int z) {
|
||||
if (z >= minZ) {
|
||||
if (z <= maxZ) {
|
||||
return 0;
|
||||
}
|
||||
return maxZ - z;
|
||||
}
|
||||
return minZ - z;
|
||||
}
|
||||
|
||||
public int distance(int x, int z) {
|
||||
if (isIn(x, z)) {
|
||||
return 0;
|
||||
}
|
||||
int dx1 = Math.abs(x - minX);
|
||||
int dx2 = Math.abs(x - maxX);
|
||||
int dz1 = Math.abs(z - minZ);
|
||||
int dz2 = Math.abs(z - maxZ);
|
||||
if (x >= minX && x <= maxX) {
|
||||
return Math.min(dz1, dz2);
|
||||
} else if (z >= minZ && z <= maxZ) {
|
||||
return Math.min(dx1, dx2);
|
||||
} else {
|
||||
int dx = Math.min(dx1, dx2);
|
||||
int dz = Math.min(dz1, dz2);
|
||||
return (int) Math.sqrt(dx * dx + dz * dz);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.minX + "," + this.minZ + "->" + this.maxX + "," + this.maxZ;
|
||||
|
@ -4,6 +4,8 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -51,7 +53,8 @@ import net.jpountz.lz4.LZ4OutputStream;
|
||||
* - Slow
|
||||
*/
|
||||
public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
|
||||
|
||||
private UUID uuid;
|
||||
private File bdFile;
|
||||
private File nbtfFile;
|
||||
private File nbttFile;
|
||||
@ -95,6 +98,14 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
private AtomicInteger size = new AtomicInteger();
|
||||
private World world;
|
||||
|
||||
public void deleteFiles() {
|
||||
bdFile.delete();
|
||||
nbtfFile.delete();
|
||||
nbttFile.delete();
|
||||
entfFile.delete();
|
||||
enttFile.delete();
|
||||
}
|
||||
|
||||
public DiskStorageHistory(World world, UUID uuid) {
|
||||
size = new AtomicInteger();
|
||||
String base = "history" + File.separator + world.getName() + File.separator + uuid;
|
||||
@ -119,6 +130,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
}
|
||||
|
||||
public void init(World world, UUID uuid, int i) {
|
||||
this.uuid = uuid;
|
||||
this.world = world;
|
||||
String base = "history" + File.separator + world.getName() + File.separator + uuid;
|
||||
base += File.separator + i;
|
||||
@ -129,6 +141,14 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
bdFile = new File(Fawe.imp().getDirectory(), base + ".bd");
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public File getBDFile() {
|
||||
return bdFile;
|
||||
}
|
||||
|
||||
public EditSession toEditSession(Player player) {
|
||||
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
||||
EditSession edit = factory.getEditSession(world, -1, null, player);
|
||||
@ -335,6 +355,82 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
return osENTT;
|
||||
}
|
||||
|
||||
int fx;
|
||||
int fz;
|
||||
|
||||
public int[] readHeaderAndFooter(RegionWrapper requiredRegion) {
|
||||
if (fx == 0 && fz == 0 && bdFile.exists()) {
|
||||
if ((ox != 0 || oz != 0) && !requiredRegion.isIn(ox, oz)) {
|
||||
return new int[] {ox, oz, ox, oz};
|
||||
}
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(bdFile);
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
LZ4Compressor compressor = factory.fastCompressor();
|
||||
final InputStream gis;
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
gis = new LZ4InputStream(new LZ4InputStream(fis));
|
||||
} else {
|
||||
gis = new LZ4InputStream(fis);
|
||||
}
|
||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
if (!requiredRegion.isIn(ox, oz)) {
|
||||
fis.close();
|
||||
gis.close();
|
||||
return new int[] {ox, oz, ox, oz};
|
||||
}
|
||||
byte[] even = new byte[9];
|
||||
byte[] odd = new byte[9];
|
||||
byte[] result = null;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
if ((i++ & 1) == 0) {
|
||||
if (gis.read(even) == -1) {
|
||||
result = odd;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (gis.read(odd) == -1) {
|
||||
result = even;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fx = ((byte) result[0] & 0xFF) + ((byte) result[1] << 8) + ox;
|
||||
fz = ((byte) result[2] & 0xFF) + ((byte) result[3] << 8) + oz;
|
||||
fis.close();
|
||||
gis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new int[] {ox, oz, fx, fz};
|
||||
}
|
||||
|
||||
public IntegerPair readHeader() {
|
||||
if (ox == 0 && oz == 0 && bdFile.exists()) {
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(bdFile);
|
||||
LZ4Factory factory = LZ4Factory.fastestInstance();
|
||||
LZ4Compressor compressor = factory.fastCompressor();
|
||||
final InputStream gis;
|
||||
if (Settings.COMPRESSION_LEVEL > 0) {
|
||||
gis = new LZ4InputStream(new LZ4InputStream(fis));
|
||||
} else {
|
||||
gis = new LZ4InputStream(fis);
|
||||
}
|
||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||
fis.close();
|
||||
gis.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new IntegerPair(ox, oz);
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public Iterator<Change> getIterator(final boolean dir) {
|
||||
flush();
|
||||
|
@ -2,15 +2,24 @@ package com.boydti.fawe.util;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.EndTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MainUtil {
|
||||
/*
|
||||
@ -50,6 +59,136 @@ public class MainUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static String secToTime(long time) {
|
||||
StringBuilder toreturn = new StringBuilder();
|
||||
if (time>=33868800) {
|
||||
int years = (int) (time/33868800);
|
||||
time-=years*33868800;
|
||||
toreturn.append(years+"y ");
|
||||
}
|
||||
if (time>=604800) {
|
||||
int weeks = (int) (time/604800);
|
||||
time-=weeks*604800;
|
||||
toreturn.append(weeks+"w ");
|
||||
}
|
||||
if (time>=86400) {
|
||||
int days = (int) (time/86400);
|
||||
time-=days*86400;
|
||||
toreturn.append(days+"d ");
|
||||
}
|
||||
if (time>=3600) {
|
||||
int hours = (int) (time/3600);
|
||||
time-=hours*3600;
|
||||
toreturn.append(hours+"h ");
|
||||
}
|
||||
if (time>=60) {
|
||||
int minutes = (int) (time/60);
|
||||
time-=minutes*60;
|
||||
toreturn.append(minutes+"m ");
|
||||
}
|
||||
if (toreturn.equals("")||time>0){
|
||||
toreturn.append((time)+"s ");
|
||||
}
|
||||
return toreturn.toString().trim();
|
||||
}
|
||||
|
||||
public static long timeToSec(String string) {
|
||||
if (MathMan.isInteger(string)) {
|
||||
return Long.parseLong(string);
|
||||
}
|
||||
string = string.toLowerCase().trim().toLowerCase();
|
||||
if (string.equalsIgnoreCase("false")) {
|
||||
return 0;
|
||||
}
|
||||
String[] split = string.split(" ");
|
||||
long time = 0;
|
||||
for (String value : split) {
|
||||
int nums = Integer.parseInt(value.replaceAll("[^\\d]", ""));
|
||||
String letters = value.replaceAll("[^a-z]", "");
|
||||
switch (letters) {
|
||||
case "week":
|
||||
case "weeks":
|
||||
case "wks":
|
||||
case "w":
|
||||
|
||||
time += 604800 * nums;
|
||||
case "days":
|
||||
case "day":
|
||||
case "d":
|
||||
time += 86400 * nums;
|
||||
case "hour":
|
||||
case "hr":
|
||||
case "hrs":
|
||||
case "hours":
|
||||
case "h":
|
||||
time += 3600 * nums;
|
||||
case "minutes":
|
||||
case "minute":
|
||||
case "mins":
|
||||
case "min":
|
||||
case "m":
|
||||
time += 60 * nums;
|
||||
case "seconds":
|
||||
case "second":
|
||||
case "secs":
|
||||
case "sec":
|
||||
case "s":
|
||||
time += nums;
|
||||
}
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
public static List<DiskStorageHistory> getBDFiles(FaweLocation origin, UUID user, int radius, long timediff) {
|
||||
File history = new File(Fawe.imp().getDirectory(), "history" + File.separator + origin.world);
|
||||
if (!history.exists()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
for (File userFile : history.listFiles()) {
|
||||
if (!userFile.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
UUID userUUID;
|
||||
try {
|
||||
userUUID = UUID.fromString(userFile.getName());
|
||||
} catch (IllegalArgumentException e) {
|
||||
continue;
|
||||
}
|
||||
if (user != null && !userUUID.equals(user)) {
|
||||
continue;
|
||||
}
|
||||
ArrayList<Integer> ids = new ArrayList<>();
|
||||
for (File file : userFile.listFiles()) {
|
||||
if (file.getName().endsWith(".bd")) {
|
||||
if (timediff > Integer.MAX_VALUE || now - file.lastModified() <= timediff) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
World world = origin.getWorld();
|
||||
Collections.sort(files, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File a, File b) {
|
||||
long value = a.lastModified() - b.lastModified();
|
||||
return value == 0 ? 0 : value < 0 ? 1 : -1;
|
||||
}
|
||||
});
|
||||
ArrayList<DiskStorageHistory> result = new ArrayList<>();
|
||||
for (File file : files) {
|
||||
UUID uuid = UUID.fromString(file.getParentFile().getName());
|
||||
DiskStorageHistory dsh = new DiskStorageHistory(world, uuid, Integer.parseInt(file.getName().split("\\.")[0]));
|
||||
int[] headerAndFooter = dsh.readHeaderAndFooter(new RegionWrapper(origin.x - 512, origin.x + 512, origin.z - 512, origin.z + 512));
|
||||
RegionWrapper region = new RegionWrapper(headerAndFooter[0], headerAndFooter[2], headerAndFooter[1], headerAndFooter[3]);
|
||||
if (region.distance(origin.x, origin.z) <= radius) {
|
||||
result.add(dsh);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void deleteOlder(File directory, final long timeDiff) {
|
||||
final long now = System.currentTimeMillis();
|
||||
iterateFiles(directory, new RunnableVal<File>() {
|
||||
|
194
core/src/main/java/com/boydti/fawe/util/MathMan.java
Normal file
194
core/src/main/java/com/boydti/fawe/util/MathMan.java
Normal file
@ -0,0 +1,194 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
public class MathMan {
|
||||
|
||||
private static final int ATAN2_BITS = 7;
|
||||
private static final int ATAN2_BITS2 = ATAN2_BITS << 1;
|
||||
private static final int ATAN2_MASK = ~(-1 << ATAN2_BITS2);
|
||||
private static final int ATAN2_COUNT = ATAN2_MASK + 1;
|
||||
private static final int ATAN2_DIM = (int) Math.sqrt(ATAN2_COUNT);
|
||||
private static final float INV_ATAN2_DIM_MINUS_1 = 1.0f / (ATAN2_DIM - 1);
|
||||
private static final float[] atan2 = new float[ATAN2_COUNT];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < ATAN2_DIM; i++) {
|
||||
for (int j = 0; j < ATAN2_DIM; j++) {
|
||||
float x0 = (float) i / ATAN2_DIM;
|
||||
float y0 = (float) j / ATAN2_DIM;
|
||||
|
||||
atan2[(j * ATAN2_DIM) + i] = (float) Math.atan2(y0, x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static double getMean(int[] array) {
|
||||
double count = 0;
|
||||
for (int i : array) {
|
||||
count += i;
|
||||
}
|
||||
return count / array.length;
|
||||
}
|
||||
|
||||
public static double getMean(double[] array) {
|
||||
double count = 0;
|
||||
for (double i : array) {
|
||||
count += i;
|
||||
}
|
||||
return count / array.length;
|
||||
}
|
||||
|
||||
public static int pair(short x, short y) {
|
||||
return (x << 16) | (y & 0xFFFF);
|
||||
}
|
||||
|
||||
public static short unpairX(int hash) {
|
||||
return (short) (hash >> 16);
|
||||
}
|
||||
|
||||
public static short unpairY(int hash) {
|
||||
return (short) (hash & 0xFFFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [x, y, z]
|
||||
* @param yaw
|
||||
* @param pitch
|
||||
* @return
|
||||
*/
|
||||
public static float[] getDirection(float yaw, float pitch) {
|
||||
double pitch_sin = Math.sin(pitch);
|
||||
return new float[]{(float) (pitch_sin * Math.cos(yaw)), (float) (pitch_sin * Math.sin(yaw)), (float) Math.cos(pitch)};
|
||||
}
|
||||
|
||||
public static int roundInt(double value) {
|
||||
return (int) (value < 0 ? (value == (int) value) ? value : value - 1 : value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [ pitch, yaw ]
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public static float[] getPitchAndYaw(float x, float y, float z) {
|
||||
float distance = sqrtApprox((z * z) + (x * x));
|
||||
return new float[]{atan2(y, distance), atan2(x, z)};
|
||||
}
|
||||
|
||||
public static final float atan2(float y, float x) {
|
||||
float add, mul;
|
||||
|
||||
if (x < 0.0f) {
|
||||
if (y < 0.0f) {
|
||||
x = -x;
|
||||
y = -y;
|
||||
|
||||
mul = 1.0f;
|
||||
} else {
|
||||
x = -x;
|
||||
mul = -1.0f;
|
||||
}
|
||||
|
||||
add = -3.141592653f;
|
||||
} else {
|
||||
if (y < 0.0f) {
|
||||
y = -y;
|
||||
mul = -1.0f;
|
||||
} else {
|
||||
mul = 1.0f;
|
||||
}
|
||||
|
||||
add = 0.0f;
|
||||
}
|
||||
|
||||
float invDiv = 1.0f / (((x < y) ? y : x) * INV_ATAN2_DIM_MINUS_1);
|
||||
|
||||
int xi = (int) (x * invDiv);
|
||||
int yi = (int) (y * invDiv);
|
||||
|
||||
return (atan2[(yi * ATAN2_DIM) + xi] + add) * mul;
|
||||
}
|
||||
|
||||
public static float sqrtApprox(float f) {
|
||||
return f * Float.intBitsToFloat(0x5f375a86 - (Float.floatToIntBits(f) >> 1));
|
||||
}
|
||||
|
||||
public static double sqrtApprox(double d) {
|
||||
return Double.longBitsToDouble(((Double.doubleToLongBits(d) - (1l << 52)) >> 1) + (1l << 61));
|
||||
}
|
||||
|
||||
public static float invSqrt(float x) {
|
||||
float xhalf = 0.5f * x;
|
||||
int i = Float.floatToIntBits(x);
|
||||
i = 0x5f3759df - (i >> 1);
|
||||
x = Float.intBitsToFloat(i);
|
||||
x = x * (1.5f - (xhalf * x * x));
|
||||
return x;
|
||||
}
|
||||
|
||||
public static int getPositiveId(int i) {
|
||||
if (i < 0) {
|
||||
return (-i * 2) - 1;
|
||||
}
|
||||
return i * 2;
|
||||
}
|
||||
|
||||
public static boolean isInteger(String str) {
|
||||
if (str == null) {
|
||||
return false;
|
||||
}
|
||||
int length = str.length();
|
||||
if (length == 0) {
|
||||
return false;
|
||||
}
|
||||
int i = 0;
|
||||
if (str.charAt(0) == '-') {
|
||||
if (length == 1) {
|
||||
return false;
|
||||
}
|
||||
i = 1;
|
||||
}
|
||||
for (; i < length; i++) {
|
||||
char c = str.charAt(i);
|
||||
if ((c <= '/') || (c >= ':')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static double getSD(double[] array, double av) {
|
||||
double sd = 0;
|
||||
for (double element : array) {
|
||||
sd += Math.pow(Math.abs(element - av), 2);
|
||||
}
|
||||
return Math.sqrt(sd / array.length);
|
||||
}
|
||||
|
||||
public static double getSD(int[] array, double av) {
|
||||
double sd = 0;
|
||||
for (int element : array) {
|
||||
sd += Math.pow(Math.abs(element - av), 2);
|
||||
}
|
||||
return Math.sqrt(sd / array.length);
|
||||
}
|
||||
|
||||
public static int mod(int x, int y) {
|
||||
if (isPowerOfTwo(y)) {
|
||||
return x & (y - 1);
|
||||
}
|
||||
return x % y;
|
||||
}
|
||||
|
||||
public static int unsignedmod(int x, int y) {
|
||||
if (isPowerOfTwo(y)) {
|
||||
return x & (y - 1);
|
||||
}
|
||||
return x % y;
|
||||
}
|
||||
|
||||
public static boolean isPowerOfTwo(int x) {
|
||||
return (x & (x - 1)) == 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user