mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-24 19:46:34 +01:00
Finish with sponge depend
Also fix 1.8 issue for kh498
This commit is contained in:
parent
fb8863cd06
commit
789098dc79
@ -10,7 +10,7 @@ buildscript {
|
||||
}
|
||||
|
||||
group = 'com.boydti.fawe'
|
||||
version = '3.3.4'
|
||||
version = '3.3.5'
|
||||
description = """FastAsyncWorldEdit"""
|
||||
|
||||
subprojects {
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.FaweBukkit
|
||||
version: 3.3.4
|
||||
version: 3.3.5
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
|
@ -28,13 +28,18 @@ import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
|
||||
private VaultUtil vault;
|
||||
private WorldEditPlugin worldedit;
|
||||
@ -53,6 +58,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
@Override
|
||||
public void onEnable() {
|
||||
try {
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
Fawe.set(this);
|
||||
try {
|
||||
final Class<?> clazz = Class.forName("org.spigotmc.AsyncCatcher");
|
||||
@ -85,9 +91,16 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
@Override
|
||||
public FawePlayer<Player> wrap(final Object obj) {
|
||||
if (obj.getClass() == String.class) {
|
||||
return new BukkitPlayer(Bukkit.getPlayer((String) obj));
|
||||
String name = (String) obj;
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(name);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
return new BukkitPlayer(Bukkit.getPlayer(name));
|
||||
} else if (obj instanceof Player) {
|
||||
return new BukkitPlayer((Player) obj);
|
||||
Player player = (Player) obj;
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new BukkitPlayer(player);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -100,6 +113,15 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
debug("&6Metrics enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FawePlayer> getPlayers() {
|
||||
HashSet<FawePlayer> players = new HashSet<>();
|
||||
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
|
||||
players.add(wrap(player));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kinda a really messy class I just copied over from an old project<br>
|
||||
* - Still works, so cbf cleaning it up<br>
|
||||
@ -300,4 +322,9 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
|
||||
}
|
||||
return managers;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Fawe.get().unregister(event.getPlayer().getName());
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package com.boydti.fawe.logging;
|
||||
|
||||
import org.PrimeSoft.blocksHub.BlocksHub;
|
||||
import org.PrimeSoft.blocksHub.IBlocksHubApi;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
package com.boydti.fawe.bukkit.logging;
|
||||
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import org.PrimeSoft.blocksHub.BlocksHub;
|
||||
import org.PrimeSoft.blocksHub.IBlocksHubApi;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class BlocksHubHook {
|
||||
private final BlocksHub hub;
|
@ -1,15 +1,4 @@
|
||||
package com.boydti.fawe.logging;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.PrimeSoft.blocksHub.IBlocksHubApi;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
package com.boydti.fawe.bukkit.logging;
|
||||
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@ -25,9 +14,18 @@ import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
import org.PrimeSoft.blocksHub.IBlocksHubApi;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Stores changes to a {@link ChangeSet}.
|
||||
* Stores changes to a {@link com.sk89q.worldedit.history.changeset.ChangeSet}.
|
||||
* Logs changes to BlocksHub
|
||||
*/
|
||||
public class LoggingExtent extends AbstractDelegateExtent {
|
@ -1,11 +1,11 @@
|
||||
package com.boydti.fawe.bukkit.v0;
|
||||
|
||||
import com.boydti.fawe.logging.BlocksHubHook;
|
||||
import com.boydti.fawe.bukkit.logging.BlocksHubHook;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
|
||||
public class BukkitEditSessionWrapper_0 extends EditSessionWrapper {
|
||||
|
||||
@ -20,7 +20,7 @@ public class BukkitEditSessionWrapper_0 extends EditSessionWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent getHistoryExtent(final Extent parent, final ChangeSet set, final FawePlayer<?> player) {
|
||||
public Extent getHistoryExtent(final Extent parent, final FaweChangeSet set, final FawePlayer<?> player) {
|
||||
if (this.hook != null) {
|
||||
// If we are doing logging, return a custom logging extent
|
||||
return this.hook.getLoggingExtent(parent, set, player);
|
||||
|
@ -1,31 +1,5 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
import static com.boydti.fawe.util.ReflectionUtils.getRefClass;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
@ -40,11 +14,36 @@ import com.boydti.fawe.util.ReflectionUtils.RefConstructor;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefField;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefMethod;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefMethod.RefExecutor;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.World.Environment;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
|
||||
import static com.boydti.fawe.util.ReflectionUtils.getRefClass;
|
||||
|
||||
public class BukkitQueue_1_8 extends BukkitQueue_0 {
|
||||
|
||||
@ -116,61 +115,36 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
|
||||
final HashMap<FaweChunk<Chunk>, Object> packets = new HashMap<>();
|
||||
final HashMap<String, ArrayList<FaweChunk<Chunk>>> map = new HashMap<>();
|
||||
|
||||
for (final FaweChunk<Chunk> fc : fcs) {
|
||||
final String world = fc.getChunkLoc().world;
|
||||
ArrayList<FaweChunk<Chunk>> list = map.get(world);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
map.put(world, list);
|
||||
sendChunk(fc);
|
||||
}
|
||||
list.add(fc);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
Chunk chunk = fc.getChunk();
|
||||
World world = chunk.getWorld();
|
||||
final int view = Bukkit.getServer().getViewDistance();
|
||||
int cx = chunk.getX();
|
||||
int cz = chunk.getZ();
|
||||
for (final Player player : Bukkit.getOnlinePlayers()) {
|
||||
final String world = player.getWorld().getName();
|
||||
final ArrayList<FaweChunk<Chunk>> list = map.get(world);
|
||||
if (list == null) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
final Location loc = player.getLocation();
|
||||
final int cx = loc.getBlockX() >> 4;
|
||||
final int cz = loc.getBlockZ() >> 4;
|
||||
final Object entity = this.methodGetHandlePlayer.of(player).call();
|
||||
|
||||
for (final FaweChunk<Chunk> fc : list) {
|
||||
final int dx = Math.abs(cx - fc.getChunkLoc().x);
|
||||
final int dz = Math.abs(cz - fc.getChunkLoc().z);
|
||||
if ((dx > view) || (dz > view)) {
|
||||
final int px = loc.getBlockX() >> 4;
|
||||
final int pz = loc.getBlockZ() >> 4;
|
||||
if ((Math.abs(cx - px) > view) || (Math.abs(cz - pz) > view)) {
|
||||
continue;
|
||||
}
|
||||
final Object entity = this.methodGetHandlePlayer.of(player).call();
|
||||
final RefExecutor con = this.send.of(this.connection.of(entity).get());
|
||||
Object packet = packets.get(fc);
|
||||
if (packet == null) {
|
||||
final Object c = this.methodGetHandleChunk.of(fc.getChunk()).call();
|
||||
packet = this.MapChunk.create(c, true, 65535);
|
||||
packets.put(fc, packet);
|
||||
con.call(packet);
|
||||
} else {
|
||||
Object packet = this.MapChunk.create(c, false, 65535);
|
||||
con.call(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
final HashSet<FaweChunk<Chunk>> chunks = new HashSet<FaweChunk<Chunk>>();
|
||||
for (final FaweChunk<Chunk> fc : fcs) {
|
||||
final Chunk chunk = fc.getChunk();
|
||||
chunk.unload(true, false);
|
||||
chunk.load();
|
||||
final ChunkLoc loc = fc.getChunkLoc();
|
||||
chunk.getWorld().refreshChunk(loc.x, loc.z);
|
||||
if (!this.fixLighting(fc, Settings.FIX_ALL_LIGHTING)) {
|
||||
chunks.add(fc);
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(final FaweChunk<?> fc, final boolean fixAll) {
|
||||
@ -424,6 +398,13 @@ public class BukkitQueue_1_8 extends BukkitQueue_0 {
|
||||
|
||||
// Clear
|
||||
fs.clear();
|
||||
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendChunk(fs);
|
||||
}
|
||||
}, 1);
|
||||
return true;
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.FaweBukkit
|
||||
version: 3.3.4
|
||||
version: 3.3.5
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
|
@ -1,23 +1,13 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryPoolMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.List;
|
||||
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationEmitter;
|
||||
import javax.management.NotificationListener;
|
||||
|
||||
import com.boydti.fawe.command.FixLighting;
|
||||
import com.boydti.fawe.command.Stream;
|
||||
import com.boydti.fawe.command.Wea;
|
||||
import com.boydti.fawe.command.WorldEditRegion;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.regions.general.PlotSquaredFeature;
|
||||
import com.boydti.fawe.util.Lag;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
@ -42,6 +32,17 @@ import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryPoolMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationEmitter;
|
||||
import javax.management.NotificationListener;
|
||||
|
||||
/**[ WorldEdit action]
|
||||
* |
|
||||
@ -159,6 +160,9 @@ public class Fawe {
|
||||
public void run() {
|
||||
// worldedit
|
||||
WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers());
|
||||
try {
|
||||
WEManager.IMP.managers.add(new PlotSquaredFeature());
|
||||
} catch (Throwable e) {}
|
||||
Fawe.this.worldedit = WorldEdit.getInstance();
|
||||
// Events
|
||||
Fawe.this.setupEvents();
|
||||
@ -258,6 +262,20 @@ public class Fawe {
|
||||
return this.thread;
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String, FawePlayer> players = new ConcurrentHashMap<>();
|
||||
|
||||
public <T> void register(FawePlayer<T> player) {
|
||||
players.put(player.getName(), player);
|
||||
}
|
||||
|
||||
public <T> void unregister(String name) {
|
||||
players.remove(name);
|
||||
}
|
||||
|
||||
public FawePlayer getCachedPlayer(String name) {
|
||||
return players.get(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO FIXME
|
||||
* - Async packet sending
|
||||
|
@ -1,8 +1,5 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
@ -10,6 +7,9 @@ import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public interface IFawe {
|
||||
public void debug(final String s);
|
||||
@ -35,4 +35,6 @@ public interface IFawe {
|
||||
public Collection<FaweMaskManager> getMaskManagers();
|
||||
|
||||
public void startMetrics();
|
||||
|
||||
public Set<FawePlayer> getPlayers();
|
||||
}
|
||||
|
@ -1,17 +1,14 @@
|
||||
package com.boydti.fawe.config;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import java.io.File;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.util.StringMan;
|
||||
import com.boydti.fawe.configuration.file.YamlConfiguration;
|
||||
|
||||
public enum BBC {
|
||||
|
||||
@ -191,15 +188,6 @@ public enum BBC {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return translated and color decoded
|
||||
*
|
||||
* @see org.bukkit.ChatColor#translateAlternateColorCodes(char, String)
|
||||
*/
|
||||
public String translated() {
|
||||
return ChatColor.translateAlternateColorCodes('&', this.s());
|
||||
}
|
||||
|
||||
public String getCat() {
|
||||
return this.cat;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import com.boydti.fawe.configuration.file.YamlConfiguration;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
|
||||
@ -26,6 +26,7 @@ public class Settings {
|
||||
public static boolean ENABLE_HARD_LIMIT = true;
|
||||
public static boolean STORE_HISTORY_ON_DISK = false;
|
||||
public static boolean COMPRESS_HISTORY = false;
|
||||
public static boolean METRICS = true;
|
||||
|
||||
public static void setup(final File file) {
|
||||
if (!file.exists()) {
|
||||
@ -51,6 +52,7 @@ public class Settings {
|
||||
options.put("fix-all-lighting", FIX_ALL_LIGHTING);
|
||||
options.put("history.use-disk", STORE_HISTORY_ON_DISK);
|
||||
options.put("history.compress", COMPRESS_HISTORY);
|
||||
options.put("metrics", METRICS);
|
||||
|
||||
for (final Entry<String, Object> node : options.entrySet()) {
|
||||
if (!config.contains(node.getKey())) {
|
||||
@ -67,6 +69,7 @@ public class Settings {
|
||||
REQUIRE_SELECTION = config.getBoolean("require-selection-in-mask");
|
||||
WE_BLACKLIST = config.getStringList("command-blacklist");
|
||||
ENABLE_HARD_LIMIT = config.getBoolean("crash-mitigation");
|
||||
METRICS = config.getBoolean("metrics");
|
||||
COMPRESS_HISTORY = config.getBoolean("history.compress");
|
||||
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
|
||||
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||
|
@ -0,0 +1,86 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
import com.boydti.fawe.configuration.ConfigurationOptions;
|
||||
import com.boydti.fawe.configuration.ConfigurationSection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a source of configurable options and settings
|
||||
*/
|
||||
public interface Configuration extends ConfigurationSection {
|
||||
/**
|
||||
* Sets the default value of the given path as provided.
|
||||
* <p>
|
||||
* If no source {@link com.boydti.fawe.configuration.Configuration} was provided as a default
|
||||
* collection, then a new {@link com.boydti.fawe.configuration.MemoryConfiguration} will be created to
|
||||
* hold the new default value.
|
||||
* <p>
|
||||
* If value is null, the value will be removed from the default
|
||||
* Configuration source.
|
||||
*
|
||||
* @param path Path of the value to set.
|
||||
* @param value Value to set the default to.
|
||||
* @throws IllegalArgumentException Thrown if path is null.
|
||||
*/
|
||||
@Override void addDefault(final String path, final Object value);
|
||||
|
||||
/**
|
||||
* Sets the default values of the given paths as provided.
|
||||
* <p>
|
||||
* If no source {@link com.boydti.fawe.configuration.Configuration} was provided as a default
|
||||
* collection, then a new {@link com.boydti.fawe.configuration.MemoryConfiguration} will be created to
|
||||
* hold the new default values.
|
||||
*
|
||||
* @param defaults A map of Path->Values to add to defaults.
|
||||
* @throws IllegalArgumentException Thrown if defaults is null.
|
||||
*/
|
||||
void addDefaults(final Map<String, Object> defaults);
|
||||
|
||||
/**
|
||||
* Sets the default values of the given paths as provided.
|
||||
* <p>
|
||||
* If no source {@link com.boydti.fawe.configuration.Configuration} was provided as a default
|
||||
* collection, then a new {@link com.boydti.fawe.configuration.MemoryConfiguration} will be created to
|
||||
* hold the new default value.
|
||||
* <p>
|
||||
* This method will not hold a reference to the specified Configuration,
|
||||
* nor will it automatically update if that Configuration ever changes. If
|
||||
* you require this, you should set the default source with {@link
|
||||
* #setDefaults(com.boydti.fawe.configuration.Configuration)}.
|
||||
*
|
||||
* @param defaults A configuration holding a list of defaults to copy.
|
||||
* @throws IllegalArgumentException Thrown if defaults is null or this.
|
||||
*/
|
||||
void addDefaults(final com.boydti.fawe.configuration.Configuration defaults);
|
||||
|
||||
/**
|
||||
* Sets the source of all default values for this {@link com.boydti.fawe.configuration.Configuration}.
|
||||
* <p>
|
||||
* If a previous source was set, or previous default values were defined,
|
||||
* then they will not be copied to the new source.
|
||||
*
|
||||
* @param defaults New source of default values for this configuration.
|
||||
* @throws IllegalArgumentException Thrown if defaults is null or this.
|
||||
*/
|
||||
void setDefaults(final com.boydti.fawe.configuration.Configuration defaults);
|
||||
|
||||
/**
|
||||
* Gets the source {@link com.boydti.fawe.configuration.Configuration} for this configuration.
|
||||
* <p>
|
||||
* If no configuration source was set, but default values were added, then
|
||||
* a {@link com.boydti.fawe.configuration.MemoryConfiguration} will be returned. If no source was set
|
||||
* and no defaults were set, then this method will return null.
|
||||
*
|
||||
* @return Configuration source for default values, or null if none exist.
|
||||
*/
|
||||
com.boydti.fawe.configuration.Configuration getDefaults();
|
||||
|
||||
/**
|
||||
* Gets the {@link com.boydti.fawe.configuration.ConfigurationOptions} for this {@link com.boydti.fawe.configuration.Configuration}.
|
||||
* <p>
|
||||
* All setters through this method are chainable.
|
||||
*
|
||||
* @return Options for this configuration
|
||||
*/
|
||||
ConfigurationOptions options();
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
import com.boydti.fawe.configuration.Configuration;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* com.boydti.fawe.configuration.Configuration}
|
||||
*/
|
||||
public class ConfigurationOptions {
|
||||
private char pathSeparator = '.';
|
||||
private boolean copyDefaults = false;
|
||||
private final Configuration configuration;
|
||||
|
||||
protected ConfigurationOptions(final Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link com.boydti.fawe.configuration.Configuration} that this object is responsible for.
|
||||
*
|
||||
* @return Parent configuration
|
||||
*/
|
||||
public Configuration configuration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the char that will be used to separate {@link
|
||||
* com.boydti.fawe.configuration.ConfigurationSection}s
|
||||
* <p>
|
||||
* This value does not affect how the {@link com.boydti.fawe.configuration.Configuration} is stored,
|
||||
* only in how you access the data. The default value is '.'.
|
||||
*
|
||||
* @return Path separator
|
||||
*/
|
||||
public char pathSeparator() {
|
||||
return pathSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the char that will be used to separate {@link
|
||||
* com.boydti.fawe.configuration.ConfigurationSection}s
|
||||
* <p>
|
||||
* This value does not affect how the {@link com.boydti.fawe.configuration.Configuration} is stored,
|
||||
* only in how you access the data. The default value is '.'.
|
||||
*
|
||||
* @param value Path separator
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public com.boydti.fawe.configuration.ConfigurationOptions pathSeparator(final char value) {
|
||||
pathSeparator = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the {@link com.boydti.fawe.configuration.Configuration} should copy values from its default
|
||||
* {@link com.boydti.fawe.configuration.Configuration} directly.
|
||||
* <p>
|
||||
* If this is true, all values in the default Configuration will be
|
||||
* directly copied, making it impossible to distinguish between values
|
||||
* that were set and values that are provided by default. As a result,
|
||||
* {@link com.boydti.fawe.configuration.ConfigurationSection#contains(String)} will always
|
||||
* return the same value as {@link
|
||||
* com.boydti.fawe.configuration.ConfigurationSection#isSet(String)}. The default value is
|
||||
* false.
|
||||
*
|
||||
* @return Whether or not defaults are directly copied
|
||||
*/
|
||||
public boolean copyDefaults() {
|
||||
return copyDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the {@link com.boydti.fawe.configuration.Configuration} should copy values from its default
|
||||
* {@link com.boydti.fawe.configuration.Configuration} directly.
|
||||
* <p>
|
||||
* If this is true, all values in the default Configuration will be
|
||||
* directly copied, making it impossible to distinguish between values
|
||||
* that were set and values that are provided by default. As a result,
|
||||
* {@link com.boydti.fawe.configuration.ConfigurationSection#contains(String)} will always
|
||||
* return the same value as {@link
|
||||
* com.boydti.fawe.configuration.ConfigurationSection#isSet(String)}. The default value is
|
||||
* false.
|
||||
*
|
||||
* @param value Whether or not defaults are directly copied
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public com.boydti.fawe.configuration.ConfigurationOptions copyDefaults(final boolean value) {
|
||||
copyDefaults = value;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,646 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
import com.boydti.fawe.configuration.Configuration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents a section of a {@link com.boydti.fawe.configuration.Configuration}
|
||||
*/
|
||||
public interface ConfigurationSection {
|
||||
|
||||
/**
|
||||
* Gets a set containing all keys in this section.
|
||||
* <p>
|
||||
* If deep is set to true, then this will contain all the keys within any
|
||||
* child {@link com.boydti.fawe.configuration.ConfigurationSection}s (and their children, etc). These
|
||||
* will be in a valid path notation for you to use.
|
||||
* <p>
|
||||
* If deep is set to false, then this will contain only the keys of any
|
||||
* direct children, and not their own children.
|
||||
*
|
||||
* @param deep Whether or not to get a deep list, as opposed to a shallow
|
||||
* list.
|
||||
* @return Set of keys contained within this ConfigurationSection.
|
||||
*/
|
||||
Set<String> getKeys(boolean deep);
|
||||
|
||||
/**
|
||||
* Gets a Map containing all keys and their values for this section.
|
||||
* <p>
|
||||
* If deep is set to true, then this will contain all the keys and values
|
||||
* within any child {@link com.boydti.fawe.configuration.ConfigurationSection}s (and their children,
|
||||
* etc). These keys will be in a valid path notation for you to use.
|
||||
* <p>
|
||||
* If deep is set to false, then this will contain only the keys and
|
||||
* values of any direct children, and not their own children.
|
||||
*
|
||||
* @param deep Whether or not to get a deep list, as opposed to a shallow
|
||||
* list.
|
||||
* @return Map of keys and values of this section.
|
||||
*/
|
||||
Map<String, Object> getValues(boolean deep);
|
||||
|
||||
/**
|
||||
* Checks if this {@link com.boydti.fawe.configuration.ConfigurationSection} contains the given path.
|
||||
* <p>
|
||||
* If the value for the requested path does not exist but a default value
|
||||
* has been specified, this will return true.
|
||||
*
|
||||
* @param path Path to check for existence.
|
||||
* @return True if this section contains the requested path, either via
|
||||
* default or being set.
|
||||
* @throws IllegalArgumentException Thrown when path is null.
|
||||
*/
|
||||
boolean contains(String path);
|
||||
|
||||
/**
|
||||
* Checks if this {@link com.boydti.fawe.configuration.ConfigurationSection} has a value set for the
|
||||
* given path.
|
||||
* <p>
|
||||
* If the value for the requested path does not exist but a default value
|
||||
* has been specified, this will still return false.
|
||||
*
|
||||
* @param path Path to check for existence.
|
||||
* @return True if this section contains the requested path, regardless of
|
||||
* having a default.
|
||||
* @throws IllegalArgumentException Thrown when path is null.
|
||||
*/
|
||||
boolean isSet(String path);
|
||||
|
||||
/**
|
||||
* Gets the path of this {@link com.boydti.fawe.configuration.ConfigurationSection} from its root {@link
|
||||
* com.boydti.fawe.configuration.Configuration}
|
||||
* <p>
|
||||
* For any {@link com.boydti.fawe.configuration.Configuration} themselves, this will return an empty
|
||||
* string.
|
||||
* <p>
|
||||
* If the section is no longer contained within its root for any reason,
|
||||
* such as being replaced with a different value, this may return null.
|
||||
* <p>
|
||||
* To retrieve the single name of this section, that is, the final part of
|
||||
* the path returned by this method, you may use {@link #getName()}.
|
||||
*
|
||||
* @return Path of this section relative to its root
|
||||
*/
|
||||
String getCurrentPath();
|
||||
|
||||
/**
|
||||
* Gets the name of this individual {@link com.boydti.fawe.configuration.ConfigurationSection}, in the
|
||||
* path.
|
||||
* <p>
|
||||
* This will always be the final part of {@link #getCurrentPath()}, unless
|
||||
* the section is orphaned.
|
||||
*
|
||||
* @return Name of this section
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the root {@link com.boydti.fawe.configuration.Configuration} that contains this {@link
|
||||
* com.boydti.fawe.configuration.ConfigurationSection}
|
||||
* <p>
|
||||
* For any {@link com.boydti.fawe.configuration.Configuration} themselves, this will return its own
|
||||
* object.
|
||||
* <p>
|
||||
* If the section is no longer contained within its root for any reason,
|
||||
* such as being replaced with a different value, this may return null.
|
||||
*
|
||||
* @return Root configuration containing this section.
|
||||
*/
|
||||
Configuration getRoot();
|
||||
|
||||
/**
|
||||
* Gets the parent {@link com.boydti.fawe.configuration.ConfigurationSection} that directly contains
|
||||
* this {@link com.boydti.fawe.configuration.ConfigurationSection}.
|
||||
* <p>
|
||||
* For any {@link com.boydti.fawe.configuration.Configuration} themselves, this will return null.
|
||||
* <p>
|
||||
* If the section is no longer contained within its parent for any reason,
|
||||
* such as being replaced with a different value, this may return null.
|
||||
*
|
||||
* @return Parent section containing this section.
|
||||
*/
|
||||
com.boydti.fawe.configuration.ConfigurationSection getParent();
|
||||
|
||||
/**
|
||||
* Gets the requested Object by path.
|
||||
* <p>
|
||||
* If the Object does not exist but a default value has been specified,
|
||||
* this will return the default value. If the Object does not exist and no
|
||||
* default value was specified, this will return null.
|
||||
*
|
||||
* @param path Path of the Object to get.
|
||||
* @return Requested Object.
|
||||
*/
|
||||
Object get(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested Object by path, returning a default value if not
|
||||
* found.
|
||||
* <p>
|
||||
* If the Object does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*
|
||||
* @param path Path of the Object to get.
|
||||
* @param def The default value to return if the path is not found.
|
||||
* @return Requested Object.
|
||||
*/
|
||||
Object get(String path, Object def);
|
||||
|
||||
/**
|
||||
* Sets the specified path to the given value.
|
||||
* <p>
|
||||
* If value is null, the entry will be removed. Any existing entry will be
|
||||
* replaced, regardless of what the new value is.
|
||||
* <p>
|
||||
* Some implementations may have limitations on what you may store. See
|
||||
* their individual javadoc for details. No implementations should allow
|
||||
* you to store {@link com.boydti.fawe.configuration.Configuration}s or {@link com.boydti.fawe.configuration.ConfigurationSection}s,
|
||||
* please use {@link #createSection(String)} for that.
|
||||
*
|
||||
* @param path Path of the object to set.
|
||||
* @param value New value to set the path to.
|
||||
*/
|
||||
void set(String path, Object value);
|
||||
|
||||
/**
|
||||
* Creates an empty {@link com.boydti.fawe.configuration.ConfigurationSection} at the specified path.
|
||||
* <p>
|
||||
* Any value that was previously set at this path will be overwritten. If
|
||||
* the previous value was itself a {@link com.boydti.fawe.configuration.ConfigurationSection}, it will
|
||||
* be orphaned.
|
||||
*
|
||||
* @param path Path to create the section at.
|
||||
* @return Newly created section
|
||||
*/
|
||||
com.boydti.fawe.configuration.ConfigurationSection createSection(String path);
|
||||
|
||||
/**
|
||||
* Creates a {@link com.boydti.fawe.configuration.ConfigurationSection} at the specified path, with
|
||||
* specified values.
|
||||
* <p>
|
||||
* Any value that was previously set at this path will be overwritten. If
|
||||
* the previous value was itself a {@link com.boydti.fawe.configuration.ConfigurationSection}, it will
|
||||
* be orphaned.
|
||||
*
|
||||
* @param path Path to create the section at.
|
||||
* @param map The values to used.
|
||||
* @return Newly created section
|
||||
*/
|
||||
com.boydti.fawe.configuration.ConfigurationSection createSection(String path, Map<?, ?> map);
|
||||
|
||||
// Primitives
|
||||
|
||||
/**
|
||||
* Gets the requested String by path.
|
||||
* <p>
|
||||
* If the String does not exist but a default value has been specified,
|
||||
* this will return the default value. If the String does not exist and no
|
||||
* default value was specified, this will return null.
|
||||
*
|
||||
* @param path Path of the String to get.
|
||||
* @return Requested String.
|
||||
*/
|
||||
String getString(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested String by path, returning a default value if not
|
||||
* found.
|
||||
* <p>
|
||||
* If the String does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*
|
||||
* @param path Path of the String to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a String.
|
||||
* @return Requested String.
|
||||
*/
|
||||
String getString(String path, String def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a String.
|
||||
*
|
||||
* <p> If the path exists but is not a String, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a String and return appropriately.</p>
|
||||
*
|
||||
* @param path Path of the String to check.
|
||||
* @return Whether or not the specified path is a String.
|
||||
*/
|
||||
boolean isString(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested int by path.
|
||||
*
|
||||
* <p>If the int does not exist but a default value has been specified, this
|
||||
* will return the default value. If the int does not exist and no default
|
||||
* value was specified, this will return 0.</p>
|
||||
*
|
||||
* @param path Path of the int to get.
|
||||
* @return Requested int.
|
||||
*/
|
||||
int getInt(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested int by path, returning a default value if not found.
|
||||
*
|
||||
* <p>If the int does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.</p>
|
||||
*
|
||||
* @param path Path of the int to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not an int.
|
||||
* @return Requested int.
|
||||
*/
|
||||
int getInt(String path, int def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is an int.
|
||||
*
|
||||
* <p>If the path exists but is not a int, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a int and return appropriately.</p>
|
||||
*
|
||||
* @param path Path of the int to check.
|
||||
* @return Whether or not the specified path is an int.
|
||||
*/
|
||||
boolean isInt(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested boolean by path.
|
||||
* <p>
|
||||
* If the boolean does not exist but a default value has been specified,
|
||||
* this will return the default value. If the boolean does not exist and
|
||||
* no default value was specified, this will return false.
|
||||
*
|
||||
* @param path Path of the boolean to get.
|
||||
* @return Requested boolean.
|
||||
*/
|
||||
boolean getBoolean(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested boolean by path, returning a default value if not
|
||||
* found.
|
||||
* <p>
|
||||
* If the boolean does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*
|
||||
* @param path Path of the boolean to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a boolean.
|
||||
* @return Requested boolean.
|
||||
*/
|
||||
boolean getBoolean(String path, boolean def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a boolean.
|
||||
* <p>
|
||||
* If the path exists but is not a boolean, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a boolean and return appropriately.
|
||||
*
|
||||
* @param path Path of the boolean to check.
|
||||
* @return Whether or not the specified path is a boolean.
|
||||
*/
|
||||
boolean isBoolean(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested double by path.
|
||||
* <p>
|
||||
* If the double does not exist but a default value has been specified,
|
||||
* this will return the default value. If the double does not exist and no
|
||||
* default value was specified, this will return 0.
|
||||
*
|
||||
* @param path Path of the double to get.
|
||||
* @return Requested double.
|
||||
*/
|
||||
double getDouble(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested double by path, returning a default value if not
|
||||
* found.
|
||||
* <p>
|
||||
* If the double does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*
|
||||
* @param path Path of the double to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a double.
|
||||
* @return Requested double.
|
||||
*/
|
||||
double getDouble(String path, double def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a double.
|
||||
* <p>
|
||||
* If the path exists but is not a double, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a double and return appropriately.
|
||||
*
|
||||
* @param path Path of the double to check.
|
||||
* @return Whether or not the specified path is a double.
|
||||
*/
|
||||
boolean isDouble(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested long by path.
|
||||
* <p>
|
||||
* If the long does not exist but a default value has been specified, this
|
||||
* will return the default value. If the long does not exist and no
|
||||
* default value was specified, this will return 0.
|
||||
*
|
||||
* @param path Path of the long to get.
|
||||
* @return Requested long.
|
||||
*/
|
||||
long getLong(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested long by path, returning a default value if not
|
||||
* found.
|
||||
* <p>
|
||||
* If the long does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*
|
||||
* @param path Path of the long to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a long.
|
||||
* @return Requested long.
|
||||
*/
|
||||
long getLong(String path, long def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a long.
|
||||
* <p>
|
||||
* If the path exists but is not a long, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a long and return appropriately.
|
||||
*
|
||||
* @param path Path of the long to check.
|
||||
* @return Whether or not the specified path is a long.
|
||||
*/
|
||||
boolean isLong(String path);
|
||||
|
||||
// Java
|
||||
|
||||
/**
|
||||
* Gets the requested List by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return null.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List.
|
||||
*/
|
||||
List<?> getList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List by path, returning a default value if not
|
||||
* found.
|
||||
* <p>
|
||||
* If the List does not exist then the specified default value will
|
||||
* returned regardless of if a default has been identified in the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @param def The default value to return if the path is not found or is
|
||||
* not a List.
|
||||
* @return Requested List.
|
||||
*/
|
||||
List<?> getList(String path, List<?> def);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a List.
|
||||
* <p>
|
||||
* If the path exists but is not a List, this will return false. If the
|
||||
* path does not exist, this will return false. If the path does not exist
|
||||
* but a default value has been specified, this will check if that default
|
||||
* value is a List and return appropriately.
|
||||
*
|
||||
* @param path Path of the List to check.
|
||||
* @return Whether or not the specified path is a List.
|
||||
*/
|
||||
boolean isList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of String by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a String if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of String.
|
||||
*/
|
||||
List<String> getStringList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Integer by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Integer if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Integer.
|
||||
*/
|
||||
List<Integer> getIntegerList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Boolean by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Boolean if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Boolean.
|
||||
*/
|
||||
List<Boolean> getBooleanList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Double by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Double if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Double.
|
||||
*/
|
||||
List<Double> getDoubleList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Float by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Float if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Float.
|
||||
*/
|
||||
List<Float> getFloatList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Long by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Long if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Long.
|
||||
*/
|
||||
List<Long> getLongList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Byte by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Byte if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Byte.
|
||||
*/
|
||||
List<Byte> getByteList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Character by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Character if
|
||||
* possible, but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Character.
|
||||
*/
|
||||
List<Character> getCharacterList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Short by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Short if possible,
|
||||
* but may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Short.
|
||||
*/
|
||||
List<Short> getShortList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested List of Maps by path.
|
||||
* <p>
|
||||
* If the List does not exist but a default value has been specified, this
|
||||
* will return the default value. If the List does not exist and no
|
||||
* default value was specified, this will return an empty List.
|
||||
* <p>
|
||||
* This method will attempt to cast any values into a Map if possible, but
|
||||
* may miss any values out if they are not compatible.
|
||||
*
|
||||
* @param path Path of the List to get.
|
||||
* @return Requested List of Maps.
|
||||
*/
|
||||
List<Map<?, ?>> getMapList(String path);
|
||||
|
||||
/**
|
||||
* Gets the requested ConfigurationSection by path.
|
||||
* <p>
|
||||
* If the ConfigurationSection does not exist but a default value has been
|
||||
* specified, this will return the default value. If the
|
||||
* ConfigurationSection does not exist and no default value was specified,
|
||||
* this will return null.
|
||||
*
|
||||
* @param path Path of the ConfigurationSection to get.
|
||||
* @return Requested ConfigurationSection.
|
||||
*/
|
||||
com.boydti.fawe.configuration.ConfigurationSection getConfigurationSection(String path);
|
||||
|
||||
/**
|
||||
* Checks if the specified path is a ConfigurationSection.
|
||||
* <p>
|
||||
* If the path exists but is not a ConfigurationSection, this will return
|
||||
* false. If the path does not exist, this will return false. If the path
|
||||
* does not exist but a default value has been specified, this will check
|
||||
* if that default value is a ConfigurationSection and return
|
||||
* appropriately.
|
||||
*
|
||||
* @param path Path of the ConfigurationSection to check.
|
||||
* @return Whether or not the specified path is a ConfigurationSection.
|
||||
*/
|
||||
boolean isConfigurationSection(String path);
|
||||
|
||||
/**
|
||||
* Gets the equivalent {@link com.boydti.fawe.configuration.ConfigurationSection} from the default
|
||||
* {@link com.boydti.fawe.configuration.Configuration} defined in {@link #getRoot()}.
|
||||
* <p>
|
||||
* If the root contains no defaults, or the defaults doesn't contain a
|
||||
* value for this path, or the value at this path is not a {@link
|
||||
* com.boydti.fawe.configuration.ConfigurationSection} then this will return null.
|
||||
*
|
||||
* @return Equivalent section in root configuration
|
||||
*/
|
||||
com.boydti.fawe.configuration.ConfigurationSection getDefaultSection();
|
||||
|
||||
/**
|
||||
* Sets the default value in the root at the given path as provided.
|
||||
* <p>
|
||||
* If no source {@link com.boydti.fawe.configuration.Configuration} was provided as a default
|
||||
* collection, then a new {@link com.boydti.fawe.configuration.MemoryConfiguration} will be created to
|
||||
* hold the new default value.
|
||||
* <p>
|
||||
* If value is null, the value will be removed from the default
|
||||
* Configuration source.
|
||||
* <p>
|
||||
* If the value as returned by {@link #getDefaultSection()} is null, then
|
||||
* this will create a new section at the path, replacing anything that may
|
||||
* have existed there previously.
|
||||
*
|
||||
* @param path Path of the value to set.
|
||||
* @param value Value to set the default to.
|
||||
* @throws IllegalArgumentException Thrown if path is null.
|
||||
*/
|
||||
void addDefault(String path, Object value);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to load an invalid {@link com.boydti.fawe.configuration.Configuration}
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class InvalidConfigurationException extends Exception {
|
||||
|
||||
/**
|
||||
* Creates a new instance of InvalidConfigurationException without a
|
||||
* message or cause.
|
||||
*/
|
||||
public InvalidConfigurationException() {}
|
||||
|
||||
/**
|
||||
* Constructs an instance of InvalidConfigurationException with the
|
||||
* specified message.
|
||||
*
|
||||
* @param msg The details of the exception.
|
||||
*/
|
||||
public InvalidConfigurationException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of InvalidConfigurationException with the
|
||||
* specified cause.
|
||||
*
|
||||
* @param cause The cause of the exception.
|
||||
*/
|
||||
public InvalidConfigurationException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of InvalidConfigurationException with the
|
||||
* specified message and cause.
|
||||
*
|
||||
* @param cause The cause of the exception.
|
||||
* @param msg The details of the exception.
|
||||
*/
|
||||
public InvalidConfigurationException(final String msg, final Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
import com.boydti.fawe.configuration.Configuration;
|
||||
import com.boydti.fawe.configuration.ConfigurationSection;
|
||||
import com.boydti.fawe.configuration.MemoryConfigurationOptions;
|
||||
import com.boydti.fawe.configuration.MemorySection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This is a {@link com.boydti.fawe.configuration.Configuration} implementation that does not save or load
|
||||
* from any source, and stores all values in memory only.
|
||||
* This is useful for temporary Configurations for providing defaults.
|
||||
*/
|
||||
public class MemoryConfiguration extends MemorySection implements Configuration {
|
||||
protected Configuration defaults;
|
||||
protected MemoryConfigurationOptions options;
|
||||
|
||||
/**
|
||||
* Creates an empty {@link com.boydti.fawe.configuration.MemoryConfiguration} with no default values.
|
||||
*/
|
||||
public MemoryConfiguration() {}
|
||||
|
||||
/**
|
||||
* Creates an empty {@link com.boydti.fawe.configuration.MemoryConfiguration} using the specified {@link
|
||||
* com.boydti.fawe.configuration.Configuration} as a source for all default values.
|
||||
*
|
||||
* @param defaults Default value provider
|
||||
* @throws IllegalArgumentException Thrown if defaults is null
|
||||
*/
|
||||
public MemoryConfiguration(final Configuration defaults) {
|
||||
this.defaults = defaults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefault(final String path, final Object value) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Path may not be null");
|
||||
}
|
||||
if (defaults == null) {
|
||||
defaults = new com.boydti.fawe.configuration.MemoryConfiguration();
|
||||
}
|
||||
|
||||
defaults.set(path, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefaults(final Map<String, Object> defaults) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("Defaults may not be null");
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, Object> entry : defaults.entrySet()) {
|
||||
addDefault(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefaults(final Configuration defaults) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("Defaults may not be null");
|
||||
}
|
||||
|
||||
addDefaults(defaults.getValues(true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaults(final Configuration defaults) {
|
||||
if (defaults == null) {
|
||||
throw new NullPointerException("Defaults may not be null");
|
||||
}
|
||||
|
||||
this.defaults = defaults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration getDefaults() {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationSection getParent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryConfigurationOptions options() {
|
||||
if (options == null) {
|
||||
options = new MemoryConfigurationOptions(this);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
import com.boydti.fawe.configuration.ConfigurationOptions;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* com.boydti.fawe.configuration.MemoryConfiguration}
|
||||
*/
|
||||
public class MemoryConfigurationOptions extends ConfigurationOptions {
|
||||
protected MemoryConfigurationOptions(final MemoryConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryConfiguration configuration() {
|
||||
return (MemoryConfiguration) super.configuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.MemoryConfigurationOptions copyDefaults(final boolean value) {
|
||||
super.copyDefaults(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.MemoryConfigurationOptions pathSeparator(final char value) {
|
||||
super.pathSeparator(value);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,847 @@
|
||||
package com.boydti.fawe.configuration;
|
||||
|
||||
import com.boydti.fawe.configuration.ConfigurationSection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A type of {@link com.boydti.fawe.configuration.ConfigurationSection} that is stored in memory.
|
||||
*/
|
||||
public class MemorySection implements com.boydti.fawe.configuration.ConfigurationSection {
|
||||
|
||||
protected final Map<String, Object> map = new LinkedHashMap<>();
|
||||
private final Configuration root;
|
||||
private final com.boydti.fawe.configuration.ConfigurationSection parent;
|
||||
private final String path;
|
||||
private final String fullPath;
|
||||
|
||||
/**
|
||||
* Creates an empty MemorySection for use as a root {@link com.boydti.fawe.configuration.Configuration}
|
||||
* section.
|
||||
* <p>
|
||||
* Note that calling this without being yourself a {@link com.boydti.fawe.configuration.Configuration}
|
||||
* will throw an exception!
|
||||
*
|
||||
* @throws IllegalStateException Thrown if this is not a {@link
|
||||
* com.boydti.fawe.configuration.Configuration} root.
|
||||
*/
|
||||
protected MemorySection() {
|
||||
if (!(this instanceof Configuration)) {
|
||||
throw new IllegalStateException("Cannot construct a root MemorySection when not a Configuration");
|
||||
}
|
||||
|
||||
this.path = "";
|
||||
this.fullPath = "";
|
||||
this.parent = null;
|
||||
this.root = (Configuration) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty MemorySection with the specified parent and path.
|
||||
*
|
||||
* @param parent Parent section that contains this own section.
|
||||
* @param path Path that you may access this section from via the root
|
||||
* {@link com.boydti.fawe.configuration.Configuration}.
|
||||
* @throws IllegalArgumentException Thrown is parent or path is null, or
|
||||
* if parent contains no root Configuration.
|
||||
*/
|
||||
protected MemorySection(com.boydti.fawe.configuration.ConfigurationSection parent, String path) {
|
||||
if (parent == null) {
|
||||
throw new NullPointerException("Parent may not be null");
|
||||
}
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Path may not be null");
|
||||
}
|
||||
|
||||
this.path = path;
|
||||
this.parent = parent;
|
||||
this.root = parent.getRoot();
|
||||
|
||||
if (this.root == null) {
|
||||
throw new NullPointerException("Path may not be orphaned");
|
||||
}
|
||||
|
||||
this.fullPath = createPath(parent, path);
|
||||
}
|
||||
|
||||
public static double toDouble(Object obj, double def) {
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).doubleValue();
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
try {
|
||||
return Double.parseDouble((String) obj);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (obj instanceof List) {
|
||||
List<?> val = (List<?>) obj;
|
||||
if (!val.isEmpty()) {
|
||||
return toDouble(val.get(0), def);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static int toInt(Object obj, int def) {
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).intValue();
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
try {
|
||||
return Integer.parseInt((String) obj);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (obj instanceof List) {
|
||||
List<?> val = (List<?>) obj;
|
||||
if (!val.isEmpty()) {
|
||||
return toInt(val.get(0), def);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static long toLong(Object obj, long def) {
|
||||
if (obj instanceof Number) {
|
||||
return ((Number) obj).longValue();
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
try {
|
||||
return Long.parseLong((String) obj);
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (obj instanceof List) {
|
||||
List<?> val = (List<?>) obj;
|
||||
if (!val.isEmpty()) {
|
||||
return toLong(val.get(0), def);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a full path to the given {@link com.boydti.fawe.configuration.ConfigurationSection} from its
|
||||
* root {@link com.boydti.fawe.configuration.Configuration}.
|
||||
* <p>
|
||||
* You may use this method for any given {@link com.boydti.fawe.configuration.ConfigurationSection}, not
|
||||
* only {@link com.boydti.fawe.configuration.MemorySection}.
|
||||
*
|
||||
* @param section Section to create a path for.
|
||||
* @param key Name of the specified section.
|
||||
* @return Full path of the section from its root.
|
||||
*/
|
||||
public static String createPath(com.boydti.fawe.configuration.ConfigurationSection section, String key) {
|
||||
return createPath(section, key, (section == null) ? null : section.getRoot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a relative path to the given {@link com.boydti.fawe.configuration.ConfigurationSection} from
|
||||
* the given relative section.
|
||||
* <p>
|
||||
* You may use this method for any given {@link com.boydti.fawe.configuration.ConfigurationSection}, not
|
||||
* only {@link com.boydti.fawe.configuration.MemorySection}.
|
||||
*
|
||||
* @param section Section to create a path for.
|
||||
* @param key Name of the specified section.
|
||||
* @param relativeTo Section to create the path relative to.
|
||||
* @return Full path of the section from its root.
|
||||
*/
|
||||
public static String createPath(com.boydti.fawe.configuration.ConfigurationSection section, String key, com.boydti.fawe.configuration.ConfigurationSection relativeTo) {
|
||||
if (section == null) {
|
||||
throw new NullPointerException("Cannot create path without a section");
|
||||
}
|
||||
Configuration root = section.getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot create path without a root");
|
||||
}
|
||||
char separator = root.options().pathSeparator();
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (com.boydti.fawe.configuration.ConfigurationSection parent = section; (parent != null) && (parent != relativeTo); parent = parent.getParent()) {
|
||||
if (builder.length() > 0) {
|
||||
builder.insert(0, separator);
|
||||
}
|
||||
|
||||
builder.insert(0, parent.getName());
|
||||
}
|
||||
|
||||
if ((key != null) && !key.isEmpty()) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append(separator);
|
||||
}
|
||||
|
||||
builder.append(key);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys(boolean deep) {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
|
||||
Configuration root = getRoot();
|
||||
if ((root != null) && root.options().copyDefaults()) {
|
||||
com.boydti.fawe.configuration.ConfigurationSection defaults = getDefaultSection();
|
||||
|
||||
if (defaults != null) {
|
||||
result.addAll(defaults.getKeys(deep));
|
||||
}
|
||||
}
|
||||
|
||||
mapChildrenKeys(result, this, deep);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getValues(boolean deep) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
|
||||
Configuration root = getRoot();
|
||||
if ((root != null) && root.options().copyDefaults()) {
|
||||
com.boydti.fawe.configuration.ConfigurationSection defaults = getDefaultSection();
|
||||
|
||||
if (defaults != null) {
|
||||
result.putAll(defaults.getValues(deep));
|
||||
}
|
||||
}
|
||||
|
||||
mapChildrenValues(result, this, deep);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String path) {
|
||||
return get(path) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSet(String path) {
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
return false;
|
||||
}
|
||||
if (root.options().copyDefaults()) {
|
||||
return contains(path);
|
||||
}
|
||||
return get(path, null) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentPath() {
|
||||
return this.fullPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration getRoot() {
|
||||
return this.root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.ConfigurationSection getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefault(String path, Object value) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Path cannot be null");
|
||||
}
|
||||
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot add default without root");
|
||||
}
|
||||
if (root == this) {
|
||||
throw new UnsupportedOperationException("Unsupported addDefault(String, Object) implementation");
|
||||
}
|
||||
root.addDefault(createPath(this, path), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.ConfigurationSection getDefaultSection() {
|
||||
Configuration root = getRoot();
|
||||
Configuration defaults = root == null ? null : root.getDefaults();
|
||||
|
||||
if (defaults != null) {
|
||||
if (defaults.isConfigurationSection(getCurrentPath())) {
|
||||
return defaults.getConfigurationSection(getCurrentPath());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String path, Object value) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Cannot set to an empty path");
|
||||
}
|
||||
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot use section without a root");
|
||||
}
|
||||
|
||||
char separator = root.options().pathSeparator();
|
||||
// i1 is the leading (higher) index
|
||||
// i2 is the trailing (lower) index
|
||||
int i1 = -1, i2;
|
||||
com.boydti.fawe.configuration.ConfigurationSection section = this;
|
||||
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
|
||||
String node = path.substring(i2, i1);
|
||||
com.boydti.fawe.configuration.ConfigurationSection subSection = section.getConfigurationSection(node);
|
||||
if (subSection == null) {
|
||||
section = section.createSection(node);
|
||||
} else {
|
||||
section = subSection;
|
||||
}
|
||||
}
|
||||
|
||||
String key = path.substring(i2);
|
||||
if (section == this) {
|
||||
if (value == null) {
|
||||
this.map.remove(key);
|
||||
} else {
|
||||
this.map.put(key, value);
|
||||
}
|
||||
} else {
|
||||
section.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String path) {
|
||||
return get(path, getDefault(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String path, Object def) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Path cannot be null");
|
||||
}
|
||||
|
||||
if (path.isEmpty()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot access section without a root");
|
||||
}
|
||||
|
||||
char separator = root.options().pathSeparator();
|
||||
// i1 is the leading (higher) index
|
||||
// i2 is the trailing (lower) index
|
||||
int i1 = -1;
|
||||
int i2;
|
||||
com.boydti.fawe.configuration.ConfigurationSection section = this;
|
||||
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
|
||||
section = section.getConfigurationSection(path.substring(i2, i1));
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
String key = path.substring(i2);
|
||||
if (section == this) {
|
||||
Object result = this.map.get(key);
|
||||
if (result == null) {
|
||||
return def;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return section.get(key, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.ConfigurationSection createSection(String path) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Cannot create section at empty path");
|
||||
}
|
||||
Configuration root = getRoot();
|
||||
if (root == null) {
|
||||
throw new IllegalStateException("Cannot create section without a root");
|
||||
}
|
||||
|
||||
char separator = root.options().pathSeparator();
|
||||
// i1 is the leading (higher) index
|
||||
// i2 is the trailing (lower) index
|
||||
int i1 = -1, i2;
|
||||
com.boydti.fawe.configuration.ConfigurationSection section = this;
|
||||
while ((i1 = path.indexOf(separator, i2 = i1 + 1)) != -1) {
|
||||
String node = path.substring(i2, i1);
|
||||
com.boydti.fawe.configuration.ConfigurationSection subSection = section.getConfigurationSection(node);
|
||||
if (subSection == null) {
|
||||
section = section.createSection(node);
|
||||
} else {
|
||||
section = subSection;
|
||||
}
|
||||
}
|
||||
|
||||
String key = path.substring(i2);
|
||||
if (section == this) {
|
||||
com.boydti.fawe.configuration.ConfigurationSection result = new com.boydti.fawe.configuration.MemorySection(this, key);
|
||||
this.map.put(key, result);
|
||||
return result;
|
||||
}
|
||||
return section.createSection(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.ConfigurationSection createSection(String path, Map<?, ?> map) {
|
||||
com.boydti.fawe.configuration.ConfigurationSection section = createSection(path);
|
||||
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
if (entry.getValue() instanceof Map) {
|
||||
section.createSection(entry.getKey().toString(), (Map<?, ?>) entry.getValue());
|
||||
} else {
|
||||
section.set(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
// Primitives
|
||||
@Override
|
||||
public String getString(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getString(path, def != null ? def.toString() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String path, String def) {
|
||||
Object val = get(path, def);
|
||||
if (val != null) {
|
||||
return val.toString();
|
||||
} else {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isString(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof String;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getInt(path, toInt(def, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String path, int def) {
|
||||
Object val = get(path, def);
|
||||
return toInt(val, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInt(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Integer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String path) {
|
||||
Object def = getDefault(path);
|
||||
if (def instanceof Boolean) {
|
||||
return getBoolean(path, (Boolean) def);
|
||||
} else {
|
||||
return getBoolean(path, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String path, boolean def) {
|
||||
Object val = get(path, def);
|
||||
if (val instanceof Boolean) {
|
||||
return (Boolean) val;
|
||||
} else {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoolean(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Boolean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getDouble(path, toDouble(def, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(String path, double def) {
|
||||
Object val = get(path, def);
|
||||
return toDouble(val, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDouble(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Double;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getLong(path, toLong(def, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String path, long def) {
|
||||
Object val = get(path, def);
|
||||
return toLong(val, def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLong(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof Long;
|
||||
}
|
||||
|
||||
// Java
|
||||
@Override
|
||||
public List<?> getList(String path) {
|
||||
Object def = getDefault(path);
|
||||
return getList(path, def instanceof List ? (List<?>) def : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<?> getList(String path, List<?> def) {
|
||||
Object val = get(path, def);
|
||||
return (List<?>) ((val instanceof List) ? val : def);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isList(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof List;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringList(String path) {
|
||||
final List<?> list = getList(path);
|
||||
|
||||
if (list == null) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
|
||||
final List<String> result = new ArrayList<>();
|
||||
|
||||
for (final Object object : list) {
|
||||
if ((object instanceof String) || (isPrimitiveWrapper(object))) {
|
||||
result.add(String.valueOf(object));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getIntegerList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Integer> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Integer) {
|
||||
result.add((Integer) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Integer.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((int) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Boolean> getBooleanList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Boolean> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Boolean) {
|
||||
result.add((Boolean) object);
|
||||
} else if (object instanceof String) {
|
||||
if (Boolean.TRUE.toString().equals(object)) {
|
||||
result.add(true);
|
||||
} else if (Boolean.FALSE.toString().equals(object)) {
|
||||
result.add(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Double> getDoubleList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Double> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Double) {
|
||||
result.add((Double) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Double.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((double) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).doubleValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Float> getFloatList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Float> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Float) {
|
||||
result.add((Float) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Float.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((float) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).floatValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> getLongList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Long> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Long) {
|
||||
result.add((Long) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Long.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((long) (Character) object);
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).longValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Byte> getByteList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Byte> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Byte) {
|
||||
result.add((Byte) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Byte.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((byte) ((Character) object).charValue());
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).byteValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Character> getCharacterList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Character> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Character) {
|
||||
result.add((Character) object);
|
||||
} else if (object instanceof String) {
|
||||
String str = (String) object;
|
||||
|
||||
if (str.length() == 1) {
|
||||
result.add(str.charAt(0));
|
||||
}
|
||||
} else if (object instanceof Number) {
|
||||
result.add((char) ((Number) object).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Short> getShortList(String path) {
|
||||
List<?> list = getList(path);
|
||||
|
||||
List<Short> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Short) {
|
||||
result.add((Short) object);
|
||||
} else if (object instanceof String) {
|
||||
try {
|
||||
result.add(Short.valueOf((String) object));
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
} else if (object instanceof Character) {
|
||||
result.add((short) ((Character) object).charValue());
|
||||
} else if (object instanceof Number) {
|
||||
result.add(((Number) object).shortValue());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<?, ?>> getMapList(String path) {
|
||||
List<?> list = getList(path);
|
||||
List<Map<?, ?>> result = new ArrayList<>();
|
||||
|
||||
for (Object object : list) {
|
||||
if (object instanceof Map) {
|
||||
result.add((Map<?, ?>) object);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.ConfigurationSection getConfigurationSection(String path) {
|
||||
Object val = get(path, null);
|
||||
if (val != null) {
|
||||
return (val instanceof com.boydti.fawe.configuration.ConfigurationSection) ? (com.boydti.fawe.configuration.ConfigurationSection) val : null;
|
||||
}
|
||||
|
||||
val = get(path, getDefault(path));
|
||||
return (val instanceof com.boydti.fawe.configuration.ConfigurationSection) ? createSection(path) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfigurationSection(String path) {
|
||||
Object val = get(path);
|
||||
return val instanceof com.boydti.fawe.configuration.ConfigurationSection;
|
||||
}
|
||||
|
||||
protected boolean isPrimitiveWrapper(Object input) {
|
||||
return (input instanceof Integer)
|
||||
|| (input instanceof Boolean)
|
||||
|| (input instanceof Character)
|
||||
|| (input instanceof Byte)
|
||||
|| (input instanceof Short)
|
||||
|| (input instanceof Double)
|
||||
|| (input instanceof Long)
|
||||
|| (input instanceof Float);
|
||||
}
|
||||
|
||||
protected Object getDefault(String path) {
|
||||
if (path == null) {
|
||||
throw new NullPointerException("Path may not be null");
|
||||
}
|
||||
|
||||
Configuration root = getRoot();
|
||||
Configuration defaults = root == null ? null : root.getDefaults();
|
||||
return (defaults == null) ? null : defaults.get(createPath(this, path));
|
||||
}
|
||||
|
||||
protected void mapChildrenKeys(Set<String> output, com.boydti.fawe.configuration.ConfigurationSection section, boolean deep) {
|
||||
if (section instanceof com.boydti.fawe.configuration.MemorySection) {
|
||||
com.boydti.fawe.configuration.MemorySection sec = (com.boydti.fawe.configuration.MemorySection) section;
|
||||
|
||||
for (Map.Entry<String, Object> entry : sec.map.entrySet()) {
|
||||
output.add(createPath(section, entry.getKey(), this));
|
||||
|
||||
if (deep && (entry.getValue() instanceof com.boydti.fawe.configuration.ConfigurationSection)) {
|
||||
com.boydti.fawe.configuration.ConfigurationSection subsection = (com.boydti.fawe.configuration.ConfigurationSection) entry.getValue();
|
||||
mapChildrenKeys(output, subsection, deep);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Set<String> keys = section.getKeys(deep);
|
||||
|
||||
for (String key : keys) {
|
||||
output.add(createPath(section, key, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void mapChildrenValues(Map<String, Object> output, com.boydti.fawe.configuration.ConfigurationSection section, boolean deep) {
|
||||
if (section instanceof com.boydti.fawe.configuration.MemorySection) {
|
||||
com.boydti.fawe.configuration.MemorySection sec = (com.boydti.fawe.configuration.MemorySection) section;
|
||||
|
||||
for (Map.Entry<String, Object> entry : sec.map.entrySet()) {
|
||||
output.put(createPath(section, entry.getKey(), this), entry.getValue());
|
||||
|
||||
if (entry.getValue() instanceof com.boydti.fawe.configuration.ConfigurationSection) {
|
||||
if (deep) {
|
||||
mapChildrenValues(output, (ConfigurationSection) entry.getValue(), deep);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Map<String, Object> values = section.getValues(deep);
|
||||
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
output.put(createPath(section, entry.getKey(), this), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Configuration root = getRoot();
|
||||
return getClass().getSimpleName() + "[path='" + getCurrentPath() + "', root='" + (root == null ? null : root.getClass().getSimpleName()) +
|
||||
"']";
|
||||
}
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
package com.boydti.fawe.configuration.file;
|
||||
|
||||
import com.boydti.fawe.configuration.Configuration;
|
||||
import com.boydti.fawe.configuration.InvalidConfigurationException;
|
||||
import com.boydti.fawe.configuration.MemoryConfiguration;
|
||||
import com.boydti.fawe.configuration.file.FileConfigurationOptions;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* This is a base class for all File based implementations of {@link
|
||||
* com.boydti.fawe.configuration.Configuration}
|
||||
*/
|
||||
public abstract class FileConfiguration extends MemoryConfiguration {
|
||||
|
||||
/**
|
||||
* Creates an empty {@link com.boydti.fawe.configuration.file.FileConfiguration} with no default values.
|
||||
*/
|
||||
public FileConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty {@link com.boydti.fawe.configuration.file.FileConfiguration} using the specified {@link
|
||||
* com.boydti.fawe.configuration.Configuration} as a source for all default values.
|
||||
*
|
||||
* @param defaults Default value provider
|
||||
*/
|
||||
public FileConfiguration(Configuration defaults) {
|
||||
super(defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this {@link com.boydti.fawe.configuration.file.FileConfiguration} to the specified location.
|
||||
* <p>
|
||||
* If the file does not exist, it will be created. If already exists, it
|
||||
* will be overwritten. If it cannot be overwritten or created, an
|
||||
* exception will be thrown.
|
||||
* <p>
|
||||
* This method will save using the system default encoding, or possibly
|
||||
* using UTF8.
|
||||
*
|
||||
* @param file File to save to.
|
||||
* @throws java.io.IOException Thrown when the given file cannot be written to for
|
||||
* any reason.
|
||||
* @throws IllegalArgumentException Thrown when file is null.
|
||||
*/
|
||||
public void save(File file) throws IOException {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("File cannot be null");
|
||||
}
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
String data = saveToString();
|
||||
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
|
||||
writer.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this {@link com.boydti.fawe.configuration.file.FileConfiguration} to the specified location.
|
||||
* <p>
|
||||
* If the file does not exist, it will be created. If already exists, it
|
||||
* will be overwritten. If it cannot be overwritten or created, an
|
||||
* exception will be thrown.
|
||||
* <p>
|
||||
* This method will save using the system default encoding, or possibly
|
||||
* using UTF8.
|
||||
*
|
||||
* @param file File to save to.
|
||||
* @throws java.io.IOException Thrown when the given file cannot be written to for
|
||||
* any reason.
|
||||
* @throws IllegalArgumentException Thrown when file is null.
|
||||
*/
|
||||
public void save(String file) throws IOException {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("File cannot be null");
|
||||
}
|
||||
|
||||
save(new File(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves this {@link com.boydti.fawe.configuration.file.FileConfiguration} to a string, and returns it.
|
||||
*
|
||||
* @return String containing this configuration.
|
||||
*/
|
||||
public abstract String saveToString();
|
||||
|
||||
/**
|
||||
* Loads this {@link com.boydti.fawe.configuration.file.FileConfiguration} from the specified location.
|
||||
* <p>
|
||||
* All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given file.
|
||||
* <p>
|
||||
* If the file cannot be loaded for any reason, an exception will be
|
||||
* thrown.
|
||||
* <p>
|
||||
*
|
||||
* @param file File to load from.
|
||||
* @throws java.io.FileNotFoundException Thrown when the given file cannot be
|
||||
* opened.
|
||||
* @throws java.io.IOException Thrown when the given file cannot be read.
|
||||
* @throws com.boydti.fawe.configuration.InvalidConfigurationException Thrown when the given file is not
|
||||
* a valid Configuration.
|
||||
* @throws IllegalArgumentException Thrown when file is null.
|
||||
*/
|
||||
public void load(File file) throws IOException, InvalidConfigurationException {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("File cannot be null");
|
||||
}
|
||||
|
||||
FileInputStream stream = new FileInputStream(file);
|
||||
|
||||
load(new InputStreamReader(stream, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads this {@link com.boydti.fawe.configuration.file.FileConfiguration} from the specified reader.
|
||||
* <p>
|
||||
* All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given stream.
|
||||
*
|
||||
* @param reader the reader to load from
|
||||
* @throws java.io.IOException thrown when underlying reader throws an IOException
|
||||
* @throws com.boydti.fawe.configuration.InvalidConfigurationException thrown when the reader does not
|
||||
* represent a valid Configuration
|
||||
* @throws IllegalArgumentException thrown when reader is null
|
||||
*/
|
||||
public void load(Reader reader) throws IOException, InvalidConfigurationException {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
try (BufferedReader input = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader)) {
|
||||
String line;
|
||||
|
||||
while ((line = input.readLine()) != null) {
|
||||
builder.append(line);
|
||||
builder.append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
loadFromString(builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads this {@link com.boydti.fawe.configuration.file.FileConfiguration} from the specified location.
|
||||
* <p>
|
||||
* All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given file.
|
||||
* <p>
|
||||
* If the file cannot be loaded for any reason, an exception will be
|
||||
* thrown.
|
||||
*
|
||||
* @param file File to load from.
|
||||
* @throws java.io.FileNotFoundException Thrown when the given file cannot be
|
||||
* opened.
|
||||
* @throws java.io.IOException Thrown when the given file cannot be read.
|
||||
* @throws com.boydti.fawe.configuration.InvalidConfigurationException Thrown when the given file is not
|
||||
* a valid Configuration.
|
||||
* @throws IllegalArgumentException Thrown when file is null.
|
||||
*/
|
||||
public void load(String file) throws IOException, InvalidConfigurationException {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("File cannot be null");
|
||||
}
|
||||
|
||||
load(new File(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads this {@link com.boydti.fawe.configuration.file.FileConfiguration} from the specified string, as
|
||||
* opposed to from file.
|
||||
* <p>
|
||||
* All the values contained within this configuration will be removed,
|
||||
* leaving only settings and defaults, and the new values will be loaded
|
||||
* from the given string.
|
||||
* <p>
|
||||
* If the string is invalid in any way, an exception will be thrown.
|
||||
*
|
||||
* @param contents Contents of a Configuration to load.
|
||||
* @throws com.boydti.fawe.configuration.InvalidConfigurationException Thrown if the specified string is
|
||||
* invalid.
|
||||
* @throws IllegalArgumentException Thrown if contents is null.
|
||||
*/
|
||||
public abstract void loadFromString(String contents) throws InvalidConfigurationException;
|
||||
|
||||
/**
|
||||
* Compiles the header for this {@link com.boydti.fawe.configuration.file.FileConfiguration} and returns the
|
||||
* result.
|
||||
* <p>
|
||||
* This will use the header from {@link #options()} -> {@link
|
||||
* com.boydti.fawe.configuration.file.FileConfigurationOptions#header()}, respecting the rules of {@link
|
||||
* com.boydti.fawe.configuration.file.FileConfigurationOptions#copyHeader()} if set.
|
||||
*
|
||||
* @return Compiled header
|
||||
*/
|
||||
protected abstract String buildHeader();
|
||||
|
||||
@Override
|
||||
public FileConfigurationOptions options() {
|
||||
if (this.options == null) {
|
||||
this.options = new FileConfigurationOptions(this);
|
||||
}
|
||||
|
||||
return (FileConfigurationOptions) this.options;
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package com.boydti.fawe.configuration.file;
|
||||
|
||||
import com.boydti.fawe.configuration.MemoryConfiguration;
|
||||
import com.boydti.fawe.configuration.MemoryConfigurationOptions;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* com.boydti.fawe.configuration.file.FileConfiguration}
|
||||
*/
|
||||
public class FileConfigurationOptions extends MemoryConfigurationOptions {
|
||||
private String header = null;
|
||||
private boolean copyHeader = true;
|
||||
|
||||
protected FileConfigurationOptions(final MemoryConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.FileConfiguration configuration() {
|
||||
return (com.boydti.fawe.configuration.file.FileConfiguration) super.configuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.FileConfigurationOptions copyDefaults(final boolean value) {
|
||||
super.copyDefaults(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.FileConfigurationOptions pathSeparator(final char value) {
|
||||
super.pathSeparator(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the header that will be applied to the top of the saved output.
|
||||
* <p>
|
||||
* This header will be commented out and applied directly at the top of
|
||||
* the generated output of the {@link com.boydti.fawe.configuration.file.FileConfiguration}. It is not
|
||||
* required to include a newline at the end of the header as it will
|
||||
* automatically be applied, but you may include one if you wish for extra
|
||||
* spacing.
|
||||
* <p>
|
||||
* Null is a valid value which will indicate that no header is to be
|
||||
* applied. The default value is null.
|
||||
*
|
||||
* @return Header
|
||||
*/
|
||||
public String header() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the header that will be applied to the top of the saved output.
|
||||
* <p>
|
||||
* This header will be commented out and applied directly at the top of
|
||||
* the generated output of the {@link com.boydti.fawe.configuration.file.FileConfiguration}. It is not
|
||||
* required to include a newline at the end of the header as it will
|
||||
* automatically be applied, but you may include one if you wish for extra
|
||||
* spacing.
|
||||
* <p>
|
||||
* Null is a valid value which will indicate that no header is to be
|
||||
* applied.
|
||||
*
|
||||
* @param value New header
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public com.boydti.fawe.configuration.file.FileConfigurationOptions header(final String value) {
|
||||
header = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether or not the header should be copied from a default source.
|
||||
* <p>
|
||||
* If this is true, if a default {@link com.boydti.fawe.configuration.file.FileConfiguration} is passed to
|
||||
* {@link
|
||||
* com.boydti.fawe.configuration.file.FileConfiguration#setDefaults(com.boydti.fawe.configuration.Configuration)}
|
||||
* then upon saving it will use the header from that config, instead of
|
||||
* the one provided here.
|
||||
* <p>
|
||||
* If no default is set on the configuration, or the default is not of
|
||||
* type FileConfiguration, or that config has no header ({@link #header()}
|
||||
* returns null) then the header specified in this configuration will be
|
||||
* used.
|
||||
* <p>
|
||||
* Defaults to true.
|
||||
*
|
||||
* @return Whether or not to copy the header
|
||||
*/
|
||||
public boolean copyHeader() {
|
||||
return copyHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the header should be copied from a default source.
|
||||
* <p>
|
||||
* If this is true, if a default {@link com.boydti.fawe.configuration.file.FileConfiguration} is passed to
|
||||
* {@link
|
||||
* com.boydti.fawe.configuration.file.FileConfiguration#setDefaults(com.boydti.fawe.configuration.Configuration)}
|
||||
* then upon saving it will use the header from that config, instead of
|
||||
* the one provided here.
|
||||
* <p>
|
||||
* If no default is set on the configuration, or the default is not of
|
||||
* type FileConfiguration, or that config has no header ({@link #header()}
|
||||
* returns null) then the header specified in this configuration will be
|
||||
* used.
|
||||
* <p>
|
||||
* Defaults to true.
|
||||
*
|
||||
* @param value Whether or not to copy the header
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public com.boydti.fawe.configuration.file.FileConfigurationOptions copyHeader(final boolean value) {
|
||||
copyHeader = value;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
package com.boydti.fawe.configuration.file;
|
||||
|
||||
import com.boydti.fawe.configuration.Configuration;
|
||||
import com.boydti.fawe.configuration.ConfigurationSection;
|
||||
import com.boydti.fawe.configuration.InvalidConfigurationException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Map;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
/**
|
||||
* An implementation of {@link com.boydti.fawe.configuration.Configuration} which saves all files in Yaml.
|
||||
* Note that this implementation is not synchronized.
|
||||
*/
|
||||
public class YamlConfiguration extends FileConfiguration {
|
||||
protected static final String COMMENT_PREFIX = "# ";
|
||||
protected static final String BLANK_CONFIG = "{}\n";
|
||||
private final DumperOptions yamlOptions = new DumperOptions();
|
||||
private final Representer yamlRepresenter = new YamlRepresenter();
|
||||
private final Yaml yaml = new Yaml(new YamlConstructor(), yamlRepresenter, yamlOptions);
|
||||
|
||||
/**
|
||||
* Creates a new {@link com.boydti.fawe.configuration.file.YamlConfiguration}, loading from the given file.
|
||||
* <p>
|
||||
* Any errors loading the Configuration will be logged and then ignored.
|
||||
* If the specified input is not a valid config, a blank config will be
|
||||
* returned.
|
||||
* <p>
|
||||
* The encoding used may follow the system dependent default.
|
||||
*
|
||||
* @param file Input file
|
||||
* @return Resulting configuration
|
||||
* @throws IllegalArgumentException Thrown if file is null
|
||||
*/
|
||||
public static com.boydti.fawe.configuration.file.YamlConfiguration loadConfiguration(final File file) {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("File cannot be null");
|
||||
}
|
||||
|
||||
final com.boydti.fawe.configuration.file.YamlConfiguration config = new com.boydti.fawe.configuration.file.YamlConfiguration();
|
||||
|
||||
try {
|
||||
config.load(file);
|
||||
} catch (InvalidConfigurationException | IOException ex) {
|
||||
try {
|
||||
file.getAbsolutePath();
|
||||
File dest = new File(file.getAbsolutePath() + "_broken");
|
||||
int i = 0;
|
||||
while (dest.exists()) {
|
||||
dest = new File(file.getAbsolutePath() + "_broken_" + i++);
|
||||
}
|
||||
Files.copy(file.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
System.out.println("&dCould not read: &7" + file);
|
||||
System.out.println("&dRenamed to: &7" + dest.getName());
|
||||
System.out.println("&c============ Full stacktrace ============");
|
||||
ex.printStackTrace();
|
||||
System.out.println("&c=========================================");
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link com.boydti.fawe.configuration.file.YamlConfiguration}, loading from the given reader.
|
||||
* <p>
|
||||
* Any errors loading the Configuration will be logged and then ignored.
|
||||
* If the specified input is not a valid config, a blank config will be
|
||||
* returned.
|
||||
*
|
||||
* @param reader input
|
||||
* @return resulting configuration
|
||||
* @throws IllegalArgumentException Thrown if stream is null
|
||||
*/
|
||||
public static com.boydti.fawe.configuration.file.YamlConfiguration loadConfiguration(final Reader reader) {
|
||||
if (reader == null) {
|
||||
throw new NullPointerException("Reader cannot be null");
|
||||
}
|
||||
|
||||
final com.boydti.fawe.configuration.file.YamlConfiguration config = new com.boydti.fawe.configuration.file.YamlConfiguration();
|
||||
|
||||
try {
|
||||
config.load(reader);
|
||||
} catch (final IOException | InvalidConfigurationException ex) {
|
||||
System.out.println("Cannot load configuration from stream");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String saveToString() {
|
||||
yamlOptions.setIndent(options().indent());
|
||||
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
|
||||
final String header = buildHeader();
|
||||
String dump = yaml.dump(getValues(false));
|
||||
|
||||
if (dump.equals(BLANK_CONFIG)) {
|
||||
dump = "";
|
||||
}
|
||||
|
||||
return header + dump;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFromString(final String contents) throws InvalidConfigurationException {
|
||||
if (contents == null) {
|
||||
throw new NullPointerException("Contents cannot be null");
|
||||
}
|
||||
|
||||
Map<?, ?> input;
|
||||
try {
|
||||
input = (Map<?, ?>) yaml.load(contents);
|
||||
} catch (final YAMLException e) {
|
||||
throw new InvalidConfigurationException(e);
|
||||
} catch (final ClassCastException e) {
|
||||
throw new InvalidConfigurationException("Top level is not a Map.");
|
||||
}
|
||||
|
||||
final String header = parseHeader(contents);
|
||||
if (!header.isEmpty()) {
|
||||
options().header(header);
|
||||
}
|
||||
|
||||
if (input != null) {
|
||||
convertMapsToSections(input, this);
|
||||
}
|
||||
}
|
||||
|
||||
protected void convertMapsToSections(final Map<?, ?> input, final ConfigurationSection section) {
|
||||
for (final Map.Entry<?, ?> entry : input.entrySet()) {
|
||||
final String key = entry.getKey().toString();
|
||||
final Object value = entry.getValue();
|
||||
|
||||
if (value instanceof Map) {
|
||||
convertMapsToSections((Map<?, ?>) value, section.createSection(key));
|
||||
} else {
|
||||
section.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected String parseHeader(final String input) {
|
||||
final String[] lines = input.split("\r?\n", -1);
|
||||
final StringBuilder result = new StringBuilder();
|
||||
boolean readingHeader = true;
|
||||
boolean foundHeader = false;
|
||||
|
||||
for (int i = 0; (i < lines.length) && readingHeader; i++) {
|
||||
final String line = lines[i];
|
||||
|
||||
if (line.startsWith(COMMENT_PREFIX)) {
|
||||
if (i > 0) {
|
||||
result.append("\n");
|
||||
}
|
||||
|
||||
if (line.length() > COMMENT_PREFIX.length()) {
|
||||
result.append(line.substring(COMMENT_PREFIX.length()));
|
||||
}
|
||||
|
||||
foundHeader = true;
|
||||
} else if (foundHeader && line.isEmpty()) {
|
||||
result.append("\n");
|
||||
} else if (foundHeader) {
|
||||
readingHeader = false;
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String buildHeader() {
|
||||
final String header = options().header();
|
||||
|
||||
if (options().copyHeader()) {
|
||||
final Configuration def = getDefaults();
|
||||
|
||||
if (def != null && def instanceof FileConfiguration) {
|
||||
final FileConfiguration filedefaults = (FileConfiguration) def;
|
||||
final String defaultsHeader = filedefaults.buildHeader();
|
||||
|
||||
if ((defaultsHeader != null) && !defaultsHeader.isEmpty()) {
|
||||
return defaultsHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final String[] lines = header.split("\r?\n", -1);
|
||||
boolean startedHeader = false;
|
||||
|
||||
for (int i = lines.length - 1; i >= 0; i--) {
|
||||
builder.insert(0, "\n");
|
||||
|
||||
if (startedHeader || !lines[i].isEmpty()) {
|
||||
builder.insert(0, lines[i]);
|
||||
builder.insert(0, COMMENT_PREFIX);
|
||||
startedHeader = true;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlConfigurationOptions options() {
|
||||
if (options == null) {
|
||||
options = new YamlConfigurationOptions(this);
|
||||
}
|
||||
|
||||
return (YamlConfigurationOptions) options;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.boydti.fawe.configuration.file;
|
||||
|
||||
import com.boydti.fawe.configuration.file.FileConfigurationOptions;
|
||||
import com.boydti.fawe.configuration.file.YamlConfiguration;
|
||||
|
||||
/**
|
||||
* Various settings for controlling the input and output of a {@link
|
||||
* com.boydti.fawe.configuration.file.YamlConfiguration}
|
||||
*/
|
||||
public class YamlConfigurationOptions extends FileConfigurationOptions {
|
||||
private int indent = 2;
|
||||
|
||||
protected YamlConfigurationOptions(final YamlConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlConfiguration configuration() {
|
||||
return (YamlConfiguration) super.configuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.YamlConfigurationOptions copyDefaults(final boolean value) {
|
||||
super.copyDefaults(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.YamlConfigurationOptions pathSeparator(final char value) {
|
||||
super.pathSeparator(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.YamlConfigurationOptions header(final String value) {
|
||||
super.header(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.boydti.fawe.configuration.file.YamlConfigurationOptions copyHeader(final boolean value) {
|
||||
super.copyHeader(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets how much spaces should be used to indent each line.
|
||||
* <p>
|
||||
* The minimum value this may be is 2, and the maximum is 9.
|
||||
*
|
||||
* @return How much to indent by
|
||||
*/
|
||||
public int indent() {
|
||||
return indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how much spaces should be used to indent each line.
|
||||
* <p>
|
||||
* The minimum value this may be is 2, and the maximum is 9.
|
||||
*
|
||||
* @param value New indent
|
||||
* @return This object, for chaining
|
||||
*/
|
||||
public com.boydti.fawe.configuration.file.YamlConfigurationOptions indent(final int value) {
|
||||
if (value < 2) {
|
||||
throw new IllegalArgumentException("Indent must be at least 2 characters");
|
||||
}
|
||||
if (value > 9) {
|
||||
throw new IllegalArgumentException("Indent cannot be greater than 9 characters");
|
||||
}
|
||||
|
||||
indent = value;
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.boydti.fawe.configuration.file;
|
||||
|
||||
import com.boydti.fawe.configuration.serialization.ConfigurationSerialization;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.yaml.snakeyaml.constructor.SafeConstructor;
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
|
||||
public class YamlConstructor extends SafeConstructor {
|
||||
|
||||
public YamlConstructor() {
|
||||
yamlConstructors.put(Tag.MAP, new ConstructCustomObject());
|
||||
}
|
||||
|
||||
private class ConstructCustomObject extends ConstructYamlMap {
|
||||
@Override
|
||||
public Object construct(final Node node) {
|
||||
if (node.isTwoStepsConstruction()) {
|
||||
throw new YAMLException("Unexpected referential mapping structure. Node: " + node);
|
||||
}
|
||||
|
||||
final Map<?, ?> raw = (Map<?, ?>) super.construct(node);
|
||||
|
||||
if (raw.containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY)) {
|
||||
final Map<String, Object> typed = new LinkedHashMap<>(raw.size());
|
||||
for (final Map.Entry<?, ?> entry : raw.entrySet()) {
|
||||
typed.put(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
|
||||
try {
|
||||
return ConfigurationSerialization.deserializeObject(typed);
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
throw new YAMLException("Could not deserialize object", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void construct2ndStep(final Node node, final Object object) {
|
||||
throw new YAMLException("Unexpected referential mapping structure. Node: " + node);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.boydti.fawe.configuration.file;
|
||||
|
||||
import com.boydti.fawe.configuration.ConfigurationSection;
|
||||
import com.boydti.fawe.configuration.serialization.ConfigurationSerializable;
|
||||
import com.boydti.fawe.configuration.serialization.ConfigurationSerialization;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.yaml.snakeyaml.nodes.Node;
|
||||
import org.yaml.snakeyaml.representer.Representer;
|
||||
|
||||
public class YamlRepresenter extends Representer {
|
||||
|
||||
public YamlRepresenter() {
|
||||
this.multiRepresenters.put(ConfigurationSection.class, new RepresentConfigurationSection());
|
||||
this.multiRepresenters.put(ConfigurationSerializable.class, new RepresentConfigurationSerializable());
|
||||
}
|
||||
|
||||
private class RepresentConfigurationSection extends RepresentMap {
|
||||
|
||||
@Override
|
||||
public Node representData(Object data) {
|
||||
return super.representData(((ConfigurationSection) data).getValues(false));
|
||||
}
|
||||
}
|
||||
|
||||
private class RepresentConfigurationSerializable extends RepresentMap {
|
||||
|
||||
@Override
|
||||
public Node representData(Object data) {
|
||||
ConfigurationSerializable serializable = (ConfigurationSerializable) data;
|
||||
Map<String, Object> values = new LinkedHashMap<>();
|
||||
values.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY, ConfigurationSerialization.getAlias(serializable.getClass()));
|
||||
values.putAll(serializable.serialize());
|
||||
|
||||
return super.representData(values);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.boydti.fawe.configuration.serialization;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents an object that may be serialized.
|
||||
* <p>
|
||||
* These objects MUST implement one of the following, in addition to the
|
||||
* methods as defined by this interface:
|
||||
* <ul>
|
||||
* <li>A static method "deserialize" that accepts a single {@link java.util.Map}<
|
||||
* {@link String}, {@link Object}> and returns the class.</li>
|
||||
* <li>A static method "valueOf" that accepts a single {@link java.util.Map}<{@link
|
||||
* String}, {@link Object}> and returns the class.</li>
|
||||
* <li>A constructor that accepts a single {@link java.util.Map}<{@link String},
|
||||
* {@link Object}>.</li>
|
||||
* </ul>
|
||||
* In addition to implementing this interface, you must register the class
|
||||
* with {@link com.boydti.fawe.configuration.serialization.ConfigurationSerialization#registerClass(Class)}.
|
||||
*
|
||||
* @see com.boydti.fawe.configuration.serialization.DelegateDeserialization
|
||||
* @see com.boydti.fawe.configuration.serialization.SerializableAs
|
||||
*/
|
||||
public interface ConfigurationSerializable {
|
||||
|
||||
/**
|
||||
* Creates a Map representation of this class.
|
||||
* <p>
|
||||
* This class must provide a method to restore this class, as defined in
|
||||
* the {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} interface javadoc.
|
||||
*
|
||||
* @return Map containing the current state of this class
|
||||
*/
|
||||
Map<String, Object> serialize();
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
package com.boydti.fawe.configuration.serialization;
|
||||
|
||||
import com.boydti.fawe.configuration.serialization.DelegateDeserialization;
|
||||
import com.boydti.fawe.configuration.serialization.SerializableAs;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Utility class for storing and retrieving classes for {@link com.boydti.fawe.configuration.Configuration}.
|
||||
*/
|
||||
public class ConfigurationSerialization {
|
||||
|
||||
public static final String SERIALIZED_TYPE_KEY = "==";
|
||||
private static final Map<String, Class<? extends ConfigurationSerializable>> aliases =
|
||||
new HashMap<String, Class<? extends ConfigurationSerializable>>();
|
||||
private final Class<? extends ConfigurationSerializable> clazz;
|
||||
|
||||
protected ConfigurationSerialization(Class<? extends ConfigurationSerializable> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to deserialize the given arguments into a new instance of the
|
||||
* given class.
|
||||
*
|
||||
* <p>The class must implement {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}, including
|
||||
* the extra methods as specified in the javadoc of
|
||||
* ConfigurationSerializable.</p>
|
||||
*
|
||||
* <p>If a new instance could not be made, an example being the class not
|
||||
* fully implementing the interface, null will be returned.</p>
|
||||
*
|
||||
* @param args Arguments for deserialization
|
||||
* @param clazz Class to deserialize into
|
||||
* @return New instance of the specified class
|
||||
*/
|
||||
public static ConfigurationSerializable deserializeObject(Map<String, ?> args, Class<? extends ConfigurationSerializable> clazz) {
|
||||
return new com.boydti.fawe.configuration.serialization.ConfigurationSerialization(clazz).deserialize(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to deserialize the given arguments into a new instance of the
|
||||
*
|
||||
* given class.
|
||||
* <p>
|
||||
* The class must implement {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}, including
|
||||
* the extra methods as specified in the javadoc of
|
||||
* ConfigurationSerializable.</p>
|
||||
*
|
||||
* <p>
|
||||
* If a new instance could not be made, an example being the class not
|
||||
* fully implementing the interface, null will be returned.</p>
|
||||
*
|
||||
* @param args Arguments for deserialization
|
||||
* @return New instance of the specified class
|
||||
*/
|
||||
public static ConfigurationSerializable deserializeObject(Map<String, ?> args) {
|
||||
Class<? extends ConfigurationSerializable> clazz = null;
|
||||
|
||||
if (args.containsKey(SERIALIZED_TYPE_KEY)) {
|
||||
try {
|
||||
String alias = (String) args.get(SERIALIZED_TYPE_KEY);
|
||||
|
||||
if (alias == null) {
|
||||
throw new IllegalArgumentException("Cannot have null alias");
|
||||
}
|
||||
clazz = getClassByAlias(alias);
|
||||
if (clazz == null) {
|
||||
throw new IllegalArgumentException("Specified class does not exist ('" + alias + "')");
|
||||
}
|
||||
} catch (ClassCastException ex) {
|
||||
ex.fillInStackTrace();
|
||||
throw ex;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Args doesn't contain type key ('" + SERIALIZED_TYPE_KEY + "')");
|
||||
}
|
||||
|
||||
return new com.boydti.fawe.configuration.serialization.ConfigurationSerialization(clazz).deserialize(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class by its
|
||||
* alias.
|
||||
*
|
||||
* @param clazz Class to register
|
||||
*/
|
||||
public static void registerClass(Class<? extends ConfigurationSerializable> clazz) {
|
||||
com.boydti.fawe.configuration.serialization.DelegateDeserialization delegate = clazz.getAnnotation(com.boydti.fawe.configuration.serialization.DelegateDeserialization.class);
|
||||
|
||||
if (delegate == null) {
|
||||
registerClass(clazz, getAlias(clazz));
|
||||
registerClass(clazz, clazz.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given alias to the specified {@link
|
||||
* com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class.
|
||||
*
|
||||
* @param clazz Class to register
|
||||
* @param alias Alias to register as
|
||||
* @see com.boydti.fawe.configuration.serialization.SerializableAs
|
||||
*/
|
||||
public static void registerClass(Class<? extends ConfigurationSerializable> clazz, String alias) {
|
||||
aliases.put(alias, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the specified alias to a {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}
|
||||
*
|
||||
* @param alias Alias to unregister
|
||||
*/
|
||||
public static void unregisterClass(String alias) {
|
||||
aliases.remove(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters any aliases for the specified {@link
|
||||
* com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class.
|
||||
*
|
||||
* @param clazz Class to unregister
|
||||
*/
|
||||
public static void unregisterClass(Class<? extends ConfigurationSerializable> clazz) {
|
||||
while (aliases.values().remove(clazz)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get a registered {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class by
|
||||
* its alias.
|
||||
*
|
||||
* @param alias Alias of the serializable
|
||||
* @return Registered class, or null if not found
|
||||
*/
|
||||
public static Class<? extends ConfigurationSerializable> getClassByAlias(String alias) {
|
||||
return aliases.get(alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correct alias for the given {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}
|
||||
* class.
|
||||
*
|
||||
* @param clazz Class to get alias for
|
||||
* @return Alias to use for the class
|
||||
*/
|
||||
public static String getAlias(Class<? extends ConfigurationSerializable> clazz) {
|
||||
com.boydti.fawe.configuration.serialization.DelegateDeserialization delegate = clazz.getAnnotation(DelegateDeserialization.class);
|
||||
|
||||
if (delegate != null) {
|
||||
if ((delegate.value() == null) || (delegate.value() == clazz)) {
|
||||
delegate = null;
|
||||
} else {
|
||||
return getAlias(delegate.value());
|
||||
}
|
||||
}
|
||||
|
||||
SerializableAs alias = clazz.getAnnotation(SerializableAs.class);
|
||||
|
||||
if (alias != null) {
|
||||
return alias.value();
|
||||
}
|
||||
|
||||
return clazz.getName();
|
||||
}
|
||||
|
||||
protected Method getMethod(String name, boolean isStatic) {
|
||||
try {
|
||||
Method method = this.clazz.getDeclaredMethod(name, Map.class);
|
||||
|
||||
if (!ConfigurationSerializable.class.isAssignableFrom(method.getReturnType())) {
|
||||
return null;
|
||||
}
|
||||
if (Modifier.isStatic(method.getModifiers()) != isStatic) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return method;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
} catch (SecurityException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Constructor<? extends ConfigurationSerializable> getConstructor() {
|
||||
try {
|
||||
return this.clazz.getConstructor(Map.class);
|
||||
} catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
} catch (SecurityException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected ConfigurationSerializable deserializeViaMethod(Method method, Map<String, ?> args) {
|
||||
try {
|
||||
ConfigurationSerializable result = (ConfigurationSerializable) method.invoke(null, args);
|
||||
|
||||
if (result == null) {
|
||||
Logger.getLogger(com.boydti.fawe.configuration.serialization.ConfigurationSerialization.class.getName()).log(Level.SEVERE,
|
||||
"Could not call method '" + method.toString() + "' of " + this.clazz + " for deserialization: method returned null");
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(com.boydti.fawe.configuration.serialization.ConfigurationSerialization.class.getName())
|
||||
.log(Level.SEVERE, "Could not call method '" + method.toString() + "' of " + this.clazz
|
||||
+ " for deserialization",
|
||||
ex instanceof InvocationTargetException ? ex.getCause() : ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ConfigurationSerializable deserializeViaCtor(Constructor<? extends ConfigurationSerializable> ctor, Map<String, ?> args) {
|
||||
try {
|
||||
return ctor.newInstance(args);
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(com.boydti.fawe.configuration.serialization.ConfigurationSerialization.class.getName())
|
||||
.log(Level.SEVERE, "Could not call constructor '" + ctor.toString() + "' of " + this.clazz
|
||||
+ " for deserialization",
|
||||
ex instanceof InvocationTargetException ? ex.getCause() : ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ConfigurationSerializable deserialize(Map<String, ?> args) {
|
||||
if (args == null) {
|
||||
throw new NullPointerException("Args must not be null");
|
||||
}
|
||||
ConfigurationSerializable result = null;
|
||||
Method method = getMethod("deserialize", true);
|
||||
|
||||
if (method != null) {
|
||||
result = deserializeViaMethod(method, args);
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
method = getMethod("valueOf", true);
|
||||
|
||||
if (method != null) {
|
||||
result = deserializeViaMethod(method, args);
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
Constructor<? extends ConfigurationSerializable> constructor = getConstructor();
|
||||
|
||||
if (constructor != null) {
|
||||
result = deserializeViaCtor(constructor, args);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.boydti.fawe.configuration.serialization;
|
||||
|
||||
import com.boydti.fawe.configuration.serialization.ConfigurationSerializable;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Applies to a {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} that will delegate all
|
||||
* deserialization to another {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface DelegateDeserialization {
|
||||
/**
|
||||
* Which class should be used as a delegate for this classes
|
||||
* deserialization
|
||||
*
|
||||
* @return Delegate class
|
||||
*/
|
||||
Class<? extends ConfigurationSerializable> value();
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.boydti.fawe.configuration.serialization;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Represents an "alias" that a {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} may be
|
||||
* stored as.
|
||||
* If this is not present on a {@link com.boydti.fawe.configuration.serialization.ConfigurationSerializable} class, it
|
||||
* will use the fully qualified name of the class.
|
||||
* <p>
|
||||
* This value will be stored in the configuration so that the configuration
|
||||
* deserialization can determine what type it is.
|
||||
* <p>
|
||||
* Using this annotation on any other class than a {@link
|
||||
* com.boydti.fawe.configuration.serialization.ConfigurationSerializable} will have no effect.
|
||||
*
|
||||
* @see com.boydti.fawe.configuration.serialization.ConfigurationSerialization#registerClass(Class, String)
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface SerializableAs {
|
||||
/**
|
||||
* This is the name your class will be stored and retrieved as.
|
||||
* <p>
|
||||
* This name MUST be unique. We recommend using names such as
|
||||
* "MyPluginThing" instead of "Thing".
|
||||
*
|
||||
* @return Name to serialize the class as.
|
||||
*/
|
||||
String value();
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
|
||||
public class EditSessionWrapper {
|
||||
|
||||
@ -26,7 +26,7 @@ public class EditSessionWrapper {
|
||||
return minY;
|
||||
}
|
||||
|
||||
public Extent getHistoryExtent(final Extent parent, final ChangeSet set, final FawePlayer<?> player) {
|
||||
public Extent getHistoryExtent(final Extent parent, FaweChangeSet set, final FawePlayer<?> player) {
|
||||
return new HistoryExtent(parent, set);
|
||||
}
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
|
||||
public class FaweChangeSet implements ChangeSet {
|
||||
|
||||
private final ArrayDeque<Change> changes = new ArrayDeque<>();
|
||||
|
||||
@Override
|
||||
public void add(final Change change) {
|
||||
if (change.getClass() == BlockChange.class) {
|
||||
final BlockChange bc = (BlockChange) change;
|
||||
bc.getCurrent();
|
||||
// BaseBlock previous = bc.getPrevious();
|
||||
// BlockVector pos = bc.getPosition();
|
||||
// int x = pos.getBlockX();
|
||||
// int y = pos.getBlockY();
|
||||
// int z = pos.getBlockZ();
|
||||
this.changes.add(bc);
|
||||
} else {
|
||||
this.changes.add(change);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> backwardIterator() {
|
||||
return this.changes.descendingIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Change> forwardIterator() {
|
||||
return this.changes.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.changes.size();
|
||||
}
|
||||
}
|
@ -11,18 +11,25 @@ import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public abstract class FawePlayer<T> {
|
||||
|
||||
public final T parent;
|
||||
private LocalSession session;
|
||||
|
||||
/**
|
||||
* The metadata map.
|
||||
*/
|
||||
private ConcurrentHashMap<String, Object> meta;
|
||||
|
||||
public static <T> FawePlayer<T> wrap(final Object obj) {
|
||||
return Fawe.imp().wrap(obj);
|
||||
}
|
||||
|
||||
public FawePlayer(final T parent) {
|
||||
this.parent = parent;
|
||||
Fawe.get().register(this);
|
||||
}
|
||||
|
||||
public abstract String getName();
|
||||
@ -84,4 +91,51 @@ public abstract class FawePlayer<T> {
|
||||
public boolean hasWorldEditBypass() {
|
||||
return this.hasPermission("fawe.bypass");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some session only metadata for the player
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public void setMeta(String key, Object value) {
|
||||
if (this.meta == null) {
|
||||
this.meta = new ConcurrentHashMap<>();
|
||||
}
|
||||
this.meta.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metadata for a key.
|
||||
* @param <T>
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public <T> T getMeta(String key) {
|
||||
if (this.meta != null) {
|
||||
return (T) this.meta.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public <T> T getMeta(String key, T def) {
|
||||
if (this.meta != null) {
|
||||
T value = (T) this.meta.get(key);
|
||||
return value == null ? def : value;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the metadata for a key.
|
||||
* - metadata is session only
|
||||
* - deleting other plugin's metadata may cause issues
|
||||
* @param key
|
||||
*/
|
||||
public Object deleteMeta(String key) {
|
||||
return this.meta == null ? null : this.meta.remove(key);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
Fawe.get().unregister(getName());
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,7 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
@ -14,28 +9,32 @@ import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Stores changes to a {@link ChangeSet}.
|
||||
*/
|
||||
public class HistoryExtent extends AbstractDelegateExtent {
|
||||
|
||||
private final ChangeSet changeSet;
|
||||
private final com.boydti.fawe.object.changeset.FaweChangeSet changeSet;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param changeSet the change set
|
||||
* @param thread
|
||||
*/
|
||||
public HistoryExtent(final Extent extent, final ChangeSet changeSet) {
|
||||
public HistoryExtent(final Extent extent, final FaweChangeSet changeSet) {
|
||||
super(extent);
|
||||
checkNotNull(changeSet);
|
||||
this.changeSet = changeSet;
|
||||
@ -53,95 +52,15 @@ public class HistoryExtent extends AbstractDelegateExtent {
|
||||
final int id_p = previous.getId();
|
||||
final int id_b = block.getId();
|
||||
if (id_p == id_b) {
|
||||
switch (id_p) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 25:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 54:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 73:
|
||||
case 74:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 117:
|
||||
case 121:
|
||||
case 122:
|
||||
case 123:
|
||||
case 124:
|
||||
case 129:
|
||||
case 133:
|
||||
case 138:
|
||||
case 137:
|
||||
case 140:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 176:
|
||||
case 177:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
if (FaweCache.hasData(id_p)) {
|
||||
if (previous.getData() == block.getData()) {
|
||||
return false;
|
||||
default:
|
||||
if (block.getData() == previous.getData()) {
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.changeSet.add(new BlockChange(location.toBlockVector(), previous, block));
|
||||
this.changeSet.add(location, previous, block);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1,12 +1,13 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
|
||||
public class NullChangeSet implements ChangeSet {
|
||||
public class NullChangeSet implements FaweChangeSet {
|
||||
|
||||
@Override
|
||||
public void add(Change change) {}
|
||||
@ -26,4 +27,9 @@ public class NullChangeSet implements ChangeSet {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {}
|
||||
|
||||
@Override
|
||||
public void add(Vector location, BaseBlock from, BaseBlock to) {}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.sk89q.worldedit.history.changeset.BlockOptimizedHistory;
|
||||
|
||||
/**
|
||||
* History optimized for speed
|
||||
* - Low CPU usage
|
||||
* - High memory usage
|
||||
* - No disk usage
|
||||
*/
|
||||
public class CPUOptimizedHistory extends BlockOptimizedHistory {
|
||||
|
||||
}
|
@ -1,18 +1,5 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
@ -25,12 +12,25 @@ import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.change.EntityCreate;
|
||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* Store the change on disk
|
||||
@ -39,7 +39,7 @@ import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
* - Minimal memory usage
|
||||
* - Slow
|
||||
*/
|
||||
public class DiskStorageHistory implements ChangeSet, FlushableChangeSet {
|
||||
public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
|
||||
|
||||
private final File bdFile;
|
||||
private final File nbtfFile;
|
||||
@ -108,7 +108,7 @@ public class DiskStorageHistory implements ChangeSet, FlushableChangeSet {
|
||||
if ((change instanceof BlockChange)) {
|
||||
add((BlockChange) change);
|
||||
} else {
|
||||
System.out.print("[FAWE] Does not support " + change + " yet! (Please bug Empire92)");
|
||||
Fawe.debug("[FAWE] Does not support " + change + " yet! (Please bug Empire92)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,24 +137,13 @@ public class DiskStorageHistory implements ChangeSet, FlushableChangeSet {
|
||||
}
|
||||
}
|
||||
|
||||
public void add(EntityCreate change) {
|
||||
|
||||
@Override
|
||||
public void add(Vector location, BaseBlock from, BaseBlock to) {
|
||||
add(location.getBlockX(), location.getBlockY(), location.getBlockZ(), from, to);
|
||||
}
|
||||
|
||||
public void add(EntityRemove change) {
|
||||
|
||||
}
|
||||
|
||||
public void add(BlockChange change) {
|
||||
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
|
||||
try {
|
||||
BlockVector loc = change.getPosition();
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
|
||||
int idfrom = from.getId();
|
||||
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
|
||||
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
|
||||
@ -200,6 +189,28 @@ public class DiskStorageHistory implements ChangeSet, FlushableChangeSet {
|
||||
}
|
||||
}
|
||||
|
||||
public void add(EntityCreate change) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void add(EntityRemove change) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void add(BlockChange change) {
|
||||
try {
|
||||
BlockVector loc = change.getPosition();
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
add(x, y, z, from, to);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private OutputStream getBAOS(int x, int y, int z) throws IOException {
|
||||
if (osBD != null) {
|
||||
return osBD;
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
|
||||
public interface FaweChangeSet extends ChangeSet {
|
||||
void flush();
|
||||
|
||||
void add(Vector location, BaseBlock from, BaseBlock to);
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
public interface FlushableChangeSet {
|
||||
public void flush();
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.object.changeset;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@ -33,7 +34,7 @@ import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
* - High CPU usage
|
||||
* - Low memory usage
|
||||
*/
|
||||
public class MemoryOptimizedHistory implements ChangeSet, FlushableChangeSet {
|
||||
public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
|
||||
|
||||
private ArrayDeque<CompoundTag> fromTags;
|
||||
private ArrayDeque<CompoundTag> toTags;
|
||||
@ -54,19 +55,12 @@ public class MemoryOptimizedHistory implements ChangeSet, FlushableChangeSet {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Change arg) {
|
||||
size.incrementAndGet();
|
||||
if ((arg instanceof BlockChange)) {
|
||||
public void add(Vector location, BaseBlock from, BaseBlock to) {
|
||||
add(location.getBlockX(), location.getBlockY(), location.getBlockZ(), from, to);
|
||||
}
|
||||
|
||||
public void add(int x, int y, int z, BaseBlock from, BaseBlock to) {
|
||||
try {
|
||||
BlockChange change = (BlockChange) arg;
|
||||
BlockVector loc = change.getPosition();
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
|
||||
int idfrom = from.getId();
|
||||
int combinedFrom = (FaweCache.hasData(idfrom) ? ((idfrom << 4) + from.getData()) : (idfrom << 4));
|
||||
CompoundTag nbtFrom = FaweCache.hasNBT(idfrom) ? from.getNbtData() : null;
|
||||
@ -114,6 +108,20 @@ public class MemoryOptimizedHistory implements ChangeSet, FlushableChangeSet {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Change arg) {
|
||||
size.incrementAndGet();
|
||||
if ((arg instanceof BlockChange)) {
|
||||
BlockChange change = (BlockChange) arg;
|
||||
BlockVector loc = change.getPosition();
|
||||
int x = loc.getBlockX();
|
||||
int y = loc.getBlockY();
|
||||
int z = loc.getBlockZ();
|
||||
BaseBlock from = change.getPrevious();
|
||||
BaseBlock to = change.getCurrent();
|
||||
add(x, y, z, from, to);
|
||||
} else {
|
||||
if (entities == null) {
|
||||
entities = new ArrayDeque<>();
|
||||
|
@ -9,6 +9,7 @@ import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class PlotSquaredFeature extends FaweMaskManager {
|
||||
@ -48,14 +49,14 @@ public class PlotSquaredFeature extends FaweMaskManager {
|
||||
RegionWrapper region = plot.getLargestRegion();
|
||||
HashSet<RegionWrapper> regions = plot.getRegions();
|
||||
|
||||
final Location pos1 = new Location(world, region.minX, 0, region.minZ);
|
||||
final Location pos2 = new Location(world, region.maxX, 256, region.maxZ);
|
||||
final BlockVector pos1 = new BlockVector(region.minX, 0, region.minZ);
|
||||
final BlockVector pos2 = new BlockVector(region.maxX, 256, region.maxZ);
|
||||
|
||||
final HashSet<com.boydti.fawe.object.RegionWrapper> faweRegions = new HashSet<com.boydti.fawe.object.RegionWrapper>();
|
||||
for (final com.intellectualcrafters.plot.object.RegionWrapper current : regions) {
|
||||
faweRegions.add(new com.boydti.fawe.object.RegionWrapper(current.minX, current.maxX, current.minZ, current.maxZ));
|
||||
}
|
||||
return new BukkitMask(pos1, pos2) {
|
||||
return new FaweMask(pos1, pos2) {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "PLOT^2:" + id;
|
||||
|
@ -1,18 +1,14 @@
|
||||
package com.boydti.fawe.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.EndTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import java.io.File;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MainUtil {
|
||||
/*
|
||||
@ -20,7 +16,7 @@ public class MainUtil {
|
||||
* e.g. sending messages
|
||||
*/
|
||||
public static void sendMessage(final FawePlayer<?> player, String message) {
|
||||
message = ChatColor.translateAlternateColorCodes('&', message);
|
||||
message = BBC.color(message);
|
||||
if (player == null) {
|
||||
Fawe.debug(message);
|
||||
} else {
|
||||
@ -29,7 +25,7 @@ public class MainUtil {
|
||||
}
|
||||
|
||||
public static void sendAdmin(final String s) {
|
||||
for (final Player player : Bukkit.getOnlinePlayers()) {
|
||||
for (final FawePlayer<?> player : Fawe.imp().getPlayers()) {
|
||||
if (player.hasPermission("fawe.admin")) {
|
||||
player.sendMessage(s);
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
|
||||
@ -32,7 +31,7 @@ public class ReflectionUtils {
|
||||
*/
|
||||
private static boolean forge = false;
|
||||
/** check server version and class names */
|
||||
static {
|
||||
public static void init() {
|
||||
if (Bukkit.getServer() != null) {
|
||||
if (Bukkit.getVersion().contains("MCPC") || Bukkit.getVersion().contains("Forge")) {
|
||||
forge = true;
|
||||
@ -221,6 +220,9 @@ public class ReflectionUtils {
|
||||
* @throws RuntimeException if no class found
|
||||
*/
|
||||
public static RefClass getRefClass(final String... classes) throws RuntimeException {
|
||||
if (preClassM == null) {
|
||||
init();
|
||||
}
|
||||
for (String className : classes) {
|
||||
try {
|
||||
className = className.replace("{cb}", preClassB).replace("{nms}", preClassM).replace("{nm}", "net.minecraft");
|
||||
|
@ -19,25 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
|
||||
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
|
||||
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
@ -47,6 +28,7 @@ import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.NullChangeSet;
|
||||
import com.boydti.fawe.object.RegionWrapper;
|
||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.object.changeset.MemoryOptimizedHistory;
|
||||
import com.boydti.fawe.object.extent.FastWorldEditExtent;
|
||||
import com.boydti.fawe.object.extent.NullExtent;
|
||||
@ -130,6 +112,24 @@ import com.sk89q.worldedit.util.collection.DoubleArrayList;
|
||||
import com.sk89q.worldedit.util.eventbus.EventBus;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
|
||||
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
|
||||
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
|
||||
|
||||
/**
|
||||
* An {@link Extent} that handles history, {@link BlockBag}s, change limits,
|
||||
@ -152,7 +152,7 @@ public class EditSession implements Extent {
|
||||
}
|
||||
|
||||
protected final World world;
|
||||
private final ChangeSet changeSet;
|
||||
private final FaweChangeSet changeSet;
|
||||
private final EditSessionWrapper wrapper;
|
||||
private MultiStageReorder reorderExtent;
|
||||
private @Nullable Extent changeSetExtent;
|
||||
|
@ -19,18 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.boydti.fawe.object.changeset.FlushableChangeSet;
|
||||
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.sk89q.jchronic.Chronic;
|
||||
import com.sk89q.jchronic.Options;
|
||||
import com.sk89q.jchronic.utils.Span;
|
||||
@ -57,6 +46,16 @@ import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Stores session information.
|
||||
@ -200,8 +199,8 @@ public class LocalSession {
|
||||
history.remove(historyPointer);
|
||||
}
|
||||
ChangeSet set = editSession.getChangeSet();
|
||||
if (set instanceof FlushableChangeSet) {
|
||||
((FlushableChangeSet) set).flush();
|
||||
if (set instanceof FaweChangeSet) {
|
||||
((FaweChangeSet) set).flush();
|
||||
}
|
||||
history.add(editSession);
|
||||
while (history.size() > MAX_HISTORY_SIZE) {
|
||||
|
@ -19,16 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.extension.platform;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.google.common.base.Joiner;
|
||||
@ -88,6 +78,16 @@ import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.util.logging.DynamicStreamHandler;
|
||||
import com.sk89q.worldedit.util.logging.LogFormat;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt;
|
||||
|
||||
/**
|
||||
* Handles the registration and invocation of commands.
|
||||
@ -271,12 +271,12 @@ public final class CommandManager {
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushQueue();
|
||||
long time = System.currentTimeMillis() - start;
|
||||
final long time = System.currentTimeMillis() - start;
|
||||
if (time > 5 && editSession.size() != 0) {
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
actor.print("[FAWE] Action complete");
|
||||
actor.print("[FAWE] Action completed in " + (time / 1000d) + " seconds");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
#################################################
|
||||
ForgeGradle 2.1-SNAPSHOT-unknown
|
||||
https://github.com/MinecraftForge/ForgeGradle
|
||||
#################################################
|
||||
Powered by MCP unknown
|
||||
http://modcoderpack.com
|
||||
by: Searge, ProfMobius, Fesh0r,
|
||||
R4wk, ZeuX, IngisKahn, bspkrs
|
||||
#################################################
|
||||
Version string 'unspecified' does not match SemVer specification
|
||||
You should try SemVer : http://semver.org/
|
||||
:forge:deobfCompileDummyTask
|
||||
:core:compileJava
|
||||
:forge:deobfProvidedDummyTask
|
||||
:forge:extractDependencyATs SKIPPED
|
||||
:forge:extractMcpDatawarning: [options] bootstrap class path not set in conjunction with -source 1.7
|
||||
SKIPPED
|
||||
:forge:extractMcpMappings SKIPPED
|
||||
:forge:genSrgs SKIPPED
|
||||
:forge:getVersionJson
|
||||
:forge:downloadServer SKIPPED
|
||||
:forge:splitServerJarNote: Some input files use or override a deprecated API.
|
||||
Note: Recompile with -Xlint:deprecation for details.
|
||||
Note: Some input files use unchecked or unsafe operations.
|
||||
Note: Recompile with -Xlint:unchecked for details.
|
||||
1 warning
|
||||
|
||||
:core:processResources UP-TO-DATE
|
||||
:core:classes
|
||||
:core:jar
|
||||
:forge:splitServerJar SKIPPED
|
||||
:forge:deobfMcMCP SKIPPED
|
||||
:forge:sourceApiJava UP-TO-DATE
|
||||
:forge:compileApiJava UP-TO-DATE
|
||||
:forge:processApiResources UP-TO-DATE
|
||||
:forge:apiClasses UP-TO-DATE
|
||||
:forge:sourceMainJava UP-TO-DATE
|
||||
:forge:compileJavaC:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'modid()' in type 'Mod': class file for net.minecraftforge.fml.common.Mod not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'name()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'version()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptableRemoteVersions()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'dependencies()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptedMinecraftVersions()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'value()' in type 'Instance': class file for net.minecraftforge.fml.common.Mod$Instance not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'serverSide()' in type 'SidedProxy': class file for net.minecraftforge.fml.common.SidedProxy not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'clientSide()' in type 'SidedProxy'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'modid()' in type 'Mod': class file for net.minecraftforge.fml.common.Mod not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'name()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'version()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptableRemoteVersions()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'dependencies()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptedMinecraftVersions()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'value()' in type 'Instance': class file for net.minecraftforge.fml.common.Mod$Instance not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'serverSide()' in type 'SidedProxy': class file for net.minecraftforge.fml.common.SidedProxy not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'clientSide()' in type 'SidedProxy'
|
||||
Note: Writing plugin metadata to file:/C:/Users/Jesse/Desktop/OTHER/GitHub/FastAsyncWorldEdit/forge/build/classes/main/mcmod.info
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'modid()' in type 'Mod': class file for net.minecraftforge.fml.common.Mod not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'name()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'version()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptableRemoteVersions()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'dependencies()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'acceptedMinecraftVersions()' in type 'Mod'
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'value()' in type 'Instance': class file for net.minecraftforge.fml.common.Mod$Instance not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'serverSide()' in type 'SidedProxy': class file for net.minecraftforge.fml.common.SidedProxy not found
|
||||
C:\Users\Jesse\.gradle\caches\modules-2\files-2.1\com.sk89q.worldedit\worldedit-forge-mc1.8.9\6.1.1\dffd7e1882eba256eb2132fe315682c1d26522b1\worldedit-forge-mc1.8.9-6.1.1.jar(com/sk89q/worldedit/forge/ForgeWorldEdit.class): warning: Cannot find annotation method 'clientSide()' in type 'SidedProxy'
|
||||
Note: Some input files use or override a deprecated API.
|
||||
Note: Recompile with -Xlint:deprecation for details.
|
||||
Note: Some input files use unchecked or unsafe operations.
|
||||
Note: Recompile with -Xlint:unchecked for details.
|
||||
27 warnings
|
||||
|
||||
:forge:processResources UP-TO-DATE
|
||||
:forge:classes
|
||||
:forge:jar
|
||||
:forge:sourceTestJava UP-TO-DATE
|
||||
:forge:compileTestJava UP-TO-DATE
|
||||
:forge:processTestResources UP-TO-DATE
|
||||
:forge:testClasses UP-TO-DATE
|
||||
:forge:test UP-TO-DATE
|
||||
:forge:reobfJar
|
||||
:forge:shadowJar
|
||||
:forge:reobfShadowJar
|
||||
:forge:extractRangemapReplacedMain
|
||||
C:\Users\Jesse\Desktop\OTHER\GitHub\FastAsyncWorldEdit\forge\build\sources\main\java
|
||||
:forge:retromapReplacedMain UP-TO-DATE
|
||||
:forge:sourceJar UP-TO-DATE
|
||||
:forge:assemble
|
||||
:forge:check UP-TO-DATE
|
||||
:forge:build
|
||||
|
||||
BUILD SUCCESSFUL
|
||||
|
||||
Total time: 38.081 secs
|
@ -3,44 +3,36 @@ package com.boydti.fawe.forge;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.forge.v0.SpongeEditSessionWrapper_0;
|
||||
import com.boydti.fawe.forge.v1_8.SpongeQueue_1_8;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.google.inject.Inject;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.forge.ForgeWorldEdit;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.mcstats.Metrics;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent;
|
||||
import org.spongepowered.api.plugin.Plugin;
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.profile.GameProfileManager;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.text.serializer.TextSerializers;
|
||||
|
||||
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.3.4")
|
||||
|
||||
import static org.spongepowered.api.Sponge.getGame;
|
||||
|
||||
public class FaweSponge implements IFawe {
|
||||
public PluginContainer plugin;
|
||||
|
||||
public final SpongeMain plugin;
|
||||
|
||||
public FaweSponge instance;
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
@Inject
|
||||
private Game game;
|
||||
private Server server;
|
||||
|
||||
private GameProfileManager resolver;
|
||||
|
||||
private ForgeWorldEdit worldedit;
|
||||
|
||||
public ForgeWorldEdit getWorldEditPlugin() {
|
||||
@ -50,46 +42,21 @@ public class FaweSponge implements IFawe {
|
||||
return this.worldedit;
|
||||
}
|
||||
|
||||
public Game getGame() {
|
||||
return this.game;
|
||||
}
|
||||
|
||||
public Server getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
public GameProfileManager getResolver() {
|
||||
if (this.resolver == null) {
|
||||
this.resolver = this.game.getServer().getGameProfileManager();
|
||||
}
|
||||
return this.resolver;
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onServerAboutToStart(GameAboutToStartServerEvent event) {
|
||||
debug("FAWE: Server init");
|
||||
public FaweSponge(SpongeMain plugin) {
|
||||
instance = this;
|
||||
plugin = this.game.getPluginManager().fromInstance(this).get();
|
||||
this.server = this.game.getServer();
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
Fawe.set(this);
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
this.getServer().shutdown();
|
||||
}
|
||||
TaskManager.IMP.later(() -> SpongeUtil.initBiomeCache(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String message) {
|
||||
message = C.format(message, C.replacements);
|
||||
if (!Settings.CONSOLE_COLOR) {
|
||||
message = message.replaceAll('\u00a7' + "[a-z|0-9]", "");
|
||||
}
|
||||
if (this.server == null) {
|
||||
this.logger.info(message);
|
||||
return;
|
||||
}
|
||||
this.server.getConsole().sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(BBC.color(message)));
|
||||
message = BBC.color(message);
|
||||
Sponge.getServer().getConsole().sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(BBC.color(message)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,57 +66,83 @@ public class FaweSponge implements IFawe {
|
||||
|
||||
@Override
|
||||
public void setupCommand(String label, FaweCommand cmd) {
|
||||
|
||||
getGame().getCommandManager().register(plugin, new SpongeCommand(cmd), label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FawePlayer wrap(Object obj) {
|
||||
if (obj.getClass() == String.class) {
|
||||
String name = (String) obj;
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(name);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
Player player = Sponge.getServer().getPlayer(name).orElseGet(null);
|
||||
return player != null ? new SpongePlayer(player) : null;
|
||||
} else if (obj instanceof Player) {
|
||||
Player player = (Player) obj;
|
||||
FawePlayer existing = Fawe.get().getCachedPlayer(player.getName());
|
||||
return existing != null ? existing : new SpongePlayer(player);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupWEListener() {
|
||||
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupVault() {
|
||||
|
||||
debug("[FAWE] Permission hook not implemented yet!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return null;
|
||||
return new SpongeTaskMan(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getVersion() {
|
||||
return new int[0];
|
||||
debug("[FAWE] Checking minecraft version: Sponge: ");
|
||||
String version = Sponge.getGame().getPlatform().getMinecraftVersion().getName();
|
||||
String[] split = version.split("\\.");
|
||||
return new int[]{Integer.parseInt(split[0]), Integer.parseInt(split[1]), split.length == 3 ? Integer.parseInt(split[2]) : 0};
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getQueue() {
|
||||
return null;
|
||||
return new SpongeQueue_1_8();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(EditSession session) {
|
||||
return null;
|
||||
return new SpongeEditSessionWrapper_0(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweMaskManager> getMaskManagers() {
|
||||
return null;
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
Metrics metrics = new Metrics(this.game, this.plugin);
|
||||
Metrics metrics = new Metrics(Sponge.getGame(), Sponge.getPluginManager().fromInstance(plugin).get());
|
||||
metrics.start();
|
||||
debug(C.PREFIX.s() + "&6Metrics enabled.");
|
||||
debug("[FAWE] &6Metrics enabled.");
|
||||
} catch (IOException e) {
|
||||
debug(C.PREFIX.s() + "&cFailed to load up metrics.");
|
||||
debug("[FAWE] &cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FawePlayer> getPlayers() {
|
||||
HashSet<FawePlayer> players = new HashSet<>();
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
players.add(wrap(player));
|
||||
}
|
||||
return players;
|
||||
}
|
||||
}
|
||||
|
57
forge/src/main/java/com/boydti/fawe/forge/SpongeMain.java
Normal file
57
forge/src/main/java/com/boydti/fawe/forge/SpongeMain.java
Normal file
@ -0,0 +1,57 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.google.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
import org.spongepowered.api.plugin.Plugin;
|
||||
import org.spongepowered.api.plugin.PluginContainer;
|
||||
import org.spongepowered.api.profile.GameProfileManager;
|
||||
|
||||
@Plugin(id = "com.boydti.fawe", name = "FastAsyncWorldEdit", description = "Lagless WorldEdit, Area restrictions, Memory mangement, Block logging", url = "https://github.com/boy0001/FastAsyncWorldedit", version = "3.3.5")
|
||||
public class SpongeMain {
|
||||
public PluginContainer plugin;
|
||||
|
||||
@Inject
|
||||
private Logger logger;
|
||||
|
||||
@Inject
|
||||
private Game game;
|
||||
private Server server;
|
||||
|
||||
private GameProfileManager resolver;
|
||||
|
||||
public Game getGame() {
|
||||
return this.game;
|
||||
}
|
||||
|
||||
public Server getServer() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
public GameProfileManager getResolver() {
|
||||
if (this.resolver == null) {
|
||||
this.resolver = this.game.getServer().getGameProfileManager();
|
||||
}
|
||||
return this.resolver;
|
||||
}
|
||||
|
||||
|
||||
@Listener
|
||||
public void onGamePreInit(GamePreInitializationEvent event) {
|
||||
plugin = this.game.getPluginManager().fromInstance(this).get();
|
||||
this.server = this.game.getServer();
|
||||
new FaweSponge(this);
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onQuit(ClientConnectionEvent.Disconnect event) {
|
||||
Player player = event.getTargetEntity();
|
||||
Fawe.get().unregister(player.getName());
|
||||
}
|
||||
}
|
@ -29,12 +29,13 @@ public class SpongePlayer extends FawePlayer<Player> {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String perm) {
|
||||
return this.parent.hasPermission(perm);
|
||||
Object meta = getMeta(perm);
|
||||
return meta instanceof Boolean ? (boolean) meta : this.parent.hasPermission(perm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPermission(final String perm, final boolean flag) {
|
||||
throw new UnsupportedOperationException("WIP NOT IMPLEMENTED YET TODO"); // TODO FIXME
|
||||
setMeta(perm, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,4 +59,8 @@ public class SpongePlayer extends FawePlayer<Player> {
|
||||
return (com.sk89q.worldedit.entity.Player) Fawe.<FaweSponge> imp().getWorldEditPlugin().wrap((EntityPlayerMP) this.parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasWorldEditBypass() {
|
||||
return hasPermission("fawe.bypass") || getMeta("fawe.bypass") == Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
72
forge/src/main/java/com/boydti/fawe/forge/SpongeTaskMan.java
Normal file
72
forge/src/main/java/com/boydti/fawe/forge/SpongeTaskMan.java
Normal file
@ -0,0 +1,72 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.scheduler.Task;
|
||||
|
||||
public class SpongeTaskMan extends TaskManager {
|
||||
|
||||
private final SpongeMain plugin;
|
||||
|
||||
public SpongeTaskMan(SpongeMain plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
private final AtomicInteger i = new AtomicInteger();
|
||||
|
||||
private final HashMap<Integer, Task> tasks = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public int repeat(Runnable runnable, int interval) {
|
||||
int val = this.i.incrementAndGet();
|
||||
Task.Builder builder = Sponge.getGame().getScheduler().createTaskBuilder();
|
||||
Task.Builder built = builder.delayTicks(interval).intervalTicks(interval).execute(runnable);
|
||||
Task task = built.submit(plugin);
|
||||
this.tasks.put(val, task);
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(Runnable runnable, int interval) {
|
||||
int val = this.i.incrementAndGet();
|
||||
Task.Builder builder = Sponge.getGame().getScheduler().createTaskBuilder();
|
||||
Task.Builder built = builder.delayTicks(interval).async().intervalTicks(interval).execute(runnable);
|
||||
Task task = built.submit(plugin);
|
||||
this.tasks.put(val, task);
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(Runnable runnable) {
|
||||
Task.Builder builder = Sponge.getGame().getScheduler().createTaskBuilder();
|
||||
builder.async().execute(runnable).submit(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(Runnable runnable) {
|
||||
Task.Builder builder = Sponge.getGame().getScheduler().createTaskBuilder();
|
||||
builder.execute(runnable).submit(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(Runnable runnable, int delay) {
|
||||
Task.Builder builder = Sponge.getGame().getScheduler().createTaskBuilder();
|
||||
builder.delayTicks(delay).execute(runnable).submit(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(Runnable runnable, int delay) {
|
||||
Task.Builder builder = Sponge.getGame().getScheduler().createTaskBuilder();
|
||||
builder.async().delayTicks(delay).execute(runnable).submit(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int i) {
|
||||
Task task = this.tasks.remove(i);
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
75
forge/src/main/java/com/boydti/fawe/forge/SpongeUtil.java
Normal file
75
forge/src/main/java/com/boydti/fawe/forge/SpongeUtil.java
Normal file
@ -0,0 +1,75 @@
|
||||
package com.boydti.fawe.forge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.sk89q.worldedit.world.biome.BiomeData;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import org.spongepowered.api.world.biome.BiomeType;
|
||||
import org.spongepowered.api.world.biome.BiomeTypes;
|
||||
|
||||
/**
|
||||
* Created by Jesse on 4/2/2016.
|
||||
*/
|
||||
public class SpongeUtil {
|
||||
private static BiomeType[] biomes;
|
||||
private static HashMap<String, Integer> biomeMap;
|
||||
public static Map<Integer, BiomeData> biomeData;
|
||||
|
||||
public static void initBiomeCache() {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("com.sk89q.worldedit.forge.ForgeBiomeRegistry");
|
||||
Field bdf = clazz.getDeclaredField("biomeData");
|
||||
bdf.setAccessible(true);
|
||||
biomeData = (Map<Integer, BiomeData>) bdf.get(null);
|
||||
biomes = new BiomeType[256];
|
||||
biomeMap = new HashMap<>();
|
||||
int lastId = 0;
|
||||
loop:
|
||||
for (Map.Entry<Integer, BiomeData> entry : biomeData.entrySet()) {
|
||||
int id = entry.getKey();
|
||||
BiomeData data = entry.getValue();
|
||||
String name = data.getName().toUpperCase().replaceAll(" ", "_").replaceAll("[+]", "_PLUS");
|
||||
if (name.endsWith("_M") || name.contains("_M_")) {
|
||||
name = name.replaceAll("_M", "_MOUNTAINS");
|
||||
}
|
||||
if (name.endsWith("_F") || name.contains("_F_")) {
|
||||
name = name.replaceAll("_F", "_FOREST");
|
||||
}
|
||||
try {
|
||||
biomes[id] = (BiomeType) BiomeTypes.class.getField(name).get(null);
|
||||
biomeMap.put(biomes[id].getId(), id);
|
||||
lastId = id;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
Field[] fields = BiomeTypes.class.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (field.getName().replaceAll("_", "").equals(name.replaceAll("_", ""))) {
|
||||
biomes[id] = (BiomeType) field.get(null);
|
||||
biomeMap.put(biomes[id].getId(), id);
|
||||
lastId = id;
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
Fawe.debug("Unknown biome: " + name);
|
||||
biomes[id] = biomes[lastId];
|
||||
biomeMap.put(biomes[lastId].getId(), lastId);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static BiomeType getBiome(String biome) {
|
||||
if (biomes == null) {
|
||||
initBiomeCache();
|
||||
}
|
||||
return biomes[biomeMap.get(biome.toUpperCase())];
|
||||
}
|
||||
|
||||
public static BiomeType getBiome(int index) {
|
||||
return (BiomeType) BiomeGenBase.getBiome(index);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
/**
|
||||
* Created by Jesse on 4/2/2016.
|
||||
*/
|
||||
public class SpongeEditSessionWrapper_0 extends EditSessionWrapper {
|
||||
public SpongeEditSessionWrapper_0(EditSession session) {
|
||||
super(session);
|
||||
}
|
||||
}
|
142
forge/src/main/java/com/boydti/fawe/forge/v0/SpongeQueue_0.java
Normal file
142
forge/src/main/java/com/boydti/fawe/forge/v0/SpongeQueue_0.java
Normal file
@ -0,0 +1,142 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.object.ChunkLoc;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
/**
|
||||
* Created by Jesse on 4/2/2016.
|
||||
*/
|
||||
public abstract class SpongeQueue_0 extends FaweQueue {
|
||||
|
||||
/**
|
||||
* Map of chunks in the queue
|
||||
*/
|
||||
private final ConcurrentHashMap<ChunkLoc, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(String worldName, int x, int z) {
|
||||
World world = Sponge.getServer().getWorld(worldName).get();
|
||||
Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null);
|
||||
return chunk != null && chunk.isLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(String world, int x, int y, int z, Runnable runnable) {
|
||||
// TODO Auto-generated method stub
|
||||
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> result = this.blocks.get(wrap);
|
||||
if (result == null) {
|
||||
throw new IllegalArgumentException("Task must be accompanied by a block change or manually adding to queue!");
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(final String world, int x, final int y, int z, final short id, final byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
|
||||
x = x & 15;
|
||||
z = z & 15;
|
||||
FaweChunk<Chunk> result = this.blocks.get(wrap);
|
||||
if (result == null) {
|
||||
result = this.getChunk(wrap);
|
||||
result.setBlock(x, y, z, id, data);
|
||||
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
|
||||
if (previous == null) {
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(wrap, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.setBlock(x, y, z, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(final String world, int x, int z, final BaseBiome biome) {
|
||||
final ChunkLoc wrap = new ChunkLoc(world, x >> 4, z >> 4);
|
||||
x = x & 15;
|
||||
z = z & 15;
|
||||
FaweChunk<Chunk> result = this.blocks.get(wrap);
|
||||
if (result == null) {
|
||||
result = this.getChunk(wrap);
|
||||
final FaweChunk<Chunk> previous = this.blocks.put(wrap, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(wrap, previous);
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
result.setBiome(x, z, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
final Iterator<Map.Entry<ChunkLoc, FaweChunk<Chunk>>> iter = this.blocks.entrySet().iterator();
|
||||
final FaweChunk<Chunk> toReturn = iter.next().getValue();
|
||||
if (SetQueue.IMP.isWaiting()) {
|
||||
return null;
|
||||
}
|
||||
iter.remove();
|
||||
this.execute(toReturn);
|
||||
return toReturn;
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayDeque<FaweChunk<Chunk>> toUpdate = new ArrayDeque<>();
|
||||
|
||||
public boolean execute(final FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
final Chunk chunk = fc.getChunk();
|
||||
chunk.loadChunk(true);
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(final FaweChunk<?> chunk) {
|
||||
this.blocks.put(chunk.getChunkLoc(), (FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public abstract Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs);
|
||||
|
||||
public abstract boolean setComponents(final FaweChunk<Chunk> fc);
|
||||
|
||||
@Override
|
||||
public abstract FaweChunk<Chunk> getChunk(final ChunkLoc wrap);
|
||||
|
||||
@Override
|
||||
public abstract boolean fixLighting(final FaweChunk<?> fc, final boolean fixAll);
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
package com.boydti.fawe.forge.v1_8;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.ChunkLoc;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
|
||||
public class SpongeChunk_1_8 extends FaweChunk<Chunk> {
|
||||
|
||||
public char[][] ids;
|
||||
public short[] count;
|
||||
public short[] air;
|
||||
public short[] relight;
|
||||
public int[][] biomes;
|
||||
public Chunk chunk;
|
||||
|
||||
public SpongeChunk_1_8(ChunkLoc chunk) {
|
||||
super(chunk);
|
||||
this.ids = new char[16][];
|
||||
this.count = new short[16];
|
||||
this.air = new short[16];
|
||||
this.relight = new short[16];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
if (this.chunk == null) {
|
||||
ChunkLoc cl = getChunkLoc();
|
||||
this.chunk = Sponge.getServer().getWorld(cl.world).get().getChunk(cl.x, 0, cl.z).get();
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getCount(int i) {
|
||||
return this.count[i];
|
||||
}
|
||||
|
||||
public int getAir(int i) {
|
||||
return this.air[i];
|
||||
}
|
||||
|
||||
public void setCount(int i, short value) {
|
||||
this.count[i] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getRelight(int i) {
|
||||
return this.relight[i];
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.count[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getTotalRelight() {
|
||||
if (getTotalCount() == 0) {
|
||||
Arrays.fill(this.count, (short) 1);
|
||||
Arrays.fill(this.relight, Short.MAX_VALUE);
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.relight[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw data for a section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public char[] getIdArray(int i) {
|
||||
return this.ids[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
char[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new char[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = (char) 1;
|
||||
return;
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
this.relight[i]++;
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 73:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 121:
|
||||
case 129:
|
||||
case 133:
|
||||
case 165:
|
||||
case 166:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
vs[j] = (char) (id << 4);
|
||||
return;
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
case 50:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
default:
|
||||
vs[j] = (char) ((id << 4) + data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BaseBiome biome) {
|
||||
if (this.biomes == null) {
|
||||
this.biomes = new int[16][];
|
||||
}
|
||||
int[] index = this.biomes[x];
|
||||
if (index == null) {
|
||||
index = this.biomes[x] = new int[16];
|
||||
}
|
||||
index[z] = biome.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk clone() {
|
||||
SpongeChunk_1_8 toReturn = new SpongeChunk_1_8(getChunkLoc());
|
||||
toReturn.air = this.air.clone();
|
||||
toReturn.count = this.count.clone();
|
||||
toReturn.relight = this.relight.clone();
|
||||
toReturn.ids = new char[this.ids.length][];
|
||||
for (int i = 0; i < this.ids.length; i++) {
|
||||
char[] matrix = this.ids[i];
|
||||
if (matrix != null) {
|
||||
toReturn.ids[i] = new char[matrix.length];
|
||||
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
}
|
@ -0,0 +1,304 @@
|
||||
package com.boydti.fawe.forge.v1_8;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.forge.SpongeUtil;
|
||||
import com.boydti.fawe.forge.v0.SpongeQueue_0;
|
||||
import com.boydti.fawe.object.ChunkLoc;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
|
||||
if (fcs.isEmpty()) {
|
||||
return fcs;
|
||||
}
|
||||
for (FaweChunk<Chunk> chunk : fcs) {
|
||||
sendChunk(chunk);
|
||||
}
|
||||
fcs.clear();
|
||||
return fcs;
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.getWorld();
|
||||
Vector3i pos = chunk.getBlockMin();
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = player.getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
Location<World> loc = player.getLocation();
|
||||
int px = loc.getBlockX() >> 4;
|
||||
int pz = loc.getBlockZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getBlockX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getBlockZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk;
|
||||
con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;
|
||||
Chunk spongeChunk = fc.getChunk();
|
||||
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeChunk.getWorld();
|
||||
ChunkLoc wrapper = fc.getChunkLoc();
|
||||
spongeChunk.loadChunk(true);
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
// Sections
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
// Trim tiles
|
||||
Set<Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
int lz = pos.getZ() & 15;
|
||||
int j = FaweCache.CACHE_I[ly][lx][lz];
|
||||
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||
char[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
if (array[k] != 0) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Trim entities
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
|
||||
entities[i] = new ClassInheritanceMultiMap<>(Entity.class);
|
||||
}
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
if (fs.getCount(j) == 0) {
|
||||
continue;
|
||||
}
|
||||
char[] newArray = fs.getIdArray(j);
|
||||
if (newArray == null) {
|
||||
continue;
|
||||
}
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
||||
section = new ExtendedBlockStorage(j << 4, flag);
|
||||
section.setData(newArray);
|
||||
sections[j] = section;
|
||||
continue;
|
||||
}
|
||||
char[] currentArray = section.getData();
|
||||
boolean fill = true;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
char n = newArray[k];
|
||||
switch (n) {
|
||||
case 0:
|
||||
fill = false;
|
||||
continue;
|
||||
case 1:
|
||||
fill = false;
|
||||
currentArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
currentArray[k] = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
// Clear
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int[][] biomes = fs.biomes;
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
int biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
spongeChunk.setBiome(x, z, SpongeUtil.getBiome(biome));
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendChunk(fs);
|
||||
}
|
||||
}, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues.
|
||||
* @param wrap
|
||||
*/
|
||||
@Override
|
||||
public SpongeChunk_1_8 getChunk(ChunkLoc wrap) {
|
||||
return new SpongeChunk_1_8(wrap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> pc, boolean fixAll) {
|
||||
try {
|
||||
SpongeChunk_1_8 bc = (SpongeChunk_1_8) pc;
|
||||
Chunk spongeChunk = bc.getChunk();
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
|
||||
if (!spongeChunk.isLoaded()) {
|
||||
if (!spongeChunk.loadChunk(false)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
spongeChunk.unloadChunk();
|
||||
spongeChunk.loadChunk(false);
|
||||
}
|
||||
nmsChunk.generateSkylightMap();
|
||||
if (bc.getTotalRelight() == 0 && !fixAll) {
|
||||
return true;
|
||||
}
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||
ChunkLoc loc = pc.getChunkLoc();
|
||||
|
||||
int X = loc.x << 4;
|
||||
int Z = loc.z << 4;
|
||||
|
||||
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if (section == null) {
|
||||
continue;
|
||||
}
|
||||
if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) {
|
||||
continue;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int l = PseudoRandom.random.random(2);
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
int i = array[k];
|
||||
if (i < 16) {
|
||||
continue;
|
||||
}
|
||||
short id = (short) (i >> 4);
|
||||
switch (id) { // Lighting
|
||||
default:
|
||||
if (!fixAll) {
|
||||
continue;
|
||||
}
|
||||
if ((k & 1) == l) {
|
||||
l = 1 - l;
|
||||
continue;
|
||||
}
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 50:
|
||||
case 51:
|
||||
case 62:
|
||||
case 74:
|
||||
case 76:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 130:
|
||||
case 138:
|
||||
case 169:
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
if (isSurrounded(sections, x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
BlockPos pos = new BlockPos(X + x, y, Z + z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
return isSolid(getId(sections, x, y + 1, z))
|
||||
&& isSolid(getId(sections, x + 1, y - 1, z))
|
||||
&& isSolid(getId(sections, x - 1, y, z))
|
||||
&& isSolid(getId(sections, x, y, z + 1))
|
||||
&& isSolid(getId(sections, x, y, z - 1));
|
||||
}
|
||||
|
||||
public boolean isSolid(int i) {
|
||||
return i != 0 && Block.getBlockById(i).isOpaqueCube();
|
||||
}
|
||||
|
||||
public int getId(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
if (x < 0 || x > 15 || z < 0 || z > 15) {
|
||||
return 1;
|
||||
}
|
||||
if (y < 0 || y > 255) {
|
||||
return 1;
|
||||
}
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user