diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index adc5c9b29..d9634733d 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -25,7 +25,6 @@ import com.boydti.fawe.bukkit.util.BukkitTaskMan; import com.boydti.fawe.bukkit.util.ItemUtil; import com.boydti.fawe.bukkit.util.VaultUtil; import com.boydti.fawe.bukkit.util.cui.CUIListener; -import com.boydti.fawe.bukkit.util.cui.StructureCUI; import com.boydti.fawe.bukkit.util.image.BukkitImageViewer; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.bukkit.v0.BukkitQueue_All; @@ -41,7 +40,6 @@ import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.Jars; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.TaskManager; -import com.boydti.fawe.util.cui.CUI; import com.boydti.fawe.util.image.ImageViewer; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.world.World; @@ -64,7 +62,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.UUID; public class FaweBukkit implements IFawe, Listener { @@ -149,32 +146,6 @@ public class FaweBukkit implements IFawe, Listener { }); } - @Override - public CUI getCUI(FawePlayer player) { - if (Settings.IMP.EXPERIMENTAL.VANILLA_CUI) { - if (listeningCui && cuiListener == null) return null; - listeningCui = true; - if (cuiListener == null) { - Plugin protocolLib = Bukkit.getPluginManager().getPlugin("ProtocolLib"); - if (protocolLib != null && protocolLib.isEnabled()) { - cuiListener = new CUIListener(plugin); - } else { - return null; - } - } - return new StructureCUI(player); - } - return null; - } - - @Override - public void registerPacketListener() { - PluginManager manager = Bukkit.getPluginManager(); - if (packetListener == null && manager.getPlugin("ProtocolLib") != null) { - packetListener = new CFIPacketListener(plugin); - } - } - @Override public synchronized ImageViewer getImageViewer(FawePlayer fp) { if (listeningImages && imageListener == null) return null; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java index b1e389cc6..5040670d5 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/cui/StructureCUI.java @@ -69,6 +69,7 @@ public class StructureCUI extends CUI { private int viewDistance() { Player player = this.getPlayer().parent; + //todo replace with PaperLib.isPaper() if (Bukkit.getVersion().contains("paper")) { return player.getViewDistance(); } else { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java index 512250b33..94da99999 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitAdapter.java @@ -56,8 +56,8 @@ import org.bukkit.inventory.ItemStack; * Adapts between Bukkit and WorldEdit equivalent objects. */ public enum BukkitAdapter { - INSTANCE - ; + INSTANCE; + private final IBukkitAdapter adapter; BukkitAdapter() { @@ -73,14 +73,36 @@ public enum BukkitAdapter { return INSTANCE.adapter; } + /** + * Checks equality between a WorldEdit BlockType and a Bukkit Material + * + * @param blockType The WorldEdit BlockType + * @param type The Bukkit Material + * @return If they are equal + */ public static boolean equals(BlockType blockType, Material type) { return getAdapter().equals(blockType, type); } + /** + * Convert any WorldEdit world into an equivalent wrapped Bukkit world. + * + *

If a matching world cannot be found, a {@link RuntimeException} + * will be thrown.

+ * + * @param world the world + * @return a wrapped Bukkit world + */ public static BukkitWorld asBukkitWorld(World world) { return getAdapter().asBukkitWorld(world); } + /** + * Create a WorldEdit world from a Bukkit world. + * + * @param world the Bukkit world + * @return a WorldEdit world + */ public static World adapt(org.bukkit.World world) { return getAdapter().adapt(world); } @@ -89,23 +111,48 @@ public enum BukkitAdapter { return getAdapter().adapt(world); } + /** + * Create a WorldEdit location from a Bukkit location. + * + * @param location the Bukkit location + * @return a WorldEdit location + */ public static Location adapt(org.bukkit.Location location) { + checkNotNull(location); return getAdapter().adapt(location); } + /** + * Create a Bukkit location from a WorldEdit location. + * + * @param location the WorldEdit location + * @return a Bukkit location + */ public static org.bukkit.Location adapt(Location location) { + checkNotNull(location); return getAdapter().adapt(location); } public static org.bukkit.Location adapt(org.bukkit.World world, Vector3 position) { return getAdapter().adapt(world, position); } - + public static org.bukkit.Location adapt(org.bukkit.World world, BlockVector3 position) { + checkNotNull(world); + checkNotNull(position); return getAdapter().adapt(world, position); } + /** + * Create a Bukkit location from a WorldEdit location with a Bukkit world. + * + * @param world the Bukkit world + * @param location the WorldEdit location + * @return a Bukkit location + */ public static org.bukkit.Location adapt(org.bukkit.World world, Location location) { + checkNotNull(world); + checkNotNull(location); return getAdapter().adapt(world, location); } @@ -113,23 +160,58 @@ public enum BukkitAdapter { return getAdapter().asVector(location); } + /** + * Create a WorldEdit Vector from a Bukkit location. + * + * @param location The Bukkit location + * @return a WorldEdit vector + */ public static BlockVector3 asBlockVector(org.bukkit.Location location) { + checkNotNull(location); return getAdapter().asBlockVector(location); } + /** + * Create a WorldEdit entity from a Bukkit entity. + * + * @param entity the Bukkit entity + * @return a WorldEdit entity + */ public static Entity adapt(org.bukkit.entity.Entity entity) { + checkNotNull(entity); return getAdapter().adapt(entity); } + /** + * Create a Bukkit Material form a WorldEdit ItemType + * + * @param itemType The WorldEdit ItemType + * @return The Bukkit Material + */ public static Material adapt(ItemType itemType) { + checkNotNull(itemType); return getAdapter().adapt(itemType); } + /** + * Create a Bukkit Material form a WorldEdit BlockType + * + * @param blockType The WorldEdit BlockType + * @return The Bukkit Material + */ public static Material adapt(BlockType blockType) { + checkNotNull(blockType); return getAdapter().adapt(blockType); } + /** + * Create a WorldEdit GameMode from a Bukkit one. + * + * @param gameMode Bukkit GameMode + * @return WorldEdit GameMode + */ public static GameMode adapt(org.bukkit.GameMode gameMode) { + checkNotNull(gameMode); return getAdapter().adapt(gameMode); } @@ -161,15 +243,37 @@ public enum BukkitAdapter { return getAdapter().adapt(entityType); } + /** + * Converts a Material to a BlockType + * + * @param material The material + * @return The blocktype + */ public static BlockType asBlockType(Material material) { + checkNotNull(material); return getAdapter().asBlockType(material); } + /** + * Converts a Material to a ItemType + * + * @param material The material + * @return The itemtype + */ public static ItemType asItemType(Material material) { + checkNotNull(material); return getAdapter().asItemType(material); } + + /** + * Create a WorldEdit BlockState from a Bukkit BlockData + * + * @param blockData The Bukkit BlockData + * @return The WorldEdit BlockState + */ public static BlockState adapt(BlockData blockData) { + checkNotNull(blockData); return getAdapter().adapt(blockData); } @@ -183,7 +287,8 @@ public enum BukkitAdapter { * @param block The WorldEdit BlockStateHolder * @return The Bukkit BlockData */ - public static > BlockData adapt(B block) { + public static BlockData adapt(BlockStateHolder block) { + checkNotNull(block); return getAdapter().adapt(block); } @@ -191,15 +296,40 @@ public enum BukkitAdapter { return getAdapter().getBlockData(combinedId); } - public static BlockState asBlockState(ItemStack itemStack) { - return getAdapter().asBlockState(itemStack); + /** + * Create a WorldEdit BlockState from a Bukkit ItemStack + * + * @param itemStack The Bukkit ItemStack + * @return The WorldEdit BlockState + */ + public static BlockState asBlockState(ItemStack itemStack) throws WorldEditException { + checkNotNull(itemStack); + if (itemStack.getType().isBlock()) { + return getAdapter().asBlockState(itemStack); + } else { + throw new NotABlockException(); + } } + /** + * Create a WorldEdit BaseItemStack from a Bukkit ItemStack + * + * @param itemStack The Bukkit ItemStack + * @return The WorldEdit BaseItemStack + */ public static BaseItemStack adapt(ItemStack itemStack) { + checkNotNull(itemStack); return getAdapter().adapt(itemStack); } + /** + * Create a Bukkit ItemStack from a WorldEdit BaseItemStack + * + * @param item The WorldEdit BaseItemStack + * @return The Bukkit ItemStack + */ public static ItemStack adapt(BaseItemStack item) { + checkNotNull(item); return getAdapter().adapt(item); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 637c61470..e9cbeb07f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -109,8 +109,8 @@ public class BukkitPlayer extends AbstractPlayerActor { if (itemStack.getType().getId().equalsIgnoreCase(WorldEdit.getInstance().getConfiguration().wandItem)) { inv.remove(newItem); } - final ItemStack item = player.getItemInHand(); - player.setItemInHand(newItem); + final ItemStack item = player.getInventory().getItemInMainHand(); + player.getInventory().setItemInMainHand(newItem); HashMap overflow = inv.addItem(item); if (!overflow.isEmpty()) { TaskManager.IMP.sync(new RunnableVal() { @@ -216,7 +216,7 @@ public class BukkitPlayer extends AbstractPlayerActor { if (params.length > 0) { send = send + "|" + StringUtil.joinString(params, "|"); } - player.sendPluginMessage(plugin, WorldEditPlugin.getCuiPluginChannel(), send.getBytes(CUIChannelListener.UTF_8_CHARSET)); + player.sendPluginMessage(plugin, WorldEditPlugin.CUI_PLUGIN_CHANNEL, send.getBytes(CUIChannelListener.UTF_8_CHARSET)); } public Player getPlayer() { @@ -305,7 +305,7 @@ public class BukkitPlayer extends AbstractPlayerActor { } @Override - public void sendFakeBlock(BlockVector3 pos, BlockStateHolder block) { + public > void sendFakeBlock(BlockVector3 pos, B block) { Location loc = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ()); if (block == null) { player.sendBlockChange(loc, player.getWorld().getBlockAt(loc).getBlockData()); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index 2d312c19f..6b92b71f8 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -100,7 +100,7 @@ public class BukkitServerInterface implements MultiUserPlatform { return player; } else { org.bukkit.entity.Player bukkitPlayer = server.getPlayerExact(player.getName()); - return bukkitPlayer != null ? plugin.wrapPlayer(bukkitPlayer) : null; + return bukkitPlayer != null ? WorldEditPlugin.getInstance().wrapPlayer(bukkitPlayer) : null; } } @@ -119,7 +119,7 @@ public class BukkitServerInterface implements MultiUserPlatform { public void registerCommands(Dispatcher dispatcher) { List toRegister = new ArrayList<>(); BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher); - + for (CommandMapping command : dispatcher.getCommands()) { Description description = command.getDescription(); List permissions = description.getPermissions(); @@ -177,7 +177,7 @@ public class BukkitServerInterface implements MultiUserPlatform { public Collection getConnectedUsers() { List users = new ArrayList<>(); for (org.bukkit.entity.Player player : Bukkit.getServer().getOnlinePlayers()) { - users.add(plugin.wrapPlayer(player)); + users.add(WorldEditPlugin.getInstance().wrapPlayer(player)); } return users; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index cdcdb6fb5..3f93e7c31 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.bukkit; -import com.bekvon.bukkit.residence.commands.message; import com.boydti.fawe.Fawe; import com.boydti.fawe.bukkit.FaweBukkit; import com.boydti.fawe.bukkit.adapter.v1_13_1.Spigot_v1_13_R2; @@ -34,47 +33,35 @@ import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; import com.sk89q.worldedit.event.platform.CommandEvent; -import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.event.platform.PlatformReadyEvent; -import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.inventory.BlockBag; -import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockCategory; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.FuzzyBlockState; import com.sk89q.worldedit.world.entity.EntityType; import com.sk89q.worldedit.world.item.ItemCategory; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.registry.LegacyMapper; -import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.Tag; import org.bukkit.block.Biome; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPluginLoader; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; @@ -111,7 +98,7 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter lookupNamesField.setAccessible(true); List plugins = (List) pluginsField.get(manager); lookupNames = (Map) lookupNamesField.get(manager); - pluginsField.set(manager, plugins = new ArrayList(plugins) { + pluginsField.set(manager, new ArrayList(plugins) { @Override public boolean add(Plugin plugin) { if (plugin.getName().startsWith("AsyncWorldEdit")) { @@ -126,7 +113,7 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter }); lookupNamesField.set(manager, lookupNames = new ConcurrentHashMap(lookupNames) { @Override - public Plugin put(String key, Plugin plugin) { + public Plugin put(@NotNull String key, @NotNull Plugin plugin) { if (plugin.getName().startsWith("AsyncWorldEdit") || plugin.getName().startsWith("BetterShutdown")) { return null; } @@ -157,15 +144,11 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter setEnabled(true); } - public static String getCuiPluginChannel() { - return CUI_PLUGIN_CHANNEL; - } - @Override public void onLoad() { if (INSTANCE != null) return; rename(); - this.INSTANCE = this; + INSTANCE = this; FaweBukkit imp = new FaweBukkit(this); //noinspection ResultOfMethodCallIgnored @@ -190,6 +173,7 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter if (INSTANCE != null) return; onLoad(); setupTags(); // these have to be done post-world since they rely on MC registries. the other ones just use Bukkit enums + //TODO: FAWE -- This needs to be moved to onLoad() setupRegistries(); WorldEdit.getInstance().loadMappings(); @@ -226,28 +210,30 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter } // Block & Item for (Material material : Material.values()) { -// if (material.isBlock() && !material.isLegacy()) { -// BlockType.REGISTRY.register(material.getKey().toString(), new BlockType(material.getKey().toString(), blockState -> { -// // TODO Use something way less hacky than this. -// ParserContext context = new ParserContext(); -// context.setPreferringWildcard(true); -// context.setTryLegacy(false); -// context.setRestricted(false); -// try { -// FuzzyBlockState state = (FuzzyBlockState) WorldEdit.getInstance().getBlockFactory().parseFromInput( -// BukkitAdapter.adapt(blockState.getBlockType()).createBlockData().getAsString(), context -// ).toImmutableState(); -// BlockState defaultState = blockState.getBlockType().getAllStates().get(0); -// for (Map.Entry, Object> propertyObjectEntry : state.getStates().entrySet()) { -// defaultState = defaultState.with((Property) propertyObjectEntry.getKey(), propertyObjectEntry.getValue()); -// } -// return defaultState; -// } catch (InputParseException e) { -// e.printStackTrace(); -// return blockState; -// } -// })); -// } +/* + if (material.isBlock() && !material.isLegacy()) { + BlockType.REGISTRY.register(material.getKey().toString(), new BlockType(material.getKey().toString(), blockState -> { + // TODO Use something way less hacky than this. + ParserContext context = new ParserContext(); + context.setPreferringWildcard(true); + context.setTryLegacy(false); + context.setRestricted(false); + try { + FuzzyBlockState state = (FuzzyBlockState) WorldEdit.getInstance().getBlockFactory().parseFromInput( + BukkitAdapter.adapt(blockState.getBlockType()).createBlockData().getAsString(), context + ).toImmutableState(); + BlockState defaultState = blockState.getBlockType().getAllStates().get(0); + for (Map.Entry, Object> propertyObjectEntry : state.getStates().entrySet()) { + defaultState = defaultState.with((Property) propertyObjectEntry.getKey(), propertyObjectEntry.getValue()); + } + return defaultState; + } catch (InputParseException e) { + e.printStackTrace(); + return blockState; + } + })); + } +*/ if (material.isItem() && !material.isLegacy()) { ItemType.REGISTRY.register(material.getKey().toString(), new ItemType(material.getKey().toString())); } @@ -276,63 +262,30 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter } private void rename() { -// { -// PluginDescriptionFile desc = getDescription(); -// if (desc != null) { -// try { -// Field nameField = PluginDescriptionFile.class.getDeclaredField("name"); -// nameField.setAccessible(true); -// nameField.set(desc, "FastAsyncWorldEdit"); -// Field descriptionField = JavaPlugin.class.getDeclaredField("description"); -// descriptionField.setAccessible(true); -// descriptionField.set(this, desc); -// } catch (Throwable ignore) { -// ignore.printStackTrace(); -// } -// } -// } - { - File dir = getDataFolder(); - if (dir != null) { - dir = new File(dir.getParentFile(), "FastAsyncWorldEdit"); - try { - Field descriptionField = JavaPlugin.class.getDeclaredField("dataFolder"); - descriptionField.setAccessible(true); - descriptionField.set(this, dir); - } catch (Throwable ignore) { - ignore.printStackTrace(); - } - } + File dir = getDataFolder(); + dir = new File(dir.getParentFile(), "FastAsyncWorldEdit"); + try { + Field descriptionField = JavaPlugin.class.getDeclaredField("dataFolder"); + descriptionField.setAccessible(true); + descriptionField.set(this, dir); + } catch (Throwable throwable) { + throwable.printStackTrace(); } -// { -// Logger logger = getLogger(); -// if (logger != null) { -// try { -// Field nameField = Logger.class.getDeclaredField("name"); -// nameField.setAccessible(true); -// nameField.set(logger, "FastAsyncWorldEdit"); -// } catch (Throwable ignore) { -// ignore.printStackTrace(); -// } -// } -// } - { - File pluginsFolder = MainUtil.getJarFile().getParentFile(); - for (File file : pluginsFolder.listFiles()) { - if (file.length() == 1988) return; - } - Plugin plugin = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit"); - File dummy = MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "DummyFawe.jar"); - if (dummy != null && dummy.exists() && plugin == this) { - try { - Bukkit.getPluginManager().loadPlugin(dummy); - } catch (Throwable e) { - e.printStackTrace(); - } - getLogger().info("Please restart the server if you have any plugins which depend on FAWE."); - } else if (dummy == null) { - MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "update" + File.separator + "DummyFawe.jar"); + File pluginsFolder = MainUtil.getJarFile().getParentFile(); + for (File file : pluginsFolder.listFiles()) { + if (file.length() == 1988) return; + } + Plugin plugin = Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit"); + File dummy = MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "DummyFawe.jar"); + if (dummy != null && dummy.exists() && plugin == this) { + try { + Bukkit.getPluginManager().loadPlugin(dummy); + } catch (Throwable e) { + e.printStackTrace(); } + getLogger().info("Please restart the server if you have any plugins which depend on FAWE."); + } else if (dummy == null) { + MainUtil.copyFile(MainUtil.getJarFile(), "DummyFawe.src", pluginsFolder, "update" + File.separator + "DummyFawe.jar"); } } @@ -470,20 +423,20 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter return true; } -// @Deprecated Using Async tab complete (rather than main thread) -// @Override -// public List onTabComplete(CommandSender sender, Command cmd, String commandLabel, String[] args) { -// // Add the command to the array because the underlying command handling -// // code of WorldEdit expects it -// String[] split = new String[args.length + 1]; -// System.arraycopy(args, 0, split, 1, args.length); -// split[0] = cmd.getName(); -// -// CommandSuggestionEvent event = new CommandSuggestionEvent(wrapCommandSender(sender), Joiner.on(" ").join(split)); -// getWorldEdit().getEventBus().post(event); -// -// return event.getSuggestions(); -// } +/* + @Override + public List onTabComplete(CommandSender sender, Command cmd, String commandLabel, String[] args) { + // Add the command to the array because the underlying command handling + // code of WorldEdit expects it + String[] split = new String[args.length + 1]; + System.arraycopy(args, 0, split, 1, args.length); + split[0] = cmd.getName(); + + CommandSuggestionEvent event = new CommandSuggestionEvent(wrapCommandSender(sender), Joiner.on(" ").join(split)); + getWorldEdit().getEventBus().post(event); + return event.getSuggestions(); + } +*/ /** * Gets the session for the player. diff --git a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java index a3aa65f71..8266a9ec2 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java @@ -9,7 +9,6 @@ import com.boydti.fawe.regions.general.plot.PlotSquaredFeature; import com.boydti.fawe.util.*; import com.boydti.fawe.util.chat.ChatManager; import com.boydti.fawe.util.chat.PlainChatManager; -import com.boydti.fawe.util.cui.CUI; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.factory.DefaultTransformParser; import com.sk89q.worldedit.extension.platform.Actor; @@ -199,25 +198,6 @@ public class Fawe { public void onDisable() { } - public CUI getCUI(Actor actor) { - FawePlayer fp = FawePlayer.wrap(actor); - CUI cui = fp.getMeta("CUI"); - if (cui == null) { - cui = Fawe.imp().getCUI(fp); - if (cui != null) { - synchronized (fp) { - CUI tmp = fp.getMeta("CUI"); - if (tmp == null) { - fp.setMeta("CUI", cui); - } else { - cui = tmp; - } - } - } - } - return cui; - } - public ChatManager getChatManager() { return chatManager; } @@ -315,11 +295,10 @@ public class Fawe { Settings.IMP.PLATFORM = IMP.getPlatform().replace("\"", ""); try (InputStream stream = getClass().getResourceAsStream("/fawe.properties"); BufferedReader br = new BufferedReader(new InputStreamReader(stream))) { - // java.util.Scanner scanner = new java.util.Scanner(stream).useDelimiter("\\A"); String versionString = br.readLine(); String commitString = br.readLine(); String dateString = br.readLine(); - // scanner.close(); + br.close(); this.version = FaweVersion.tryParse(versionString, commitString, dateString); Settings.IMP.DATE = new Date(100 + version.year, version.month, version.day).toGMTString(); Settings.IMP.BUILD = "https://ci.athion.net/job/FastAsyncWorldEdit-Breaking/" + version.build; @@ -381,7 +360,7 @@ public class Fawe { try { String arch = System.getenv("PROCESSOR_ARCHITECTURE"); String wow64Arch = System.getenv("PROCESSOR_ARCHITEW6432"); - boolean x86OS = arch.endsWith("64") || wow64Arch != null && wow64Arch.endsWith("64") ? false : true; + boolean x86OS = !arch.endsWith("64") && (wow64Arch == null || !wow64Arch.endsWith("64")); boolean x86JVM = System.getProperty("sun.arch.data.model").equals("32"); if (x86OS != x86JVM) { debug("====== UPGRADE TO 64-BIT JAVA ======"); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java b/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java index ecba46a2f..304d9d1cb 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java @@ -5,7 +5,6 @@ import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.TaskManager; -import com.boydti.fawe.util.cui.CUI; import com.boydti.fawe.util.image.ImageViewer; import com.sk89q.worldedit.world.World; @@ -36,12 +35,8 @@ public interface IFawe { void startMetrics(); - default CUI getCUI(FawePlayer player) { return null; } - default ImageViewer getImageViewer(FawePlayer player) { return null; } - default void registerPacketListener() {} - default int getPlayerCount() { return Fawe.get().getCachedPlayers().size(); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java b/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java index 8c4402947..ba0ca4477 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/PlotLoader.java @@ -65,12 +65,9 @@ public class PlotLoader { area.setMeta("lastPlot", new PlotId(0, 0)); } PlotId lastId = (PlotId) area.getMeta("lastPlot"); - while (true) { + do { lastId = Auto.getNextPlotId(lastId, 1); - if (area.canClaim(player, lastId, lastId)) { - break; - } - } + } while (!area.canClaim(player, lastId, lastId)); area.setMeta("lastPlot", lastId); this.value = area.getPlot(lastId); this.value.setOwner(player.getUUID()); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index f66b12a69..1d0e4c183 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -339,11 +339,6 @@ public class Settings extends Config { "Allows brushes to be persistent (default: true)", }) public boolean PERSISTENT_BRUSHES = true; - @Comment({ - "[SAFE] Enable CUI without needing the mod installed (Requires ProtocolLib)", - }) - public boolean VANILLA_CUI = false; - @Comment({ "Disable using native libraries", @@ -502,4 +497,4 @@ public class Settings extends Config { } return limit; } -} \ No newline at end of file +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/installer/InstallerFrame.java b/worldedit-core/src/main/java/com/boydti/fawe/installer/InstallerFrame.java index d68476e3e..3da4bc019 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/installer/InstallerFrame.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/installer/InstallerFrame.java @@ -37,19 +37,14 @@ import javax.swing.border.EmptyBorder; public class InstallerFrame extends JFrame { private final InvisiblePanel loggerPanel; - private Color LIGHT_GRAY = new Color(0x66, 0x66, 0x66); - private Color GRAY = new Color(0x44, 0x44, 0x46); - private Color DARK_GRAY = new Color(0x33, 0x33, 0x36); - private Color DARKER_GRAY = new Color(0x26, 0x26, 0x28); + private Color DARKER_GRAY; private Color INVISIBLE = new Color(0, 0, 0, 0); - private Color OFF_WHITE = new Color(200, 200, 200); private JTextArea loggerTextArea; private BrowseButton browse; public InstallerFrame() throws Exception { final MovablePanel movable = new MovablePanel(this); - Container content = this.getContentPane(); content.add(movable); this.setSize(480, 320); @@ -61,117 +56,109 @@ public class InstallerFrame extends JFrame { this.setLocation(x, y); this.setVisible(true); this.setOpacity(0); - movable.setBackground(DARK_GRAY); + movable.setBackground(Color.darkGray); movable.setLayout(new BorderLayout()); fadeIn(); JPanel topBar = new InvisiblePanel(new BorderLayout()); - { - JPanel topBarLeft = new InvisiblePanel(); - JPanel topBarRight = new InvisiblePanel(); + JPanel topBarLeft = new InvisiblePanel(); + JPanel topBarRight = new InvisiblePanel(); - JLabel title = new JLabel("FastAsyncWorldEdit Installer"); - title.setHorizontalAlignment(SwingConstants.CENTER); - title.setAlignmentX(Component.RIGHT_ALIGNMENT); - title.setForeground(LIGHT_GRAY); + JLabel title = new JLabel("FastAsyncWorldEdit Installer"); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setAlignmentX(Component.RIGHT_ALIGNMENT); + title.setForeground(Color.lightGray); - MinimizeButton minimize = new MinimizeButton(this); - CloseButton exit = new CloseButton(); + MinimizeButton minimize = new MinimizeButton(this); + CloseButton exit = new CloseButton(); - topBarLeft.add(title); - topBarRight.add(minimize); - topBarRight.add(exit); + topBarLeft.add(title); + topBarRight.add(minimize); + topBarRight.add(exit); - topBar.add(topBarLeft, BorderLayout.CENTER); - topBar.add(topBarRight, BorderLayout.EAST); - } + topBar.add(topBarLeft, BorderLayout.CENTER); + topBar.add(topBarRight, BorderLayout.EAST); final JPanel mainContent = new InvisiblePanel(new BorderLayout()); - { - final JPanel browseContent = new InvisiblePanel(new BorderLayout()); - File dir = MainUtil.getWorkingDirectory("minecraft"); - JLabel folder = new JLabel("Folder: "); - folder.setForeground(OFF_WHITE); - final InteractiveButton text = new InteractiveButton(dir.getPath(), DARKER_GRAY) { - @Override - public void actionPerformed(ActionEvent e) { - browse.actionPerformed(e); - } - }; - text.setForeground(OFF_WHITE); - text.setBackground(DARKER_GRAY); - text.setOpaque(true); - text.setBorder(new EmptyBorder(4, 4, 4, 4)); - browse = new BrowseButton("") { - @Override - public void onSelect(File folder) { - text.setText(folder.getPath()); - movable.repaint(); - } - }; - InteractiveButton install = new InteractiveButton(">> Create Profile <<", DARKER_GRAY) { - @Override - public void actionPerformed(ActionEvent e) { - try { - install(text.getText()); - } catch (Exception e1) { - e1.printStackTrace(); - } - } - }; - browseContent.add(folder, BorderLayout.WEST); - browseContent.add(text, BorderLayout.CENTER); - browseContent.add(browse, BorderLayout.EAST); - final JPanel installContent = new InvisiblePanel(new FlowLayout()); - install.setPreferredSize(new Dimension(416, 32)); - installContent.add(install); - installContent.setBorder(new EmptyBorder(10, 0, 10, 0)); - this.loggerPanel = new InvisiblePanel(new BorderLayout()); - this.loggerPanel.setBackground(Color.GREEN); - loggerPanel.setPreferredSize(new Dimension(416, 160)); - loggerTextArea = new JTextArea(12, 52); - loggerTextArea.setBackground(GRAY); - loggerTextArea.setForeground(DARKER_GRAY); - loggerTextArea.setFont(new Font(loggerTextArea.getFont().getName(), Font.PLAIN, 9)); - JScrollPane scroll = new JScrollPane(loggerTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - scroll.setBackground(DARK_GRAY); - scroll.setBorder(new EmptyBorder(0, 0, 0, 0)); - loggerPanel.add(scroll); - loggerPanel.setVisible(false); - - mainContent.setBorder(new EmptyBorder(6, 32, 6, 32)); - mainContent.add(browseContent, BorderLayout.NORTH); - mainContent.add(installContent, BorderLayout.CENTER); - mainContent.add(loggerPanel, BorderLayout.SOUTH); - } - JPanel bottomBar = new InvisiblePanel(); - { - try { - InputStream stream = getClass().getResourceAsStream("/fawe.properties"); - java.util.Scanner scanner = new java.util.Scanner(stream).useDelimiter("\\A"); - String versionString = scanner.next().trim(); - scanner.close(); - FaweVersion version = null; - String date = new Date(100 + version.year, version.month, version.day).toGMTString(); - String build = "https://ci.athion.net/job/FastAsyncWorldEdit/" + version.build; - String commit = "https://github.com/boy0001/FastAsyncWorldedit/commit/" + Integer.toHexString(version.hash); - String footerMessage = "FAWE v" + version.year + "." + version.month + "." + version.day + " by Empire92 (c) 2017 (GPL v3.0)"; - URL licenseUrl = new URL("https://github.com/boy0001/FastAsyncWorldedit/blob/master/LICENSE"); - URLButton licenseButton = new URLButton(licenseUrl, footerMessage); - bottomBar.add(licenseButton); - } catch (Throwable ignore) { - ignore.printStackTrace(); + DARKER_GRAY = new Color(0x26, 0x26, 0x28); + final JPanel browseContent = new InvisiblePanel(new BorderLayout()); + File dir = MainUtil.getWorkingDirectory("minecraft"); + JLabel folder = new JLabel("Folder: "); + folder.setForeground(Color.white); + final InteractiveButton text = new InteractiveButton(dir.getPath(), DARKER_GRAY) { + @Override + public void actionPerformed(ActionEvent e) { + browse.actionPerformed(e); } - URL chat = new URL("https://discord.gg/ngZCzbU"); - URLButton chatButton = new URLButton(chat, "Chat"); - bottomBar.add(chatButton); - URL wiki = new URL("https://github.com/boy0001/FastAsyncWorldedit/wiki"); - URLButton wikiButton = new URLButton(wiki, "Wiki"); - bottomBar.add(wikiButton); - URL issue = new URL("https://github.com/boy0001/FastAsyncWorldedit/issues/new"); - URLButton issueButton = new URLButton(issue, "Report Issue"); - bottomBar.add(issueButton); + }; + text.setForeground(Color.white); + text.setBackground(DARKER_GRAY); + text.setOpaque(true); + text.setBorder(new EmptyBorder(4, 4, 4, 4)); + browse = new BrowseButton("") { + @Override + public void onSelect(File folder) { + text.setText(folder.getPath()); + movable.repaint(); + } + }; + InteractiveButton install = new InteractiveButton(">> Create Profile <<", DARKER_GRAY) { + @Override + public void actionPerformed(ActionEvent e) { + try { + install(text.getText()); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + }; + browseContent.add(folder, BorderLayout.WEST); + browseContent.add(text, BorderLayout.CENTER); + browseContent.add(browse, BorderLayout.EAST); + final JPanel installContent = new InvisiblePanel(new FlowLayout()); + install.setPreferredSize(new Dimension(416, 32)); + installContent.add(install); + installContent.setBorder(new EmptyBorder(10, 0, 10, 0)); + this.loggerPanel = new InvisiblePanel(new BorderLayout()); + this.loggerPanel.setBackground(Color.GREEN); + loggerPanel.setPreferredSize(new Dimension(416, 160)); + loggerTextArea = new JTextArea(12, 52); + Color GRAY = new Color(0x44, 0x44, 0x46); + loggerTextArea.setBackground(GRAY); + loggerTextArea.setForeground(DARKER_GRAY); + loggerTextArea.setFont(new Font(loggerTextArea.getFont().getName(), Font.PLAIN, 9)); + JScrollPane scroll = new JScrollPane(loggerTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + scroll.setBackground(Color.darkGray); + scroll.setBorder(new EmptyBorder(0, 0, 0, 0)); + loggerPanel.add(scroll); + loggerPanel.setVisible(false); + + mainContent.setBorder(new EmptyBorder(6, 32, 6, 32)); + mainContent.add(browseContent, BorderLayout.NORTH); + mainContent.add(installContent, BorderLayout.CENTER); + mainContent.add(loggerPanel, BorderLayout.SOUTH); + JPanel bottomBar = new InvisiblePanel(); + try { + FaweVersion version = null; + String date = new Date(100 + version.year, version.month, version.day).toGMTString(); + String build = "https://ci.athion.net/job/FastAsyncWorldEdit/" + version.build; + String commit = "https://github.com/boy0001/FastAsyncWorldedit/commit/" + Integer.toHexString(version.hash); + String footerMessage = "FAWE v" + version.year + "." + version.month + "." + version.day + " by Empire92 (c) 2017 (GPL v3.0)"; + URL licenseUrl = new URL("https://github.com/boy0001/FastAsyncWorldedit/blob/master/LICENSE"); + URLButton licenseButton = new URLButton(licenseUrl, footerMessage); + bottomBar.add(licenseButton); + } catch (Throwable ignore) { + ignore.printStackTrace(); } + URL chat = new URL("https://discord.gg/ngZCzbU"); + URLButton chatButton = new URLButton(chat, "Chat"); + bottomBar.add(chatButton); + URL wiki = new URL("https://github.com/boy0001/FastAsyncWorldedit/wiki"); + URLButton wikiButton = new URLButton(wiki, "Wiki"); + bottomBar.add(wikiButton); + URL issue = new URL("https://github.com/boy0001/FastAsyncWorldedit/issues/new"); + URLButton issueButton = new URLButton(issue, "Report Issue"); + bottomBar.add(issueButton); // We want to add these a bit later movable.add(topBar, BorderLayout.NORTH); @@ -214,140 +201,134 @@ public class InstallerFrame extends JFrame { prompt("You must select a folder, not a file"); return; } - Thread installThread = new Thread(new Runnable() { - @Override - public void run() { - List supported = Arrays.asList("v1710", "v189", "v194", "v110", "v111"); - String supportedString = null; - for (String version : supported) { - try { - Class.forName("com.boydti.fawe.forge." + version + ".ForgeChunk_All"); - supportedString = version; - break; - } catch (ClassNotFoundException ignore) { - } - } - if (supportedString == null) { - prompt("This version of FAWE cannot be installed this way."); - return; - } - debug("Selected version " + supportedString); - URL forgeUrl; - URL worldEditUrl; - URL worldEditCuiUrl; + Thread installThread = new Thread(() -> { + List supported = Arrays.asList("v1710", "v189", "v194", "v110", "v111"); + String supportedString = null; + for (String version : supported) { try { - switch (supportedString) { - case "v111": - forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.11.2-13.20.0.2201/forge-1.11.2-13.20.0.2201-installer.jar"); - worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9593/download/worldedit-forge-mc1.11-6.1.6-SNAPSHOT-dist.jar"); - worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/241/worldeditcuife-v1.0.6-mf-1.11.2-13.20.0.2201.jar"); - break; - case "v110": - forgeUrl = new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.10.2-12.18.3.2185/forge-1.10.2-12.18.3.2185-installer.jar"); - worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9395/download/worldedit-forge-mc1.10.2-6.1.4-SNAPSHOT-dist.jar"); - worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/239/WorldEditCuiFe-v1.0.6-mf-1.10.2-12.18.2.2125.jar"); - break; - case "v194": - forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.9.4-12.17.0.2051/forge-1.9.4-12.17.0.2051-installer.jar"); - worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9171/download/worldedit-forge-mc1.9.4-6.1.3-SNAPSHOT-dist.jar"); - worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/236/WorldEditCuiFe-v1.0.6-mf-1.9.4-12.17.0.1976.jar"); - break; - case "v189": - forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.8.9-11.15.1.1902-1.8.9/forge-1.8.9-11.15.1.1902-1.8.9-installer.jar"); - worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/8755/download/worldedit-forge-mc1.8.9-6.1.1-dist.jar"); - worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/235/WorldEditCuiFe-v1.0.6-mf-1.8.9-11.15.1.1855.jar"); - break; - case "v1710": - forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.7.10-10.13.4.1614-1.7.10/forge-1.7.10-10.13.4.1614-1.7.10-installer.jar"); - worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9194/download/worldedit-forge-mc1.7.10-6.1.2-SNAPSHOT-dist.jar"); - worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/234/WorldEditCuiFe-v1.0.6-mf-1.7.10-10.13.4.1566.jar"); - break; - default: - return; - } - } catch (MalformedURLException e) { - e.printStackTrace(); - return; + Class.forName("com.boydti.fawe.forge." + version + ".ForgeChunk_All"); + supportedString = version; + break; + } catch (ClassNotFoundException ignore) { } - try { // install forge - debug("Downloading forge installer from:\n - https://files.minecraftforge.net/"); - URLClassLoader loader = new URLClassLoader(new URL[]{forgeUrl}); - debug("Connected"); - Class forgeInstallClass = loader.loadClass("net.minecraftforge.installer.ClientInstall"); - debug("Found ClientInstall class"); - Object forgeInstallInstance = forgeInstallClass.newInstance(); - debug(forgeInstallInstance + " | " + forgeInstallClass + " | " + StringMan.getString(forgeInstallClass.getMethods())); - debug("Created instance " + forgeInstallInstance); - Method methodRun = forgeInstallClass.getDeclaredMethods()[0];//("run", File.class, Predicate.class); - Object alwaysTrue = loader.loadClass("com.google.common.base.Predicates").getDeclaredMethod("alwaysTrue").invoke(null); - methodRun.invoke(forgeInstallInstance, dirMc, alwaysTrue); - debug("Forge profile created, now installing WorldEdit"); - } catch (Throwable e) { - e.printStackTrace(); - prompt("[ERROR] Forge install failed, download from:\nhttps://files.minecraftforge.net/"); - } - File mods = new File(dirMc, "mods"); - if (!mods.exists()) { - debug("Creating mods directory"); - mods.mkdirs(); - } else { - for (File file : mods.listFiles()) { - String name = file.getName().toLowerCase(); - if ((name.contains("worldedit") || name.contains("fawe"))) { - debug("Delete existing: " + file.getName()); - file.delete(); - } - } - } - try { // install worldedit - debug("Downloading WE-CUI from:\n - https://minecraft.curseforge.com/projects/worldeditcui-forge-edition"); - try (ReadableByteChannel rbc = Channels.newChannel(worldEditCuiUrl.openStream())) { - try (FileOutputStream fos = new FileOutputStream(new File(mods, "WorldEditCUI.jar"))) { - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - } - } - debug("Successfully downloaded WorldEdit-CUI"); - } catch (Throwable e) { - prompt("[ERROR] WorldEdit install failed, download from:\nhttp://builds.enginehub.org/job/worldedit"); - } - try { // install worldedit - debug("Downloading WorldEdit from:\n - http://builds.enginehub.org/job/worldedit"); - try (ReadableByteChannel rbc = Channels.newChannel(worldEditUrl.openStream())) { - try (FileOutputStream fos = new FileOutputStream(new File(mods, "WorldEdit.jar"))) { - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - - } - } - debug("Successfully downloaded WorldEdit"); - } catch (Throwable e) { - prompt("[ERROR] WorldEdit install failed, download from:\nhttp://builds.enginehub.org/job/worldedit"); - } - try { // install FAWE - debug("Copying FastAsyncWorldEdit to mods directory"); - File file = new File(InstallerFrame.class.getProtectionDomain().getCodeSource().getLocation().getPath()); - debug(" - " + file.getPath()); - MainUtil.copyFile(file, new File(mods, "FastAsyncWorldEdit.jar")); - debug("Installation complete!"); - } catch (Throwable e) { - prompt("[ERROR] Copy installer failed, please copy this installer jar manually"); - } - prompt("Installation complete!\nLaunch the game using the forge profile."); } + if (supportedString == null) { + prompt("This version of FAWE cannot be installed this way."); + return; + } + debug("Selected version " + supportedString); + URL forgeUrl; + URL worldEditUrl; + URL worldEditCuiUrl; + try { + switch (supportedString) { + case "v111": + forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.11.2-13.20.0.2201/forge-1.11.2-13.20.0.2201-installer.jar"); + worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9593/download/worldedit-forge-mc1.11-6.1.6-SNAPSHOT-dist.jar"); + worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/241/worldeditcuife-v1.0.6-mf-1.11.2-13.20.0.2201.jar"); + break; + case "v110": + forgeUrl = new URL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.10.2-12.18.3.2185/forge-1.10.2-12.18.3.2185-installer.jar"); + worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9395/download/worldedit-forge-mc1.10.2-6.1.4-SNAPSHOT-dist.jar"); + worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/239/WorldEditCuiFe-v1.0.6-mf-1.10.2-12.18.2.2125.jar"); + break; + case "v194": + forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.9.4-12.17.0.2051/forge-1.9.4-12.17.0.2051-installer.jar"); + worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9171/download/worldedit-forge-mc1.9.4-6.1.3-SNAPSHOT-dist.jar"); + worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/236/WorldEditCuiFe-v1.0.6-mf-1.9.4-12.17.0.1976.jar"); + break; + case "v189": + forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.8.9-11.15.1.1902-1.8.9/forge-1.8.9-11.15.1.1902-1.8.9-installer.jar"); + worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/8755/download/worldedit-forge-mc1.8.9-6.1.1-dist.jar"); + worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/235/WorldEditCuiFe-v1.0.6-mf-1.8.9-11.15.1.1855.jar"); + break; + case "v1710": + forgeUrl = new URL("https://files.minecraftforge.net/maven/net/minecraftforge/forge/1.7.10-10.13.4.1614-1.7.10/forge-1.7.10-10.13.4.1614-1.7.10-installer.jar"); + worldEditUrl = new URL("http://builds.enginehub.org/job/worldedit/9194/download/worldedit-forge-mc1.7.10-6.1.2-SNAPSHOT-dist.jar"); + worldEditCuiUrl = new URL("https://addons-origin.cursecdn.com/files/2361/234/WorldEditCuiFe-v1.0.6-mf-1.7.10-10.13.4.1566.jar"); + break; + default: + return; + } + } catch (MalformedURLException e) { + e.printStackTrace(); + return; + } + try { // install forge + debug("Downloading forge installer from:\n - https://files.minecraftforge.net/"); + URLClassLoader loader = new URLClassLoader(new URL[]{forgeUrl}); + debug("Connected"); + Class forgeInstallClass = loader.loadClass("net.minecraftforge.installer.ClientInstall"); + debug("Found ClientInstall class"); + Object forgeInstallInstance = forgeInstallClass.newInstance(); + debug(forgeInstallInstance + " | " + forgeInstallClass + " | " + StringMan.getString(forgeInstallClass.getMethods())); + debug("Created instance " + forgeInstallInstance); + Method methodRun = forgeInstallClass.getDeclaredMethods()[0];//("run", File.class, Predicate.class); + Object alwaysTrue = loader.loadClass("com.google.common.base.Predicates").getDeclaredMethod("alwaysTrue").invoke(null); + methodRun.invoke(forgeInstallInstance, dirMc, alwaysTrue); + debug("Forge profile created, now installing WorldEdit"); + } catch (Throwable e) { + e.printStackTrace(); + prompt("[ERROR] Forge install failed, download from:\nhttps://files.minecraftforge.net/"); + } + File mods = new File(dirMc, "mods"); + if (!mods.exists()) { + debug("Creating mods directory"); + mods.mkdirs(); + } else { + for (File file : mods.listFiles()) { + String name1 = file.getName().toLowerCase(); + if ((name1.contains("worldedit") || name1.contains("fawe"))) { + debug("Delete existing: " + file.getName()); + file.delete(); + } + } + } + try { // install worldedit + debug("Downloading WE-CUI from:\n - https://minecraft.curseforge.com/projects/worldeditcui-forge-edition"); + try (ReadableByteChannel rbc = Channels.newChannel(worldEditCuiUrl.openStream())) { + try (FileOutputStream fos = new FileOutputStream(new File(mods, "WorldEditCUI.jar"))) { + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + } + } + debug("Successfully downloaded WorldEdit-CUI"); + } catch (Throwable e) { + prompt("[ERROR] WorldEdit install failed, download from:\nhttp://builds.enginehub.org/job/worldedit"); + } + try { // install worldedit + debug("Downloading WorldEdit from:\n - http://builds.enginehub.org/job/worldedit"); + try (ReadableByteChannel rbc = Channels.newChannel(worldEditUrl.openStream())) { + try (FileOutputStream fos = new FileOutputStream(new File(mods, "WorldEdit.jar"))) { + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + + } + } + debug("Successfully downloaded WorldEdit"); + } catch (Throwable e) { + prompt("[ERROR] WorldEdit install failed, download from:\nhttp://builds.enginehub.org/job/worldedit"); + } + try { // install FAWE + debug("Copying FastAsyncWorldEdit to mods directory"); + File file = new File(InstallerFrame.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + debug(" - " + file.getPath()); + MainUtil.copyFile(file, new File(mods, "FastAsyncWorldEdit.jar")); + debug("Installation complete!"); + } catch (Throwable e) { + prompt("[ERROR] Copy installer failed, please copy this installer jar manually"); + } + prompt("Installation complete!\nLaunch the game using the forge profile."); }); installThread.start(); } public void fadeIn() { - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - for (float i = 0; i <= 1; i += 0.001) { - InstallerFrame.this.setOpacity(i); - try { - Thread.sleep(1); - } catch (InterruptedException e) { - e.printStackTrace(); - } + Thread thread = new Thread(() -> { + for (float i = 0; i <= 1; i += 0.001) { + InstallerFrame.this.setOpacity(i); + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); } } }); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/BitStream.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/BitStream.java deleted file mode 100644 index 6957593fa..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/BitStream.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -import static com.boydti.fawe.object.io.zstd.UnsafeUtil.UNSAFE; -import static com.boydti.fawe.object.io.zstd.Util.highestBit; -import static com.boydti.fawe.object.io.zstd.Util.verify; -import static com.boydti.fawe.object.io.zstd.ZstdFrameDecompressor.SIZE_OF_LONG; - -/** - * Bit streams are encoded as a byte-aligned little-endian stream. Thus, bits are laid out - * in the following manner, and the stream is read from right to left. - *

- *

- * ... [16 17 18 19 20 21 22 23] [8 9 10 11 12 13 14 15] [0 1 2 3 4 5 6 7] - */ -class BitStream -{ - private BitStream() - { - } - - public static boolean isEndOfStream(long startAddress, long currentAddress, int bitsConsumed) - { - return startAddress == currentAddress && bitsConsumed == Long.SIZE; - } - - static long readTail(Object inputBase, long inputAddress, int inputSize) - { - long bits = UNSAFE.getByte(inputBase, inputAddress) & 0xFF; - - switch (inputSize) { - case 7: - bits |= (UNSAFE.getByte(inputBase, inputAddress + 6) & 0xFFL) << 48; - case 6: - bits |= (UNSAFE.getByte(inputBase, inputAddress + 5) & 0xFFL) << 40; - case 5: - bits |= (UNSAFE.getByte(inputBase, inputAddress + 4) & 0xFFL) << 32; - case 4: - bits |= (UNSAFE.getByte(inputBase, inputAddress + 3) & 0xFFL) << 24; - case 3: - bits |= (UNSAFE.getByte(inputBase, inputAddress + 2) & 0xFFL) << 16; - case 2: - bits |= (UNSAFE.getByte(inputBase, inputAddress + 1) & 0xFFL) << 8; - } - - return bits; - } - - /** - * @return numberOfBits in the low order bits of a long - */ - public static long peekBits(int bitsConsumed, long bitContainer, int numberOfBits) - { - return (((bitContainer << bitsConsumed) >>> 1) >>> (63 - numberOfBits)); - } - - /** - * numberOfBits must be > 0 - * - * @return numberOfBits in the low order bits of a long - */ - public static long peekBitsFast(int bitsConsumed, long bitContainer, int numberOfBits) - { - return ((bitContainer << bitsConsumed) >>> (64 - numberOfBits)); - } - - static class Initializer - { - private final Object inputBase; - private final long startAddress; - private final long endAddress; - private long bits; - private long currentAddress; - private int bitsConsumed; - - public Initializer(Object inputBase, long startAddress, long endAddress) - { - this.inputBase = inputBase; - this.startAddress = startAddress; - this.endAddress = endAddress; - } - - public long getBits() - { - return bits; - } - - public long getCurrentAddress() - { - return currentAddress; - } - - public int getBitsConsumed() - { - return bitsConsumed; - } - - public void initialize() - { - verify(endAddress - startAddress >= 1, startAddress, "Bitstream is empty"); - - int lastByte = UNSAFE.getByte(inputBase, endAddress - 1) & 0xFF; - verify(lastByte != 0, endAddress, "Bitstream end mark not present"); - - bitsConsumed = SIZE_OF_LONG - highestBit(lastByte); - - int inputSize = (int) (endAddress - startAddress); - if (inputSize >= SIZE_OF_LONG) { /* normal case */ - currentAddress = endAddress - SIZE_OF_LONG; - bits = UNSAFE.getLong(inputBase, currentAddress); - } - else { - currentAddress = startAddress; - bits = readTail(inputBase, startAddress, inputSize); - - bitsConsumed += (SIZE_OF_LONG - inputSize) * 8; - } - } - } - - static final class Loader - { - private final Object inputBase; - private final long startAddress; - private long bits; - private long currentAddress; - private int bitsConsumed; - private boolean overflow; - - public Loader(Object inputBase, long startAddress, long currentAddress, long bits, int bitsConsumed) - { - this.inputBase = inputBase; - this.startAddress = startAddress; - this.bits = bits; - this.currentAddress = currentAddress; - this.bitsConsumed = bitsConsumed; - } - - public long getBits() - { - return bits; - } - - public long getCurrentAddress() - { - return currentAddress; - } - - public int getBitsConsumed() - { - return bitsConsumed; - } - - public boolean isOverflow() - { - return overflow; - } - - public boolean load() - { - if (bitsConsumed > 64) { - overflow = true; - return true; - } - - else if (currentAddress == startAddress) { - return true; - } - - int bytes = bitsConsumed >>> 3; // divide by 8 - if (currentAddress >= startAddress + SIZE_OF_LONG) { - if (bytes > 0) { - currentAddress -= bytes; - bits = UNSAFE.getLong(inputBase, currentAddress); - } - bitsConsumed &= 0b111; - } - else if (currentAddress - bytes < startAddress) { - bytes = (int) (currentAddress - startAddress); - currentAddress = startAddress; - bitsConsumed -= bytes * SIZE_OF_LONG; - bits = UNSAFE.getLong(inputBase, startAddress); - return true; - } - else { - currentAddress -= bytes; - bitsConsumed -= bytes * SIZE_OF_LONG; - bits = UNSAFE.getLong(inputBase, currentAddress); - } - - return false; - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/FiniteStateEntropy.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/FiniteStateEntropy.java deleted file mode 100644 index 9569b3dbc..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/FiniteStateEntropy.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -import static com.boydti.fawe.object.io.zstd.BitStream.peekBits; -import static com.boydti.fawe.object.io.zstd.FseTableReader.FSE_MAX_SYMBOL_VALUE; -import static com.boydti.fawe.object.io.zstd.UnsafeUtil.UNSAFE; -import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; - -class FiniteStateEntropy -{ - private static final int MAX_TABLE_LOG = 12; - - private final FiniteStateEntropy.Table table; - private final FseTableReader reader = new FseTableReader(); - - public FiniteStateEntropy(int maxLog) - { - table = new FiniteStateEntropy.Table(maxLog); - } - - public int decompress(final Object inputBase, final long inputAddress, final long inputLimit, byte[] weights) - { - long input = inputAddress; - input += reader.readFseTable(table, inputBase, input, inputLimit, FSE_MAX_SYMBOL_VALUE, MAX_TABLE_LOG); - - final Object outputBase = weights; - final long outputAddress = ARRAY_BYTE_BASE_OFFSET; - final long outputLimit = outputAddress + weights.length; - - long output = outputAddress; - - // initialize bit stream - BitStream.Initializer initializer = new BitStream.Initializer(inputBase, input, inputLimit); - initializer.initialize(); - int bitsConsumed = initializer.getBitsConsumed(); - long currentAddress = initializer.getCurrentAddress(); - long bits = initializer.getBits(); - - // initialize first FSE stream - int state1 = (int) peekBits(bitsConsumed, bits, table.log2Size); - bitsConsumed += table.log2Size; - - BitStream.Loader loader = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - loader.load(); - bits = loader.getBits(); - bitsConsumed = loader.getBitsConsumed(); - currentAddress = loader.getCurrentAddress(); - - // initialize second FSE stream - int state2 = (int) peekBits(bitsConsumed, bits, table.log2Size); - bitsConsumed += table.log2Size; - - loader = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - loader.load(); - bits = loader.getBits(); - bitsConsumed = loader.getBitsConsumed(); - currentAddress = loader.getCurrentAddress(); - - byte[] symbols = table.symbol; - byte[] numbersOfBits = table.numberOfBits; - int[] newStates = table.newState; - - // decode 4 symbols per loop - while (output < outputLimit) { - int numberOfBits; - - UNSAFE.putByte(outputBase, output, symbols[state1]); - numberOfBits = numbersOfBits[state1]; - state1 = (int) (newStates[state1] + peekBits(bitsConsumed, bits, numberOfBits)); - bitsConsumed += numberOfBits; - - UNSAFE.putByte(outputBase, output + 1, symbols[state2]); - numberOfBits = numbersOfBits[state2]; - state2 = (int) (newStates[state2] + peekBits(bitsConsumed, bits, numberOfBits)); - bitsConsumed += numberOfBits; - - UNSAFE.putByte(outputBase, output + 2, symbols[state1]); - numberOfBits = numbersOfBits[state1]; - state1 = (int) (newStates[state1] + peekBits(bitsConsumed, bits, numberOfBits)); - bitsConsumed += numberOfBits; - - UNSAFE.putByte(outputBase, output + 3, symbols[state2]); - numberOfBits = numbersOfBits[state2]; - state2 = (int) (newStates[state2] + peekBits(bitsConsumed, bits, numberOfBits)); - bitsConsumed += numberOfBits; - - output += ZstdFrameDecompressor.SIZE_OF_INT; - - loader = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - boolean done = loader.load(); - bitsConsumed = loader.getBitsConsumed(); - bits = loader.getBits(); - currentAddress = loader.getCurrentAddress(); - if (done) { - break; - } - } - - while (true) { - UNSAFE.putByte(outputBase, output++, symbols[state1]); - int numberOfBits = numbersOfBits[state1]; - state1 = (int) (newStates[state1] + peekBits(bitsConsumed, bits, numberOfBits)); - bitsConsumed += numberOfBits; - - loader = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - loader.load(); - bitsConsumed = loader.getBitsConsumed(); - bits = loader.getBits(); - currentAddress = loader.getCurrentAddress(); - - if (loader.isOverflow()) { - UNSAFE.putByte(outputBase, output++, symbols[state2]); - break; - } - - UNSAFE.putByte(outputBase, output++, symbols[state2]); - int numberOfBits1 = numbersOfBits[state2]; - state2 = (int) (newStates[state2] + peekBits(bitsConsumed, bits, numberOfBits1)); - bitsConsumed += numberOfBits1; - - loader = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - loader.load(); - bitsConsumed = loader.getBitsConsumed(); - bits = loader.getBits(); - currentAddress = loader.getCurrentAddress(); - - if (loader.isOverflow()) { - UNSAFE.putByte(outputBase, output++, symbols[state1]); - break; - } - } - - return (int) (output - outputAddress); - } - - public static final class Table - { - int log2Size; - final int[] newState; - final byte[] symbol; - final byte[] numberOfBits; - - public Table(int log2Size) - { - int size = 1 << log2Size; - newState = new int[size]; - symbol = new byte[size]; - numberOfBits = new byte[size]; - } - - public Table(int log2Size, int[] newState, byte[] symbol, byte[] numberOfBits) - { - int size = 1 << log2Size; - if (newState.length != size || symbol.length != size || numberOfBits.length != size) { - throw new IllegalArgumentException("Expected arrays to match provided size"); - } - - this.log2Size = log2Size; - this.newState = newState; - this.symbol = symbol; - this.numberOfBits = numberOfBits; - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/FseTableReader.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/FseTableReader.java deleted file mode 100644 index bce65eac2..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/FseTableReader.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -import static com.boydti.fawe.object.io.zstd.UnsafeUtil.UNSAFE; -import static com.boydti.fawe.object.io.zstd.Util.highestBit; -import static com.boydti.fawe.object.io.zstd.Util.verify; - -class FseTableReader -{ - private static final int FSE_MIN_TABLE_LOG = 5; - - public static final int FSE_MAX_SYMBOL_VALUE = 255; - private final short[] nextSymbol = new short[FSE_MAX_SYMBOL_VALUE + 1]; - private final short[] normalizedCounters = new short[FSE_MAX_SYMBOL_VALUE + 1]; - - public int readFseTable(FiniteStateEntropy.Table table, Object inputBase, long inputAddress, long inputLimit, int maxSymbol, int maxTableLog) - { - // read table headers - long input = inputAddress; - verify(inputLimit - inputAddress >= 4, input, "Not enough input bytes"); - - int threshold; - int symbolNumber = 0; - boolean previousIsZero = false; - - int bitStream = UNSAFE.getInt(inputBase, input); - - int tableLog = (bitStream & 0xF) + FSE_MIN_TABLE_LOG; - - int numberOfBits = tableLog + 1; - bitStream >>>= 4; - int bitCount = 4; - - verify(tableLog <= maxTableLog, input, "FSE table size exceeds maximum allowed size"); - - int remaining = (1 << tableLog) + 1; - threshold = 1 << tableLog; - - while (remaining > 1 && symbolNumber <= maxSymbol) { - if (previousIsZero) { - int n0 = symbolNumber; - while ((bitStream & 0xFFFF) == 0xFFFF) { - n0 += 24; - if (input < inputLimit - 5) { - input += 2; - bitStream = (UNSAFE.getInt(inputBase, input) >>> bitCount); - } - else { - // end of bit stream - bitStream >>>= 16; - bitCount += 16; - } - } - while ((bitStream & 3) == 3) { - n0 += 3; - bitStream >>>= 2; - bitCount += 2; - } - n0 += bitStream & 3; - bitCount += 2; - - verify(n0 <= maxSymbol, input, "Symbol larger than max value"); - - while (symbolNumber < n0) { - normalizedCounters[symbolNumber++] = 0; - } - if ((input <= inputLimit - 7) || (input + (bitCount >>> 3) <= inputLimit - 4)) { - input += bitCount >>> 3; - bitCount &= 7; - bitStream = UNSAFE.getInt(inputBase, input) >>> bitCount; - } - else { - bitStream >>>= 2; - } - } - - short max = (short) ((2 * threshold - 1) - remaining); - short count; - - if ((bitStream & (threshold - 1)) < max) { - count = (short) (bitStream & (threshold - 1)); - bitCount += numberOfBits - 1; - } - else { - count = (short) (bitStream & (2 * threshold - 1)); - if (count >= threshold) { - count -= max; - } - bitCount += numberOfBits; - } - count--; // extra accuracy - - remaining -= Math.abs(count); - normalizedCounters[symbolNumber++] = count; - previousIsZero = count == 0; - while (remaining < threshold) { - numberOfBits--; - threshold >>>= 1; - } - - if ((input <= inputLimit - 7) || (input + (bitCount >> 3) <= inputLimit - 4)) { - input += bitCount >>> 3; - bitCount &= 7; - } - else { - bitCount -= (int) (8 * (inputLimit - 4 - input)); - input = inputLimit - 4; - } - bitStream = UNSAFE.getInt(inputBase, input) >>> (bitCount & 31); - } - - verify(remaining == 1 && bitCount <= 32, input, "Input is corrupted"); - - maxSymbol = symbolNumber - 1; - verify(maxSymbol <= FSE_MAX_SYMBOL_VALUE, input, "Max symbol value too large (too many symbols for FSE)"); - - input += (bitCount + 7) >> 3; - - // populate decoding table - int symbolCount = maxSymbol + 1; - int tableSize = 1 << tableLog; - int highThreshold = tableSize - 1; - - table.log2Size = tableLog; - - for (byte symbol = 0; symbol < symbolCount; symbol++) { - if (normalizedCounters[symbol] == -1) { - table.symbol[highThreshold--] = symbol; - nextSymbol[symbol] = 1; - } - else { - nextSymbol[symbol] = normalizedCounters[symbol]; - } - } - - // spread symbols - int tableMask = tableSize - 1; - int step = (tableSize >>> 1) + (tableSize >>> 3) + 3; - int position = 0; - for (byte symbol = 0; symbol < symbolCount; symbol++) { - for (int i = 0; i < normalizedCounters[symbol]; i++) { - table.symbol[position] = symbol; - do { - position = (position + step) & tableMask; - } - while (position > highThreshold); - } - } - - // position must reach all cells once, otherwise normalizedCounter is incorrect - verify(position == 0, input, "Input is corrupted"); - - for (int i = 0; i < tableSize; i++) { - byte symbol = table.symbol[i]; - short nextState = nextSymbol[symbol]++; - table.numberOfBits[i] = (byte) (tableLog - highestBit(nextState)); - table.newState[i] = (short) ((nextState << table.numberOfBits[i]) - tableSize); - } - - return (int) (input - inputAddress); - } - - public static void buildRleTable(FiniteStateEntropy.Table table, byte value) - { - table.log2Size = 0; - table.symbol[0] = value; - table.newState[0] = 0; - table.numberOfBits[0] = 0; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/Huffman.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/Huffman.java deleted file mode 100644 index 990de4968..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/Huffman.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -import java.util.Arrays; - - -import static com.boydti.fawe.object.io.zstd.BitStream.isEndOfStream; -import static com.boydti.fawe.object.io.zstd.BitStream.peekBitsFast; -import static com.boydti.fawe.object.io.zstd.UnsafeUtil.UNSAFE; -import static com.boydti.fawe.object.io.zstd.Util.isPowerOf2; -import static com.boydti.fawe.object.io.zstd.Util.verify; -import static com.boydti.fawe.object.io.zstd.ZstdFrameDecompressor.SIZE_OF_INT; -import static com.boydti.fawe.object.io.zstd.ZstdFrameDecompressor.SIZE_OF_SHORT; - -class Huffman -{ - private static final int MAX_SYMBOL = 255; - private static final int MAX_TABLE_LOG = 12; - - // stats - private final byte[] weights = new byte[MAX_SYMBOL + 1]; - private final int[] ranks = new int[MAX_TABLE_LOG + 1]; - - // table - private int tableLog = -1; - private final byte[] symbols = new byte[1 << MAX_TABLE_LOG]; - private final byte[] numbersOfBits = new byte[1 << MAX_TABLE_LOG]; - - private final FiniteStateEntropy finiteStateEntropy = new FiniteStateEntropy(6); - - public boolean isLoaded() - { - return tableLog != -1; - } - - public int readTable(final Object inputBase, final long inputAddress, final int size) - { - Arrays.fill(ranks, 0); - long input = inputAddress; - - // read table header - verify(size > 0, input, "Not enough input bytes"); - int inputSize = UNSAFE.getByte(inputBase, input++) & 0xFF; - - int outputSize; - if (inputSize >= 128) { - outputSize = inputSize - 127; - inputSize = ((outputSize + 1) / 2); - - verify(inputSize + 1 <= size, input, "Not enough input bytes"); - verify(outputSize <= MAX_SYMBOL + 1, input, "Input is corrupted"); - - for (int i = 0; i < outputSize; i += 2) { - int value = UNSAFE.getByte(inputBase, input + i / 2) & 0xFF; - weights[i] = (byte) (value >>> 4); - weights[i + 1] = (byte) (value & 0b1111); - } - } - else { - verify(inputSize + 1 <= size, input, "Not enough input bytes"); - - outputSize = finiteStateEntropy.decompress(inputBase, input, input + inputSize, weights); - } - - int totalWeight = 0; - for (int i = 0; i < outputSize; i++) { - ranks[weights[i]]++; - totalWeight += (1 << weights[i]) >> 1; // TODO same as 1 << (weights[n] - 1)? - } - verify(totalWeight != 0, input, "Input is corrupted"); - - tableLog = Util.highestBit(totalWeight) + 1; - verify(tableLog <= MAX_TABLE_LOG, input, "Input is corrupted"); - - int total = 1 << tableLog; - int rest = total - totalWeight; - verify(isPowerOf2(rest), input, "Input is corrupted"); - - int lastWeight = Util.highestBit(rest) + 1; - - weights[outputSize] = (byte) lastWeight; - ranks[lastWeight]++; - - int numberOfSymbols = outputSize + 1; - - // populate table - int nextRankStart = 0; - for (int i = 1; i < tableLog + 1; ++i) { - int current = nextRankStart; - nextRankStart += ranks[i] << (i - 1); - ranks[i] = current; - } - - for (int n = 0; n < numberOfSymbols; n++) { - int weight = weights[n]; - int length = (1 << weight) >> 1; // TODO: 1 << (weight - 1) ?? - - byte symbol = (byte) n; - byte numberOfBits = (byte) (tableLog + 1 - weight); - for (int i = ranks[weight]; i < ranks[weight] + length; i++) { - symbols[i] = symbol; - numbersOfBits[i] = numberOfBits; - } - ranks[weight] += length; - } - - verify(ranks[1] >= 2 && (ranks[1] & 1) == 0, input, "Input is corrupted"); - - return inputSize + 1; - } - - public void decodeSingleStream(final Object inputBase, final long inputAddress, final long inputLimit, final Object outputBase, final long outputAddress, final long outputLimit) - { - BitStream.Initializer initializer = new BitStream.Initializer(inputBase, inputAddress, inputLimit); - initializer.initialize(); - - long bits = initializer.getBits(); - int bitsConsumed = initializer.getBitsConsumed(); - long currentAddress = initializer.getCurrentAddress(); - - int tableLog = this.tableLog; - byte[] numbersOfBits = this.numbersOfBits; - byte[] symbols = this.symbols; - - // 4 symbols at a time - long output = outputAddress; - long fastOutputLimit = outputLimit - 4; - while (output < fastOutputLimit) { - BitStream.Loader loader = new BitStream.Loader(inputBase, inputAddress, currentAddress, bits, bitsConsumed); - boolean done = loader.load(); - bits = loader.getBits(); - bitsConsumed = loader.getBitsConsumed(); - currentAddress = loader.getCurrentAddress(); - if (done) { - break; - } - - bitsConsumed = decodeSymbol(outputBase, output, bits, bitsConsumed, tableLog, numbersOfBits, symbols); - bitsConsumed = decodeSymbol(outputBase, output + 1, bits, bitsConsumed, tableLog, numbersOfBits, symbols); - bitsConsumed = decodeSymbol(outputBase, output + 2, bits, bitsConsumed, tableLog, numbersOfBits, symbols); - bitsConsumed = decodeSymbol(outputBase, output + 3, bits, bitsConsumed, tableLog, numbersOfBits, symbols); - output += SIZE_OF_INT; - } - - decodeTail(inputBase, inputAddress, currentAddress, bitsConsumed, bits, outputBase, output, outputLimit); - } - - public void decode4Streams(final Object inputBase, final long inputAddress, final long inputLimit, final Object outputBase, final long outputAddress, final long outputLimit) - { - verify(inputLimit - inputAddress >= 10, inputAddress, "Input is corrupted"); // jump table + 1 byte per stream - - long start1 = inputAddress + 3 * SIZE_OF_SHORT; // for the shorts we read below - long start2 = start1 + (UNSAFE.getShort(inputBase, inputAddress) & 0xFFFF); - long start3 = start2 + (UNSAFE.getShort(inputBase, inputAddress + 2) & 0xFFFF); - long start4 = start3 + (UNSAFE.getShort(inputBase, inputAddress + 4) & 0xFFFF); - - BitStream.Initializer initializer = new BitStream.Initializer(inputBase, start1, start2); - initializer.initialize(); - int stream1bitsConsumed = initializer.getBitsConsumed(); - long stream1currentAddress = initializer.getCurrentAddress(); - long stream1bits = initializer.getBits(); - - initializer = new BitStream.Initializer(inputBase, start2, start3); - initializer.initialize(); - int stream2bitsConsumed = initializer.getBitsConsumed(); - long stream2currentAddress = initializer.getCurrentAddress(); - long stream2bits = initializer.getBits(); - - initializer = new BitStream.Initializer(inputBase, start3, start4); - initializer.initialize(); - int stream3bitsConsumed = initializer.getBitsConsumed(); - long stream3currentAddress = initializer.getCurrentAddress(); - long stream3bits = initializer.getBits(); - - initializer = new BitStream.Initializer(inputBase, start4, inputLimit); - initializer.initialize(); - int stream4bitsConsumed = initializer.getBitsConsumed(); - long stream4currentAddress = initializer.getCurrentAddress(); - long stream4bits = initializer.getBits(); - - int segmentSize = (int) ((outputLimit - outputAddress + 3) / 4); - - long outputStart2 = outputAddress + segmentSize; - long outputStart3 = outputStart2 + segmentSize; - long outputStart4 = outputStart3 + segmentSize; - - long output1 = outputAddress; - long output2 = outputStart2; - long output3 = outputStart3; - long output4 = outputStart4; - - long fastOutputLimit = outputLimit - 7; - int tableLog = this.tableLog; - byte[] numbersOfBits = this.numbersOfBits; - byte[] symbols = this.symbols; - - while (output4 < fastOutputLimit) { - stream1bitsConsumed = decodeSymbol(outputBase, output1, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); - stream2bitsConsumed = decodeSymbol(outputBase, output2, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); - stream3bitsConsumed = decodeSymbol(outputBase, output3, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); - stream4bitsConsumed = decodeSymbol(outputBase, output4, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); - - stream1bitsConsumed = decodeSymbol(outputBase, output1 + 1, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); - stream2bitsConsumed = decodeSymbol(outputBase, output2 + 1, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); - stream3bitsConsumed = decodeSymbol(outputBase, output3 + 1, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); - stream4bitsConsumed = decodeSymbol(outputBase, output4 + 1, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); - - stream1bitsConsumed = decodeSymbol(outputBase, output1 + 2, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); - stream2bitsConsumed = decodeSymbol(outputBase, output2 + 2, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); - stream3bitsConsumed = decodeSymbol(outputBase, output3 + 2, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); - stream4bitsConsumed = decodeSymbol(outputBase, output4 + 2, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); - - stream1bitsConsumed = decodeSymbol(outputBase, output1 + 3, stream1bits, stream1bitsConsumed, tableLog, numbersOfBits, symbols); - stream2bitsConsumed = decodeSymbol(outputBase, output2 + 3, stream2bits, stream2bitsConsumed, tableLog, numbersOfBits, symbols); - stream3bitsConsumed = decodeSymbol(outputBase, output3 + 3, stream3bits, stream3bitsConsumed, tableLog, numbersOfBits, symbols); - stream4bitsConsumed = decodeSymbol(outputBase, output4 + 3, stream4bits, stream4bitsConsumed, tableLog, numbersOfBits, symbols); - - output1 += SIZE_OF_INT; - output2 += SIZE_OF_INT; - output3 += SIZE_OF_INT; - output4 += SIZE_OF_INT; - - BitStream.Loader loader = new BitStream.Loader(inputBase, start1, stream1currentAddress, stream1bits, stream1bitsConsumed); - boolean done = loader.load(); - stream1bitsConsumed = loader.getBitsConsumed(); - stream1bits = loader.getBits(); - stream1currentAddress = loader.getCurrentAddress(); - - if (done) { - break; - } - - loader = new BitStream.Loader(inputBase, start2, stream2currentAddress, stream2bits, stream2bitsConsumed); - done = loader.load(); - stream2bitsConsumed = loader.getBitsConsumed(); - stream2bits = loader.getBits(); - stream2currentAddress = loader.getCurrentAddress(); - - if (done) { - break; - } - - loader = new BitStream.Loader(inputBase, start3, stream3currentAddress, stream3bits, stream3bitsConsumed); - done = loader.load(); - stream3bitsConsumed = loader.getBitsConsumed(); - stream3bits = loader.getBits(); - stream3currentAddress = loader.getCurrentAddress(); - if (done) { - break; - } - - loader = new BitStream.Loader(inputBase, start4, stream4currentAddress, stream4bits, stream4bitsConsumed); - done = loader.load(); - stream4bitsConsumed = loader.getBitsConsumed(); - stream4bits = loader.getBits(); - stream4currentAddress = loader.getCurrentAddress(); - if (done) { - break; - } - } - - verify(output1 <= outputStart2 && output2 <= outputStart3 && output3 <= outputStart4, inputAddress, "Input is corrupted"); - - /// finish streams one by one - decodeTail(inputBase, start1, stream1currentAddress, stream1bitsConsumed, stream1bits, outputBase, output1, outputStart2); - decodeTail(inputBase, start2, stream2currentAddress, stream2bitsConsumed, stream2bits, outputBase, output2, outputStart3); - decodeTail(inputBase, start3, stream3currentAddress, stream3bitsConsumed, stream3bits, outputBase, output3, outputStart4); - decodeTail(inputBase, start4, stream4currentAddress, stream4bitsConsumed, stream4bits, outputBase, output4, outputLimit); - } - - private void decodeTail(final Object inputBase, final long startAddress, long currentAddress, int bitsConsumed, long bits, final Object outputBase, long outputAddress, final long outputLimit) - { - int tableLog = this.tableLog; - byte[] numbersOfBits = this.numbersOfBits; - byte[] symbols = this.symbols; - - // closer to the end - while (outputAddress < outputLimit) { - BitStream.Loader loader = new BitStream.Loader(inputBase, startAddress, currentAddress, bits, bitsConsumed); - boolean done = loader.load(); - bitsConsumed = loader.getBitsConsumed(); - bits = loader.getBits(); - currentAddress = loader.getCurrentAddress(); - if (done) { - break; - } - - bitsConsumed = decodeSymbol(outputBase, outputAddress++, bits, bitsConsumed, tableLog, numbersOfBits, symbols); - } - - // not more data in bit stream, so no need to reload - while (outputAddress < outputLimit) { - bitsConsumed = decodeSymbol(outputBase, outputAddress++, bits, bitsConsumed, tableLog, numbersOfBits, symbols); - } - - verify(isEndOfStream(startAddress, currentAddress, bitsConsumed), startAddress, "Bit stream is not fully consumed"); - } - - private static int decodeSymbol(Object outputBase, long outputAddress, long bitContainer, int bitsConsumed, int tableLog, byte[] numbersOfBits, byte[] symbols) - { - int value = (int) peekBitsFast(bitsConsumed, bitContainer, tableLog); - UNSAFE.putByte(outputBase, outputAddress, symbols[value]); - return bitsConsumed + numbersOfBits[value]; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/UnsafeUtil.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/UnsafeUtil.java deleted file mode 100644 index 6b6bbe167..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/UnsafeUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import sun.misc.Unsafe; - -import java.lang.reflect.Field; -import java.nio.Buffer; - -final class UnsafeUtil -{ - public static final Unsafe UNSAFE; - private static final Field ADDRESS_ACCESSOR; - - private UnsafeUtil() {} - - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(null); - } - catch (Exception e) { - throw new RuntimeException(e); - } - - try { - Field field = Buffer.class.getDeclaredField("address"); - field.setAccessible(true); - ADDRESS_ACCESSOR = field; - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static long getAddress(Buffer buffer) - { - try { - return (long) ADDRESS_ACCESSOR.get(buffer); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/ZstdDecompressor.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/ZstdDecompressor.java deleted file mode 100644 index fdba71bad..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/ZstdDecompressor.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -import java.nio.ByteBuffer; - - -import static com.boydti.fawe.object.io.zstd.UnsafeUtil.getAddress; -import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; - -public class ZstdDecompressor -{ - private final ZstdFrameDecompressor decompressor = new ZstdFrameDecompressor(); - - public int decompress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int maxOutputLength) - throws MalformedInputException - { - long inputAddress = ARRAY_BYTE_BASE_OFFSET + inputOffset; - long inputLimit = inputAddress + inputLength; - long outputAddress = ARRAY_BYTE_BASE_OFFSET + outputOffset; - long outputLimit = outputAddress + maxOutputLength; - - return decompressor.decompress(input, inputAddress, inputLimit, output, outputAddress, outputLimit); - } - - public void decompress(ByteBuffer input, ByteBuffer output) - throws MalformedInputException - { - Object inputBase; - long inputAddress; - long inputLimit; - if (input.isDirect()) { - inputBase = null; - long address = getAddress(input); - inputAddress = address + input.position(); - inputLimit = address + input.limit(); - } - else if (input.hasArray()) { - inputBase = input.array(); - inputAddress = ARRAY_BYTE_BASE_OFFSET + input.arrayOffset() + input.position(); - inputLimit = ARRAY_BYTE_BASE_OFFSET + input.arrayOffset() + input.limit(); - } - else { - throw new IllegalArgumentException("Unsupported input ByteBuffer implementation " + input.getClass().getName()); - } - - Object outputBase; - long outputAddress; - long outputLimit; - if (output.isDirect()) { - outputBase = null; - long address = getAddress(output); - outputAddress = address + output.position(); - outputLimit = address + output.limit(); - } - else if (output.hasArray()) { - outputBase = output.array(); - outputAddress = ARRAY_BYTE_BASE_OFFSET + output.arrayOffset() + output.position(); - outputLimit = ARRAY_BYTE_BASE_OFFSET + output.arrayOffset() + output.limit(); - } - else { - throw new IllegalArgumentException("Unsupported output ByteBuffer implementation " + output.getClass().getName()); - } - - // HACK: Assure JVM does not collect Slice wrappers while decompressing, since the - // collection may trigger freeing of the underlying memory resulting in a segfault - // There is no other known way to signal to the JVM that an object should not be - // collected in a block, and technically, the JVM is allowed to eliminate these locks. - synchronized (input) { - synchronized (output) { - int written = new ZstdFrameDecompressor().decompress(inputBase, inputAddress, inputLimit, outputBase, outputAddress, outputLimit); - output.position(output.position() + written); - } - } - } - - public static long getDecompressedSize(byte[] input, int offset, int length) - { - int baseAddress = ARRAY_BYTE_BASE_OFFSET + offset; - return ZstdFrameDecompressor.getDecompressedSize(input, baseAddress, baseAddress + length); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/ZstdFrameDecompressor.java b/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/ZstdFrameDecompressor.java deleted file mode 100644 index 83c359fb4..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/io/zstd/ZstdFrameDecompressor.java +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.boydti.fawe.object.io.zstd; - -import java.util.Arrays; - - -import static com.boydti.fawe.object.io.zstd.BitStream.peekBits; -import static com.boydti.fawe.object.io.zstd.UnsafeUtil.UNSAFE; -import static com.boydti.fawe.object.io.zstd.Util.fail; -import static com.boydti.fawe.object.io.zstd.Util.mask; -import static com.boydti.fawe.object.io.zstd.Util.verify; -import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; - -class ZstdFrameDecompressor -{ - private static final int MIN_MATCH = 3; - - private static final int[] DEC_32_TABLE = {4, 1, 2, 1, 4, 4, 4, 4}; - private static final int[] DEC_64_TABLE = {0, 0, 0, -1, 0, 1, 2, 3}; - - private static final int MAGIC_NUMBER = 0xFD2FB528; // v0.5 - - private static final int MIN_SEQUENCES_SIZE = 1; - private static final int MIN_BLOCK_SIZE = 1 // block type tag - + 1 // min size of raw or rle length header - + MIN_SEQUENCES_SIZE; - - private static final int MAX_BLOCK_SIZE = 128 * 1024; - - private static final int MIN_WINDOW_LOG = 10; - private static final int MAX_WINDOW_SIZE = 1 << 23; - - public static final int SIZE_OF_BYTE = 1; - public static final int SIZE_OF_SHORT = 2; - public static final int SIZE_OF_INT = 4; - public static final int SIZE_OF_LONG = 8; - - private static final long SIZE_OF_BLOCK_HEADER = 3; - - // block types - private static final int RAW_BLOCK = 0; - private static final int RLE_BLOCK = 1; - private static final int COMPRESSED_BLOCK = 2; - - // literal block types - private static final int RAW_LITERALS_BLOCK = 0; - private static final int RLE_LITERALS_BLOCK = 1; - private static final int COMPRESSED_LITERALS_BLOCK = 2; - private static final int REPEAT_STATS_LITERALS_BLOCK = 3; - - private static final int LONG_NUMBER_OF_SEQUENCES = 0x7F00; - - private static final int MAX_LITERALS_LENGTH_SYMBOL = 35; - private static final int MAX_MATCH_LENGTH_SYMBOL = 52; - private static final int MAX_OFFSET_CODE_SYMBOL = 28; - - private static final int LITERALS_LENGTH_FSE_LOG = 9; - private static final int MATCH_LENGTH_FSE_LOG = 9; - private static final int OFFSET_CODES_FSE_LOG = 8; - - private static final int SET_BASIC = 0; - private static final int SET_RLE = 1; - private static final int SET_COMPRESSED = 2; - private static final int SET_REPEAT = 3; - - private static final int[] LITERALS_LENGTH_BASE = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, - 0x2000, 0x4000, 0x8000, 0x10000}; - - private static final int[] MATCH_LENGTH_BASE = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, - 0x1003, 0x2003, 0x4003, 0x8003, 0x10003}; - - private static final int[] OFFSET_CODES_BASE = { - 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, - 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, - 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, - 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD}; - - private static final int[] LITERALS_LENGTH_BITS = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16}; - - private static final int[] MATCH_LENGTH_BITS = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16}; - - private static final FiniteStateEntropy.Table DEFAULT_LITERALS_LENGTH_TABLE = new FiniteStateEntropy.Table( - 6, - new int[] { - 0, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 32, 0, 0, 32, 0, 32, 0, 32, 0, 0, 32, 0, 32, 0, 32, 0, 0, 16, 32, 0, 0, 48, 16, 32, 32, 32, - 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0}, - new byte[] { - 0, 0, 1, 3, 4, 6, 7, 9, 10, 12, 14, 16, 18, 19, 21, 22, 24, 25, 26, 27, 29, 31, 0, 1, 2, 4, 5, 7, 8, 10, 11, 13, 16, 17, 19, 20, 22, 23, 25, 25, 26, 28, 30, 0, - 1, 2, 3, 5, 6, 8, 9, 11, 12, 15, 17, 18, 20, 21, 23, 24, 35, 34, 33, 32}, - new byte[] { - 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 4, 4, 5, 6, 6, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6}); - - private static final FiniteStateEntropy.Table DEFAULT_OFFSET_CODES_TABLE = new FiniteStateEntropy.Table( - 5, - new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0}, - new byte[] {0, 6, 9, 15, 21, 3, 7, 12, 18, 23, 5, 8, 14, 20, 2, 7, 11, 17, 22, 4, 8, 13, 19, 1, 6, 10, 16, 28, 27, 26, 25, 24}, - new byte[] {5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5}); - - private static final FiniteStateEntropy.Table DEFAULT_MATCH_LENGTH_TABLE = new FiniteStateEntropy.Table( - 6, - new int[] { - 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 32, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 48, 16, 32, 32, 32, 32, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - new byte[] { - 0, 1, 2, 3, 5, 6, 8, 10, 13, 16, 19, 22, 25, 28, 31, 33, 35, 37, 39, 41, 43, 45, 1, 2, 3, 4, 6, 7, 9, 12, 15, 18, 21, 24, 27, 30, 32, 34, 36, 38, 40, 42, 44, 1, - 1, 2, 4, 5, 7, 8, 11, 14, 17, 20, 23, 26, 29, 52, 51, 50, 49, 48, 47, 46}, - new byte[] { - 6, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}); - - private final byte[] literals = new byte[MAX_BLOCK_SIZE + SIZE_OF_LONG]; // extra space to allow for long-at-a-time copy - - // current buffer containing literals - private Object literalsBase; - private long literalsAddress; - private long literalsLimit; - - private final int[] previousOffsets = new int[3]; - - private final FiniteStateEntropy.Table literalsLengthTable = new FiniteStateEntropy.Table(LITERALS_LENGTH_FSE_LOG); - private final FiniteStateEntropy.Table offsetCodesTable = new FiniteStateEntropy.Table(OFFSET_CODES_FSE_LOG); - private final FiniteStateEntropy.Table matchLengthTable = new FiniteStateEntropy.Table(MATCH_LENGTH_FSE_LOG); - - private FiniteStateEntropy.Table currentLiteralsLengthTable; - private FiniteStateEntropy.Table currentOffsetCodesTable; - private FiniteStateEntropy.Table currentMatchLengthTable; - - private final Huffman huffman = new Huffman(); - private final FseTableReader fse = new FseTableReader(); - - public int decompress( - final Object inputBase, - final long inputAddress, - final long inputLimit, - final Object outputBase, - final long outputAddress, - final long outputLimit) - { - if (outputAddress == outputLimit) { - return 0; - } - - reset(); - - long input = inputAddress; - long output = outputAddress; - - input += verifyMagic(inputBase, inputAddress, inputLimit); - - FrameHeader frameHeader = readFrameHeader(inputBase, input, inputLimit); - input += frameHeader.headerSize; - - boolean lastBlock; - do { - verify(input + SIZE_OF_BLOCK_HEADER <= inputLimit, input, "Not enough input bytes"); - - // read block header - int header = UNSAFE.getInt(inputBase, input) & 0xFF_FFFF; - input += SIZE_OF_BLOCK_HEADER; - - lastBlock = (header & 1) != 0; - int blockType = (header >>> 1) & 0b11; - int blockSize = (header >>> 3) & 0x1F_FFFF; // 21 bits - - int decodedSize; - switch (blockType) { - case RAW_BLOCK: - verify(inputAddress + blockSize <= inputLimit, input, "Not enough input bytes"); - decodedSize = decodeRawBlock(inputBase, input, blockSize, outputBase, output, outputLimit); - input += blockSize; - break; - case RLE_BLOCK: - verify(inputAddress + 1 <= inputLimit, input, "Not enough input bytes"); - decodedSize = decodeRleBlock(blockSize, inputBase, input, outputBase, output, outputLimit); - input += 1; - break; - case COMPRESSED_BLOCK: - verify(inputAddress + blockSize <= inputLimit, input, "Not enough input bytes"); - decodedSize = decodeCompressedBlock(inputBase, input, blockSize, outputBase, output, outputLimit, frameHeader.windowSize); - input += blockSize; - break; - default: - throw fail(input, "Invalid block type"); - } - - output += decodedSize; - } - while (!lastBlock); - - if (frameHeader.hasChecksum) { - // TODO checksum - } - - return (int) (output - outputAddress); - } - - private void reset() - { - previousOffsets[0] = 1; - previousOffsets[1] = 4; - previousOffsets[2] = 8; - - currentLiteralsLengthTable = null; - currentOffsetCodesTable = null; - currentMatchLengthTable = null; - } - - private static int decodeRawBlock(Object inputBase, long inputAddress, int blockSize, Object outputBase, long outputAddress, long outputLimit) - { - verify(outputAddress + blockSize <= outputLimit, inputAddress, "Output buffer too small"); - - UNSAFE.copyMemory(inputBase, inputAddress, outputBase, outputAddress, blockSize); - return blockSize; - } - - private static int decodeRleBlock(int size, Object inputBase, long inputAddress, Object outputBase, long outputAddress, long outputLimit) - { - verify(outputAddress + size <= outputLimit, inputAddress, "Output buffer too small"); - - long output = outputAddress; - long value = UNSAFE.getByte(inputBase, inputAddress) & 0xFFL; - - int remaining = size; - if (remaining >= SIZE_OF_LONG) { - long packed = value - | (value << 8) - | (value << 16) - | (value << 24) - | (value << 32) - | (value << 40) - | (value << 48) - | (value << 56); - - do { - UNSAFE.putLong(outputBase, output, packed); - output += SIZE_OF_LONG; - remaining -= SIZE_OF_LONG; - } - while (remaining >= SIZE_OF_LONG); - } - - for (int i = 0; i < remaining; i++) { - UNSAFE.putByte(outputBase, output, (byte) value); - output++; - } - - return size; - } - - private int decodeCompressedBlock(Object inputBase, final long inputAddress, int blockSize, Object outputBase, long outputAddress, long outputLimit, int windowSize) - { - long inputLimit = inputAddress + blockSize; - long input = inputAddress; - - verify(blockSize <= MAX_BLOCK_SIZE, input, "Expected match length table to be present"); - verify(blockSize >= MIN_BLOCK_SIZE, input, "Compressed block size too small"); - - // decode literals - int literalsBlockType = UNSAFE.getByte(inputBase, input) & 0b11; - - switch (literalsBlockType) { - case RAW_LITERALS_BLOCK: { - input += decodeRawLiterals(inputBase, input, inputLimit); - break; - } - case RLE_LITERALS_BLOCK: { - input += decodeRleLiterals(inputBase, input, blockSize); - break; - } - case REPEAT_STATS_LITERALS_BLOCK: - verify(huffman.isLoaded(), input, "Dictionary is corrupted"); - case COMPRESSED_LITERALS_BLOCK: { - input += decodeCompressedLiterals(inputBase, input, blockSize, literalsBlockType); - break; - } - default: - throw fail(input, "Invalid literals block encoding type"); - } - - verify(windowSize <= MAX_WINDOW_SIZE, input, "Window size too large (not yet supported)"); - - return decompressSequences( - inputBase, input, inputAddress + blockSize, - outputBase, outputAddress, outputLimit, - literalsBase, literalsAddress, literalsLimit); - } - - private int decompressSequences( - final Object inputBase, final long inputAddress, final long inputLimit, - final Object outputBase, final long outputAddress, final long outputLimit, - final Object literalsBase, final long literalsAddress, final long literalsLimit) - { - final long fastOutputLimit = outputLimit - SIZE_OF_LONG; - - long input = inputAddress; - long output = outputAddress; - - long literalsInput = literalsAddress; - - int size = (int) (inputLimit - inputAddress); - verify(size >= MIN_SEQUENCES_SIZE, input, "Not enough input bytes"); - - // decode header - int sequenceCount = UNSAFE.getByte(inputBase, input++) & 0xFF; - if (sequenceCount != 0) { - if (sequenceCount == 255) { - verify(input + SIZE_OF_SHORT <= inputLimit, input, "Not enough input bytes"); - sequenceCount = (UNSAFE.getShort(inputBase, input) & 0xFFFF) + LONG_NUMBER_OF_SEQUENCES; - input += SIZE_OF_SHORT; - } - else if (sequenceCount > 127) { - verify(input < inputLimit, input, "Not enough input bytes"); - sequenceCount = ((sequenceCount - 128) << 8) + (UNSAFE.getByte(inputBase, input++) & 0xFF); - } - - verify(input + SIZE_OF_INT <= inputLimit, input, "Not enough input bytes"); - - byte type = UNSAFE.getByte(inputBase, input++); - - int literalsLengthType = (type & 0xFF) >>> 6; - int offsetCodesType = (type >>> 4) & 0b11; - int matchLengthType = (type >>> 2) & 0b11; - - input = computeLiteralsTable(literalsLengthType, inputBase, input, inputLimit); - input = computeOffsetsTable(offsetCodesType, inputBase, input, inputLimit); - input = computeMatchLengthTable(matchLengthType, inputBase, input, inputLimit); - - // decompress sequences - BitStream.Initializer initializer = new BitStream.Initializer(inputBase, input, inputLimit); - initializer.initialize(); - int bitsConsumed = initializer.getBitsConsumed(); - long bits = initializer.getBits(); - long currentAddress = initializer.getCurrentAddress(); - - FiniteStateEntropy.Table currentLiteralsLengthTable = this.currentLiteralsLengthTable; - FiniteStateEntropy.Table currentOffsetCodesTable = this.currentOffsetCodesTable; - FiniteStateEntropy.Table currentMatchLengthTable = this.currentMatchLengthTable; - - int literalsLengthState = (int) peekBits(bitsConsumed, bits, currentLiteralsLengthTable.log2Size); - bitsConsumed += currentLiteralsLengthTable.log2Size; - - int offsetCodesState = (int) peekBits(bitsConsumed, bits, currentOffsetCodesTable.log2Size); - bitsConsumed += currentOffsetCodesTable.log2Size; - - int matchLengthState = (int) peekBits(bitsConsumed, bits, currentMatchLengthTable.log2Size); - bitsConsumed += currentMatchLengthTable.log2Size; - - int[] previousOffsets = this.previousOffsets; - - byte[] literalsLengthNumbersOfBits = currentLiteralsLengthTable.numberOfBits; - int[] literalsLengthNewStates = currentLiteralsLengthTable.newState; - byte[] literalsLengthSymbols = currentLiteralsLengthTable.symbol; - - byte[] matchLengthNumbersOfBits = currentMatchLengthTable.numberOfBits; - int[] matchLengthNewStates = currentMatchLengthTable.newState; - byte[] matchLengthSymbols = currentMatchLengthTable.symbol; - - byte[] offsetCodesNumbersOfBits = currentOffsetCodesTable.numberOfBits; - int[] offsetCodesNewStates = currentOffsetCodesTable.newState; - byte[] offsetCodesSymbols = currentOffsetCodesTable.symbol; - - while (sequenceCount > 0) { - sequenceCount--; - - BitStream.Loader loader = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - loader.load(); - bitsConsumed = loader.getBitsConsumed(); - bits = loader.getBits(); - currentAddress = loader.getCurrentAddress(); - if (loader.isOverflow()) { - verify(sequenceCount == 0, input, "Not all sequences were consumed"); - break; - } - - // decode sequence - int literalsLengthCode = literalsLengthSymbols[literalsLengthState]; - int matchLengthCode = matchLengthSymbols[matchLengthState]; - int offsetCode = offsetCodesSymbols[offsetCodesState]; - - int literalsLengthBits = LITERALS_LENGTH_BITS[literalsLengthCode]; - int matchLengthBits = MATCH_LENGTH_BITS[matchLengthCode]; - int offsetBits = offsetCode; - - int offset = OFFSET_CODES_BASE[offsetCode]; - if (offsetCode > 0) { - offset += peekBits(bitsConsumed, bits, offsetBits); - bitsConsumed += offsetBits; - } - - if (offsetCode <= 1) { - if (literalsLengthCode == 0) { - offset++; - } - - if (offset != 0) { - int temp; - if (offset == 3) { - temp = previousOffsets[0] - 1; - } - else { - temp = previousOffsets[offset]; - } - - if (temp == 0) { - temp = 1; - } - - if (offset != 1) { - previousOffsets[2] = previousOffsets[1]; - } - previousOffsets[1] = previousOffsets[0]; - previousOffsets[0] = temp; - - offset = temp; - } - else { - offset = previousOffsets[0]; - } - } - else { - previousOffsets[2] = previousOffsets[1]; - previousOffsets[1] = previousOffsets[0]; - previousOffsets[0] = offset; - } - - int matchLength = MATCH_LENGTH_BASE[matchLengthCode]; - if (matchLengthCode > 31) { - matchLength += peekBits(bitsConsumed, bits, matchLengthBits); - bitsConsumed += matchLengthBits; - } - - int literalsLength = LITERALS_LENGTH_BASE[literalsLengthCode]; - if (literalsLengthCode > 15) { - literalsLength += peekBits(bitsConsumed, bits, literalsLengthBits); - bitsConsumed += literalsLengthBits; - } - - int totalBits = literalsLengthBits + matchLengthBits + offsetBits; - if (totalBits > 64 - 7 - (LITERALS_LENGTH_FSE_LOG + MATCH_LENGTH_FSE_LOG + OFFSET_CODES_FSE_LOG)) { - BitStream.Loader loader1 = new BitStream.Loader(inputBase, input, currentAddress, bits, bitsConsumed); - loader1.load(); - - bitsConsumed = loader1.getBitsConsumed(); - bits = loader1.getBits(); - currentAddress = loader1.getCurrentAddress(); - } - - int numberOfBits; - - numberOfBits = literalsLengthNumbersOfBits[literalsLengthState]; - literalsLengthState = (int) (literalsLengthNewStates[literalsLengthState] + peekBits(bitsConsumed, bits, numberOfBits)); // <= 9 bits - bitsConsumed += numberOfBits; - - numberOfBits = matchLengthNumbersOfBits[matchLengthState]; - matchLengthState = (int) (matchLengthNewStates[matchLengthState] + peekBits(bitsConsumed, bits, numberOfBits)); // <= 9 bits - bitsConsumed += numberOfBits; - - numberOfBits = offsetCodesNumbersOfBits[offsetCodesState]; - offsetCodesState = (int) (offsetCodesNewStates[offsetCodesState] + peekBits(bitsConsumed, bits, numberOfBits)); // <= 8 bits - bitsConsumed += numberOfBits; - - final long literalOutputLimit = output + literalsLength; - final long matchOutputLimit = literalOutputLimit + matchLength; - - verify(matchOutputLimit <= outputLimit, input, "Output buffer too small"); - verify(literalsInput + literalsLength <= literalsLimit, input, "Input is corrupted"); - - long matchAddress = literalOutputLimit - offset; - - if (literalOutputLimit > fastOutputLimit) { - executeLastSequence(outputBase, output, literalOutputLimit, matchOutputLimit, fastOutputLimit, literalsInput, matchAddress); - } - else { - // copy literals. literalOutputLimit <= fastOutputLimit, so we can copy - // long at a time with over-copy - output = copyLiterals(outputBase, literalsBase, output, literalsInput, literalOutputLimit); - copyMatch(outputBase, fastOutputLimit, output, offset, matchOutputLimit, matchAddress); - } - output = matchOutputLimit; - literalsInput += literalsLength; - } - } - - // last literal segment - output = copyLastLiteral(outputBase, literalsBase, literalsLimit, output, literalsInput); - - return (int) (output - outputAddress); - } - - private long copyLastLiteral(Object outputBase, Object literalsBase, long literalsLimit, long output, long literalsInput) - { - long lastLiteralsSize = literalsLimit - literalsInput; - UNSAFE.copyMemory(literalsBase, literalsInput, outputBase, output, lastLiteralsSize); - output += lastLiteralsSize; - return output; - } - - private void copyMatch(Object outputBase, long fastOutputLimit, long output, int offset, long matchOutputLimit, long matchAddress) - { - matchAddress = copyMatchHead(outputBase, output, offset, matchAddress); - output += SIZE_OF_LONG; - - copyMatchTail(outputBase, fastOutputLimit, output, matchOutputLimit, matchAddress); - } - - private void copyMatchTail(Object outputBase, long fastOutputLimit, long output, long matchOutputLimit, long matchAddress) - { - if (matchOutputLimit > fastOutputLimit) { - while (output < fastOutputLimit) { - UNSAFE.putLong(outputBase, output, UNSAFE.getLong(outputBase, matchAddress)); - matchAddress += SIZE_OF_LONG; - output += SIZE_OF_LONG; - } - - while (output < matchOutputLimit) { - UNSAFE.putByte(outputBase, output++, UNSAFE.getByte(outputBase, matchAddress++)); - } - } - else { - while (output < matchOutputLimit) { - UNSAFE.putLong(outputBase, output, UNSAFE.getLong(outputBase, matchAddress)); - matchAddress += SIZE_OF_LONG; - output += SIZE_OF_LONG; - } - } - } - - private long copyMatchHead(Object outputBase, long output, int offset, long matchAddress) - { - // copy match - if (offset < 8) { - // 8 bytes apart so that we can copy long-at-a-time below - int increment32 = DEC_32_TABLE[offset]; - int decrement64 = DEC_64_TABLE[offset]; - - UNSAFE.putByte(outputBase, output, UNSAFE.getByte(outputBase, matchAddress)); - UNSAFE.putByte(outputBase, output + 1, UNSAFE.getByte(outputBase, matchAddress + 1)); - UNSAFE.putByte(outputBase, output + 2, UNSAFE.getByte(outputBase, matchAddress + 2)); - UNSAFE.putByte(outputBase, output + 3, UNSAFE.getByte(outputBase, matchAddress + 3)); - matchAddress += increment32; - - UNSAFE.putInt(outputBase, output + 4, UNSAFE.getInt(outputBase, matchAddress)); - matchAddress -= decrement64; - } - else { - UNSAFE.putLong(outputBase, output, UNSAFE.getLong(outputBase, matchAddress)); - matchAddress += SIZE_OF_LONG; - } - return matchAddress; - } - - private long copyLiterals(Object outputBase, Object literalsBase, long output, long literalsInput, long literalOutputLimit) - { - long literalInput = literalsInput; - do { - UNSAFE.putLong(outputBase, output, UNSAFE.getLong(literalsBase, literalInput)); - output += SIZE_OF_LONG; - literalInput += SIZE_OF_LONG; - } - while (output < literalOutputLimit); - output = literalOutputLimit; // correction in case we over-copied - return output; - } - - private long computeMatchLengthTable(int matchLengthType, Object inputBase, long input, long inputLimit) - { - switch (matchLengthType) { - case SET_RLE: - verify(input < inputLimit, input, "Not enough input bytes"); - - byte value = UNSAFE.getByte(inputBase, input++); - verify(value <= MAX_MATCH_LENGTH_SYMBOL, input, "Value exceeds expected maximum value"); - - FseTableReader.buildRleTable(matchLengthTable, value); - currentMatchLengthTable = matchLengthTable; - break; - case SET_BASIC: - currentMatchLengthTable = DEFAULT_MATCH_LENGTH_TABLE; - break; - case SET_REPEAT: - verify(currentMatchLengthTable != null, input, "Expected match length table to be present"); - break; - case SET_COMPRESSED: - input += fse.readFseTable(matchLengthTable, inputBase, input, inputLimit, MAX_MATCH_LENGTH_SYMBOL, MATCH_LENGTH_FSE_LOG); - currentMatchLengthTable = matchLengthTable; - break; - default: - throw fail(input, "Invalid match length encoding type"); - } - return input; - } - - private long computeOffsetsTable(int offsetCodesType, Object inputBase, long input, long inputLimit) - { - switch (offsetCodesType) { - case SET_RLE: - verify(input < inputLimit, input, "Not enough input bytes"); - - byte value = UNSAFE.getByte(inputBase, input++); - verify(value <= MAX_OFFSET_CODE_SYMBOL, input, "Value exceeds expected maximum value"); - - FseTableReader.buildRleTable(offsetCodesTable, value); - currentOffsetCodesTable = offsetCodesTable; - break; - case SET_BASIC: - currentOffsetCodesTable = DEFAULT_OFFSET_CODES_TABLE; - break; - case SET_REPEAT: - verify(currentOffsetCodesTable != null, input, "Expected match length table to be present"); - break; - case SET_COMPRESSED: - input += fse.readFseTable(offsetCodesTable, inputBase, input, inputLimit, MAX_OFFSET_CODE_SYMBOL, OFFSET_CODES_FSE_LOG); - currentOffsetCodesTable = offsetCodesTable; - break; - default: - throw fail(input, "Invalid offset code encoding type"); - } - return input; - } - - private long computeLiteralsTable(int literalsLengthType, Object inputBase, long input, long inputLimit) - { - switch (literalsLengthType) { - case SET_RLE: - verify(input < inputLimit, input, "Not enough input bytes"); - - byte value = UNSAFE.getByte(inputBase, input++); - verify(value <= MAX_LITERALS_LENGTH_SYMBOL, input, "Value exceeds expected maximum value"); - - FseTableReader.buildRleTable(literalsLengthTable, value); - currentLiteralsLengthTable = literalsLengthTable; - break; - case SET_BASIC: - currentLiteralsLengthTable = DEFAULT_LITERALS_LENGTH_TABLE; - break; - case SET_REPEAT: - verify(currentLiteralsLengthTable != null, input, "Expected match length table to be present"); - break; - case SET_COMPRESSED: - input += fse.readFseTable(literalsLengthTable, inputBase, input, inputLimit, MAX_LITERALS_LENGTH_SYMBOL, LITERALS_LENGTH_FSE_LOG); - currentLiteralsLengthTable = literalsLengthTable; - break; - default: - throw fail(input, "Invalid literals length encoding type"); - } - return input; - } - - private void executeLastSequence(Object outputBase, long output, long literalOutputLimit, long matchOutputLimit, long fastOutputLimit, long literalInput, long matchAddress) - { - // copy literals - if (output < fastOutputLimit) { - // wild copy - do { - UNSAFE.putLong(outputBase, output, UNSAFE.getLong(literalsBase, literalInput)); - output += SIZE_OF_LONG; - literalInput += SIZE_OF_LONG; - } - while (output < fastOutputLimit); - - literalInput -= output - fastOutputLimit; - output = fastOutputLimit; - } - - while (output < literalOutputLimit) { - UNSAFE.putByte(outputBase, output, UNSAFE.getByte(literalsBase, literalInput)); - output++; - literalInput++; - } - - // copy match - while (output < matchOutputLimit) { - UNSAFE.putByte(outputBase, output, UNSAFE.getByte(outputBase, matchAddress)); - output++; - matchAddress++; - } - } - - private int decodeCompressedLiterals(Object inputBase, final long inputAddress, int blockSize, int literalsBlockType) - { - long input = inputAddress; - verify(blockSize >= 5, input, "Not enough input bytes"); - - // compressed - int compressedSize; - int uncompressedSize; - boolean singleStream = false; - int headerSize; - int type = (UNSAFE.getByte(inputBase, input) >> 2) & 0b11; - switch (type) { - case 0: - singleStream = true; - case 1: { - int header = UNSAFE.getInt(inputBase, input); - - headerSize = 3; - uncompressedSize = (header >>> 4) & mask(10); - compressedSize = (header >>> 14) & mask(10); - break; - } - case 2: { - int header = UNSAFE.getInt(inputBase, input); - - headerSize = 4; - uncompressedSize = (header >>> 4) & mask(14); - compressedSize = (header >>> 18) & mask(14); - break; - } - case 3: { - // read 5 little-endian bytes - long header = UNSAFE.getByte(inputBase, input) & 0xFF | - (UNSAFE.getInt(inputBase, input + 1) & 0xFFFF_FFFFL) << 8; - - headerSize = 5; - uncompressedSize = (int) ((header >>> 4) & mask(18)); - compressedSize = (int) ((header >>> 22) & mask(18)); - break; - } - default: - throw fail(input, "Invalid literals header size type"); - } - - verify(uncompressedSize <= MAX_BLOCK_SIZE, input, "Block exceeds maximum size"); - verify(headerSize + compressedSize <= blockSize, input, "Input is corrupted"); - - input += headerSize; - - long inputLimit = input + compressedSize; - if (literalsBlockType != REPEAT_STATS_LITERALS_BLOCK) { - input += huffman.readTable(inputBase, input, compressedSize); - } - - literalsBase = literals; - literalsAddress = ARRAY_BYTE_BASE_OFFSET; - literalsLimit = ARRAY_BYTE_BASE_OFFSET + uncompressedSize; - - if (singleStream) { - huffman.decodeSingleStream(inputBase, input, inputLimit, literals, literalsAddress, literalsLimit); - } - else { - huffman.decode4Streams(inputBase, input, inputLimit, literals, literalsAddress, literalsLimit); - } - - return headerSize + compressedSize; - } - - private int decodeRleLiterals(Object inputBase, final long inputAddress, int blockSize) - { - long input = inputAddress; - int outputSize; - - int type = (UNSAFE.getByte(inputBase, input) >> 2) & 0b11; - switch (type) { - case 0: - case 2: - outputSize = (UNSAFE.getByte(inputBase, input) & 0xFF) >>> 3; - input++; - break; - case 1: - outputSize = (UNSAFE.getShort(inputBase, input) & 0xFFFF) >>> 4; - input += 2; - break; - case 3: - // we need at least 4 bytes (3 for the header, 1 for the payload) - verify(blockSize >= SIZE_OF_INT, input, "Not enough input bytes"); - outputSize = (UNSAFE.getInt(inputBase, input) & 0xFF_FFFF) >>> 4; - input += 3; - break; - default: - throw fail(input, "Invalid RLE literals header encoding type"); - } - - verify(outputSize <= MAX_BLOCK_SIZE, input, "Output exceeds maximum block size"); - - byte value = UNSAFE.getByte(inputBase, input++); - Arrays.fill(literals, 0, outputSize + SIZE_OF_LONG, value); - - literalsBase = literals; - literalsAddress = ARRAY_BYTE_BASE_OFFSET; - literalsLimit = ARRAY_BYTE_BASE_OFFSET + outputSize; - - return (int) (input - inputAddress); - } - - private int decodeRawLiterals(Object inputBase, final long inputAddress, long inputLimit) - { - long input = inputAddress; - int type = (UNSAFE.getByte(inputBase, input) >> 2) & 0b11; - - int literalSize; - switch (type) { - case 0: - case 2: - literalSize = (UNSAFE.getByte(inputBase, input) & 0xFF) >>> 3; - input++; - break; - case 1: - literalSize = (UNSAFE.getShort(inputBase, input) & 0xFFFF) >>> 4; - input += 2; - break; - case 3: - // read 3 little-endian bytes - int header = ((UNSAFE.getByte(inputBase, input) & 0xFF) | - ((UNSAFE.getShort(inputBase, input + 1) & 0xFFFF) << 8)); - - literalSize = header >>> 4; - input += 3; - break; - default: - throw fail(input, "Invalid raw literals header encoding type"); - } - - verify(input + literalSize <= inputLimit, input, "Not enough input bytes"); - - // Set literals pointer to [input, literalSize], but only if we can copy 8 bytes at a time during sequence decoding - // Otherwise, copy literals into buffer that's big enough to guarantee that - if (literalSize > (inputLimit - input) - SIZE_OF_LONG) { - literalsBase = literals; - literalsAddress = ARRAY_BYTE_BASE_OFFSET; - literalsLimit = ARRAY_BYTE_BASE_OFFSET + literalSize; - - UNSAFE.copyMemory(inputBase, input, literals, literalsAddress, literalSize); - Arrays.fill(literals, literalSize, literalSize + SIZE_OF_LONG, (byte) 0); - } - else { - literalsBase = inputBase; - literalsAddress = input; - literalsLimit = literalsAddress + literalSize; - } - input += literalSize; - - return (int) (input - inputAddress); - } - - private static FrameHeader readFrameHeader(final Object inputBase, final long inputAddress, final long inputLimit) - { - long input = inputAddress; - verify(input < inputLimit, input, "Not enough input bytes"); - - int frameHeaderDescriptor = UNSAFE.getByte(inputBase, input++) & 0xFF; - boolean singleSegment = (frameHeaderDescriptor & 0b100000) != 0; - int dictionaryDescriptor = frameHeaderDescriptor & 0b11; - int contentSizeDescriptor = frameHeaderDescriptor >>> 6; - - int headerSize = 1 + - (singleSegment ? 0 : 1) + - (dictionaryDescriptor == 0 ? 0 : (1 << (dictionaryDescriptor - 1))) + - (contentSizeDescriptor == 0 ? (singleSegment ? 1 : 0) : (1 << contentSizeDescriptor)); - - verify(headerSize <= inputLimit - inputAddress, input, "Not enough input bytes"); - - // decode window size - int windowSize = -1; - if (!singleSegment) { - int windowDescriptor = UNSAFE.getByte(inputBase, input++) & 0xFF; - int exponent = windowDescriptor >>> 3; - int mantissa = windowDescriptor & 0b111; - - int base = 1 << (MIN_WINDOW_LOG + exponent); - windowSize = base + (base / 8) * mantissa; - } - - // decode dictionary id - long dictionaryId = -1; - switch (dictionaryDescriptor) { - case 1: - dictionaryId = UNSAFE.getByte(inputBase, input) & 0xFF; - input += SIZE_OF_BYTE; - break; - case 2: - dictionaryId = UNSAFE.getShort(inputBase, input) & 0xFFFF; - input += SIZE_OF_SHORT; - break; - case 3: - dictionaryId = UNSAFE.getInt(inputBase, input) & 0xFFFF_FFFFL; - input += SIZE_OF_INT; - break; - } - verify(dictionaryId == -1, input, "Custom dictionaries not supported"); - - // decode content size - long contentSize = -1; - switch (contentSizeDescriptor) { - case 0: - if (singleSegment) { - contentSize = UNSAFE.getByte(inputBase, input) & 0xFF; - input += SIZE_OF_BYTE; - } - break; - case 1: - contentSize = UNSAFE.getShort(inputBase, input) & 0xFFFF; - contentSize += 256; - input += SIZE_OF_SHORT; - break; - case 2: - contentSize = UNSAFE.getInt(inputBase, input) & 0xFFFF_FFFFL; - input += SIZE_OF_INT; - break; - case 3: - contentSize = UNSAFE.getLong(inputBase, input); - input += SIZE_OF_LONG; - break; - } - - boolean hasChecksum = (frameHeaderDescriptor & 0b100) != 0; - - return new FrameHeader( - input - inputAddress, - windowSize, - contentSize, - dictionaryId, - hasChecksum); - } - - public static long getDecompressedSize(final Object inputBase, final long inputAddress, final long inputLimit) - { - long input = inputAddress; - input += verifyMagic(inputBase, input, inputLimit); - return readFrameHeader(inputBase, input, inputLimit).contentSize; - } - - private static int verifyMagic(Object inputBase, long inputAddress, long inputLimit) - { - verify(inputLimit - inputAddress >= 4, inputAddress, "Not enough input bytes"); - - int magic = UNSAFE.getInt(inputBase, inputAddress); - if (magic != MAGIC_NUMBER) { - throw new MalformedInputException(inputAddress, "Invalid magic prefix: " + Integer.toHexString(magic)); - } - - return SIZE_OF_INT; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java b/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java index 40b609b95..8ab6b1cda 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java @@ -23,7 +23,6 @@ public class ReflectionUtils { return t.isInstance(o) ? t.cast(o) : null; } - @SuppressWarnings("unchecked") public static > T addEnum(Class enumType, String enumName) { try { return addEnum(enumType, enumName, new Class[]{}, new Object[]{}); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java index 6e6711650..4ff97afc3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java @@ -157,19 +157,6 @@ public class PlayerWrapper extends AbstractPlayerActor { parent.setGameMode(gameMode); } - ///////////////////////////////////////// - ///////////////////////////////////////// - ///////////////////////////////////////// - - ///////////////////////////////////////// - ///////////////////////////////////////// - ///////////////////////////////////////// - - ///////////////////////////////////////// - ///////////////////////////////////////// - ///////////////////////////////////////// - - @Override public void findFreePosition(final Location searchPos) { TaskManager.IMP.sync(new RunnableVal() { diff --git a/worldedit-core/src/main/java/com/sk89q/util/ReflectionUtil.java b/worldedit-core/src/main/java/com/sk89q/util/ReflectionUtil.java index bec4e79ed..1cabccdb5 100644 --- a/worldedit-core/src/main/java/com/sk89q/util/ReflectionUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/util/ReflectionUtil.java @@ -19,19 +19,13 @@ package com.sk89q.util; -import sun.reflect.ConstructorAccessor; -import sun.reflect.FieldAccessor; -import sun.reflect.ReflectionFactory; - -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Field; public final class ReflectionUtil { private ReflectionUtil() { } - @SuppressWarnings("unchecked") public static T getField(Object from, String name) { if (from instanceof Class) return getField((Class) from, null, name); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 3517bb2f7..e71afeba7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -570,6 +570,7 @@ public class LocalSession implements TextureHolder { newEditSession.setBlocks(changeSet, ChangeSetExecutor.Type.REDO); return newEditSession; } + return null; } @@ -625,14 +626,6 @@ public class LocalSession implements TextureHolder { return selector; } - /** - * @deprecated use {@link #getRegionSelector(World)} - */ - @Deprecated - public RegionSelector getRegionSelector() { - return selector; - } - /** * Set the region selector. * @@ -646,16 +639,6 @@ public class LocalSession implements TextureHolder { this.selector = selector; } - /** - * Returns true if the region is fully defined. - * - * @return true if a region selection is defined - */ - @Deprecated - public boolean isRegionDefined() { - return selector.isDefined(); - } - /** * Returns true if the region is fully defined for the specified world. * @@ -670,14 +653,6 @@ public class LocalSession implements TextureHolder { return selector.isDefined(); } - /** - * @deprecated use {@link #getSelection(World)} - */ - @Deprecated - public Region getRegion() throws IncompleteRegionException { - return selector.getRegion(); - } - /** * Get the selection region. If you change the region, you should * call learnRegionChanges(). If the selection is defined in @@ -907,7 +882,7 @@ public class LocalSession implements TextureHolder { public BlockVector3 getPlacementPosition(Player player) throws IncompleteRegionException { checkNotNull(player); if (!placeAtPos1) { - return player.getBlockIn().toBlockPoint(); + return player.getBlockIn().toVector().toBlockPoint(); } return selector.getPrimaryPosition(); @@ -976,6 +951,12 @@ public class LocalSession implements TextureHolder { this.pickaxeMode = tool; } + /** + * Get the tool assigned to the item. + * + * @param item the item type + * @return the tool, which may be {@code null} + */ @Nullable public Tool getTool(ItemType item) { return tools[item.getInternalId()]; @@ -1012,11 +993,6 @@ public class LocalSession implements TextureHolder { return getBrushTool(item.getDefaultState(), null, true); } - @Deprecated - public BrushTool getBrushTool(BaseItem item) throws InvalidToolBindException { - return getBrushTool(item, null, true); - } - public BrushTool getBrushTool(Player player) throws InvalidToolBindException { return getBrushTool(player, true); } @@ -1048,7 +1024,6 @@ public class LocalSession implements TextureHolder { * @param tool the tool to set, which can be {@code null} * @throws InvalidToolBindException if the item can't be bound to that item */ - @Deprecated public void setTool(ItemType item, @Nullable Tool tool) throws InvalidToolBindException { setTool(item.getDefaultState(), tool, null); } @@ -1141,7 +1116,6 @@ public class LocalSession implements TextureHolder { public void tellVersion(Actor player) { } - public boolean shouldUseServerCUI() { return this.useServerCUI; } @@ -1209,9 +1183,8 @@ public class LocalSession implements TextureHolder { if (hasCUISupport) { actor.dispatchCUIEvent(event); - } else if (actor.isPlayer()) { - CUI cui = Fawe.get().getCUI(actor); - if (cui != null) cui.dispatchCUIEvent(event); + } else if (useServerCUI) { + updateServerCUI(actor); } } @@ -1243,12 +1216,13 @@ public class LocalSession implements TextureHolder { CUIRegion tempSel = (CUIRegion) selector; if (tempSel.getProtocolVersion() > cuiVersion) { - dispatchCUIEvent(actor, new SelectionShapeEvent(tempSel.getLegacyTypeID())); + actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getLegacyTypeID())); tempSel.describeLegacyCUI(this, actor); } else { - dispatchCUIEvent(actor, new SelectionShapeEvent(tempSel.getTypeID())); + actor.dispatchCUIEvent(new SelectionShapeEvent(tempSel.getTypeID())); tempSel.describeCUI(this, actor); } + } } @@ -1259,6 +1233,11 @@ public class LocalSession implements TextureHolder { */ public void describeCUI(Actor actor) { checkNotNull(actor); + + if (!hasCUISupport) { + return; + } + if (selector instanceof CUIRegion) { CUIRegion tempSel = (CUIRegion) selector; @@ -1285,18 +1264,15 @@ public class LocalSession implements TextureHolder { String[] split = text.split("\\|", 2); if (split.length > 1 && split[0].equalsIgnoreCase("v")) { // enough fields and right message if (split[1].length() > 4) { - this.failedCuiAttempts++; + this.failedCuiAttempts ++; return; } setCUISupport(true); try { setCUIVersion(Integer.parseInt(split[1])); } catch (NumberFormatException e) { - String msg = e.getMessage(); - if (msg != null && msg.length() > 256) msg = msg.substring(0, 256); - this.failedCuiAttempts++; - WorldEdit.logger.warn("Error while reading CUI init message for player " + uuid + ": " + msg); - + WorldEdit.logger.warn("Error while reading CUI init message: " + e.getMessage()); + this.failedCuiAttempts ++; } } } @@ -1364,7 +1340,6 @@ public class LocalSession implements TextureHolder { * @param player the player * @return an edit session */ - @SuppressWarnings("deprecation") public EditSession createEditSession(Player player) { checkNotNull(player); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index 64026f536..935e4ecce 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -23,7 +23,7 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweVersion; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.util.*; +import com.boydti.fawe.util.IncendoPaster; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; @@ -32,16 +32,24 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; -import com.sk89q.worldedit.extension.platform.*; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.Capability; +import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extension.platform.PlatformManager; import com.sk89q.worldedit.extension.platform.PlatformManager; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.Map; +import java.util.TimeZone; @Command(aliases = {"worldedit", "we", "fawe"}, desc = "Updating, informational, debug and help commands") public class WorldEditCommands { @@ -54,19 +62,19 @@ public class WorldEditCommands { } @Command( - aliases = {"version", "ver"}, - usage = "", - desc = "Get WorldEdit/FAWE version", - min = 0, - max = 0, - queued = false + aliases = { "version", "ver" }, + usage = "", + desc = "Get WorldEdit/FAWE version", + min = 0, + max = 0, + queued = false ) public void version(Actor actor) throws WorldEditException { FaweVersion fVer = Fawe.get().getVersion(); String fVerStr = fVer == null ? "unknown" : "-" + fVer.build; - actor.print(BBC.getPrefix() + "FastAsyncWorldEdit-1.13" + fVerStr + " by Empire92"); + actor.print("FastAsyncWorldEdit-1.13" + fVerStr + " by Empire92"); if (fVer != null) { - actor.printDebug("------------------------------------"); + actor.printDebug("----------- Platforms -----------"); FaweVersion version = Fawe.get().getVersion(); Date date = new GregorianCalendar(2000 + version.year, version.month - 1, version.day).getTime(); actor.printDebug(" - DATE: " + date.toLocaleString()); @@ -76,11 +84,13 @@ public class WorldEditCommands { actor.printDebug("------------------------------------"); } PlatformManager pm = we.getPlatformManager(); - actor.printDebug("Platforms:"); + + actor.printDebug("----------- Platforms -----------"); for (Platform platform : pm.getPlatforms()) { - actor.printDebug(String.format(" - %s", platform.getPlatformName())); + actor.printDebug(String.format("* %s", platform.getPlatformName())); } - actor.printDebug("Capabilities:"); + + actor.printDebug("----------- Capabilities -----------"); for (Capability capability : Capability.values()) { Platform platform = pm.queryCapability(capability); actor.printDebug(String.format(" - %s: %s", capability.name(), platform != null ? platform.getPlatformName() : "NONE")); @@ -90,11 +100,11 @@ public class WorldEditCommands { } @Command( - aliases = {"reload"}, - usage = "", - desc = "Reload configuration and translations", - min = 0, - max = 0 + aliases = { "reload" }, + usage = "", + desc = "Reload configuration and translations", + min = 0, + max = 0 ) @CommandPermissions("worldedit.reload") public void reload(Actor actor) throws WorldEditException { @@ -102,7 +112,7 @@ public class WorldEditCommands { we.getEventBus().post(new ConfigurationLoadEvent(we.getPlatformManager().queryCapability(Capability.CONFIGURATION).getConfiguration())); Fawe.get().setupConfigs(); CommandManager.getInstance().register(we.getPlatformManager().queryCapability(Capability.USER_COMMANDS)); - actor.print(BBC.getPrefix() + "Reloaded FastAsyncWorldEdit configuration and translation files"); + actor.print("Configuration and translations reloaded!"); } @Command( @@ -139,11 +149,11 @@ public class WorldEditCommands { } @Command( - aliases = {"cui"}, - usage = "", - desc = "Complete CUI handshake (internal usage)", - min = 0, - max = 0 + aliases = { "cui" }, + usage = "", + desc = "Complete CUI handshake (internal usage)", + min = 0, + max = 0 ) public void cui(Player player, LocalSession session) throws WorldEditException { session.setCUISupport(true); @@ -151,11 +161,11 @@ public class WorldEditCommands { } @Command( - aliases = {"tz"}, - usage = "[timezone]", - desc = "Set your timezone for snapshots", - min = 1, - max = 1 + aliases = { "tz" }, + usage = "[timezone]", + desc = "Set your timezone for snapshots", + min = 1, + max = 1 ) public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException { TimeZone tz = TimeZone.getTimeZone(args.getString(0)); @@ -165,13 +175,14 @@ public class WorldEditCommands { } @Command( - aliases = {"help"}, - usage = "[]", + aliases = { "help" }, + usage = "[]", desc = "Displays help for FAWE commands", - min = 0, - max = -1, - queued = false + min = 0, + max = -1, + queued = false ) + @CommandPermissions("worldedit.help") public void help(Actor actor, CommandContext args) throws WorldEditException { UtilityCommands.help(args, we, actor); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index 95fa08e91..27cf4d6b9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -42,7 +42,6 @@ import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; -import com.sk89q.worldedit.world.registry.BlockMaterial; import java.io.File; @@ -137,7 +136,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { final BlockVector3 pos = BlockVector3.at(x, y, z); final BlockState id = world.getBlock(pos); if (id.getBlockType().getMaterial().isMovementBlocker()) { - setPosition(new Location(world, Vector3.at(x + 0.5, y + + BlockTypeUtil.centralTopLimit(id), z + 0.5))); + setPosition(Vector3.at(x + 0.5, y + 1, z + 0.5)); return; } @@ -158,47 +157,36 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { final int z = pos.getBlockZ(); final Extent world = pos.getExtent(); - int maxY = world.getMaxY(); - if (y >= maxY) return false; + byte free = 0; + byte spots = 0; - BlockMaterial initialMaterial = world.getBlockType(BlockVector3.at(x, y, z)).getMaterial(); - - boolean lastState = initialMaterial.isMovementBlocker() && initialMaterial.isFullCube(); - - double height = 1.85; - double freeStart = -1; - - for (int level = y + 1; level <= maxY + 2; level++) { - BlockState state; - if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState(); - else state = world.getBlock(BlockVector3.at(x, level, z)); - BlockType type = state.getBlockType(); - BlockMaterial material = type.getMaterial(); - - if (!material.isFullCube() || !material.isMovementBlocker()) { - if (!lastState) { - lastState = BlockTypeUtil.centralBottomLimit(state) != 1; - continue; - } - if (freeStart == -1) { - freeStart = level + BlockTypeUtil.centralTopLimit(state); - } else { - double bottomLimit = BlockTypeUtil.centralBottomLimit(state); - double space = level + bottomLimit - freeStart; - if (space >= height) { - setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); - return true; - } - // Not enough room, reset the free position - if (bottomLimit != 1) { - freeStart = -1; - } - } + while (y <= world.getMaximumPoint().getY() + 2) { + if (!world.getBlock(BlockVector3.at(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) { + ++free; } else { - freeStart = -1; - lastState = true; + free = 0; } + + if (free == 2) { + ++spots; + if (spots == 2) { + final BlockVector3 platform = BlockVector3.at(x, y - 2, z); + final BlockState block = world.getBlock(platform); + final com.sk89q.worldedit.world.block.BlockType type = block.getBlockType(); + + // Don't get put in lava! + if (type == BlockTypes.LAVA) { + return false; + } + + setPosition(platform.toVector3().add(0.5, 1, 0.5)); + return true; + } + } + + ++y; } + return false; } @@ -206,52 +194,44 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { public boolean descendLevel() { final Location pos = getBlockIn(); final int x = pos.getBlockX(); - int y = Math.max(0, pos.getBlockY()); + int y = Math.max(0, pos.getBlockY() - 1); final int z = pos.getBlockZ(); final Extent world = pos.getExtent(); - BlockMaterial initialMaterial = world.getBlockType(BlockVector3.at(x, y, z)).getMaterial(); + byte free = 0; - boolean lastState = initialMaterial.isMovementBlocker() && initialMaterial.isFullCube(); + while (y >= 1) { + if (!world.getBlock(BlockVector3.at(x, y, z)).getBlockType().getMaterial().isMovementBlocker()) { + ++free; + } else { + free = 0; + } - double height = 1.85; - double freeEnd = -1; + if (free == 2) { + // So we've found a spot, but we have to drop the player + // lightly and also check to see if there's something to + // stand upon + while (y >= 0) { + final BlockVector3 platform = BlockVector3.at(x, y, z); + final BlockState block = world.getBlock(platform); + final BlockType type = block.getBlockType(); - int maxY = world.getMaxY(); - if (y <= 2) return false; - - for (int level = y + 1; level > 0; level--) { - BlockState state; - if (level >= maxY) state = BlockTypes.VOID_AIR.getDefaultState(); - else state = world.getBlock(BlockVector3.at(x, level, z)); - BlockType type = state.getBlockType(); - BlockMaterial material = type.getMaterial(); - - if (!material.isFullCube() || !material.isMovementBlocker()) { - if (!lastState) { - lastState = BlockTypeUtil.centralTopLimit(state) != 0; - continue; - } - if (freeEnd == -1) { - freeEnd = level + BlockTypeUtil.centralBottomLimit(state); - } else { - double topLimit = BlockTypeUtil.centralTopLimit(state); - double freeStart = level + topLimit; - double space = freeEnd - freeStart; - if (space >= height) { - setPosition(Vector3.at(x + 0.5, freeStart, z + 0.5)); + // Don't want to end up in lava + if (!type.getMaterial().isAir() && type != BlockTypes.LAVA) { + // Found a block! + setPosition(platform.toVector3().add(0.5, 1, 0.5)); return true; } - // Not enough room, reset the free position - if (topLimit != 0) { - freeEnd = -1; - } + + --y; } - } else { - lastState = true; - freeEnd = -1; + + return false; } + + --y; } + return false; } @@ -326,7 +306,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { if (!getLocation().getExtent().getBlock(spot).getBlockType().getMaterial().isMovementBlocker()) { getLocation().getExtent().setBlock(spot, BlockTypes.GLASS.getDefaultState()); } - }catch (WorldEditException e) { + } catch (WorldEditException e) { e.printStackTrace(); } setPosition(Vector3.at(x + 0.5, y, z + 0.5)); @@ -334,12 +314,12 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { @Override public Location getBlockIn() { - return getLocation().setPosition(getLocation().floor()); + return getLocation().setPosition(getLocation().toVector().floor()); } @Override public Location getBlockOn() { - return getLocation().setPosition(getLocation().setY(getLocation().getY() - 1).floor()); + return getLocation().setPosition(getLocation().setY(getLocation().getY() - 1).toVector().floor()); } @Override @@ -393,7 +373,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { if (typeId.hasBlockType()) { return typeId.getBlockType().getDefaultState().toBaseBlock(); } else { - return BlockTypes.AIR.getDefaultState().toBaseBlock(); + throw new NotABlockException(); } } @@ -414,7 +394,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { boolean inFree = false; while ((block = hitBlox.getNextBlock()) != null) { - boolean free = !world.getBlock(block.toBlockPoint()).getBlockType().getMaterial().isMovementBlocker(); + boolean free = !world.getBlock(block.toVector().toBlockPoint()).getBlockType().getMaterial().isMovementBlocker(); if (firstBlock) { firstBlock = false; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 98f8ee7bd..4bdd72c74 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -57,6 +57,7 @@ import java.util.EnumMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicBoolean; import static com.google.common.base.Preconditions.checkNotNull; @@ -139,9 +140,9 @@ public class PlatformManager { // Check whether this platform was chosen to be the preferred one // for any capability and be sure to remove it - Iterator> it = preferences.entrySet().iterator(); + Iterator> it = preferences.entrySet().iterator(); while (it.hasNext()) { - Map.Entry entry = it.next(); + Entry entry = it.next(); if (entry.getValue().equals(platform)) { entry.getKey().unload(this, entry.getValue()); it.remove(); @@ -347,6 +348,7 @@ public class PlatformManager { event.setCancelled(true); return; } + if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) { final BlockTool superPickaxe = session.getSuperPickaxe(); if (superPickaxe != null && superPickaxe.canUse(player)) { @@ -357,8 +359,8 @@ public class PlatformManager { return; } } - final Tool tool = session.getTool(player); - if (tool != null && tool instanceof DoubleActionBlockTool) { + Tool tool = session.getTool(player); + if (tool instanceof DoubleActionBlockTool) { if (tool.canUse(player)) { FawePlayer fp = FawePlayer.wrap(player); final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); @@ -372,6 +374,7 @@ public class PlatformManager { return; } } + } else if (event.getType() == Interaction.OPEN) { if (session.isToolControlEnabled() && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { if (!actor.hasPermission("worldedit.selection.pos")) { @@ -392,12 +395,13 @@ public class PlatformManager { } }, false, true); } + event.setCancelled(true); return; } - final Tool tool = session.getTool(player); - if (tool != null && tool instanceof BlockTool) { + Tool tool = session.getTool(player); + if (tool instanceof BlockTool) { if (tool.canUse(player)) { FawePlayer fp = FawePlayer.wrap(player); if (fp.checkAction()) { @@ -439,8 +443,8 @@ public class PlatformManager { // Create a proxy actor with a potentially different world for // making changes to the world Player actor = createProxyActor(event.getPlayer()); - final Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap(actor), actor.getLocation(), true); - final LocalSession session = worldEdit.getSessionManager().get(player); + Player player = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap(actor), actor.getLocation(), true); + LocalSession session = worldEdit.getSessionManager().get(player); VirtualWorld virtual = session.getVirtualWorld(); if (virtual != null) { @@ -451,7 +455,7 @@ public class PlatformManager { try { switch (event.getInputType()) { case PRIMARY: { - if (getConfiguration().navigationWandMaxDistance > 0 && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) { + if ((getConfiguration().navigationWandMaxDistance > 0) && player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().navigationWand)) { if (!player.hasPermission("worldedit.navigation.jumpto.tool")) { return; } @@ -476,6 +480,7 @@ public class PlatformManager { return; } } + break; } @@ -521,5 +526,4 @@ public class PlatformManager { } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index 8d8db170b..6bc5c623d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -19,12 +19,9 @@ package com.sk89q.worldedit.extension.platform; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockStateHolder; - import static com.google.common.base.Preconditions.checkNotNull; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Player; @@ -36,13 +33,13 @@ import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.gamemode.GameMode; -import javax.annotation.Nullable; - import java.util.UUID; -import static com.google.common.base.Preconditions.checkNotNull; +import javax.annotation.Nullable; public class PlayerProxy extends AbstractPlayerActor { @@ -50,7 +47,6 @@ public class PlayerProxy extends AbstractPlayerActor { private final Actor permActor; private final Actor cuiActor; private final World world; - private Vector3 offset = Vector3.ZERO; public PlayerProxy(Player basePlayer, Actor permActor, Actor cuiActor, World world) { checkNotNull(basePlayer); @@ -63,10 +59,6 @@ public class PlayerProxy extends AbstractPlayerActor { this.world = world; } - public void setOffset(Vector3 position) { - this.offset = position; - } - @Override public BaseBlock getBlockInHand(HandSide handSide) throws WorldEditException { @@ -105,13 +97,12 @@ public class PlayerProxy extends AbstractPlayerActor { @Override public BaseEntity getState() { - throw new UnsupportedOperationException("Can't withPropertyId() on a player"); + throw new UnsupportedOperationException("Can't getState() on a player"); } @Override public Location getLocation() { - Location loc = this.basePlayer.getLocation(); - return new Location(loc.getExtent(), loc.add(offset), loc.getDirection()); + return basePlayer.getLocation(); } @Override @@ -194,4 +185,3 @@ public class PlayerProxy extends AbstractPlayerActor { return basePlayer; } } - diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java index dfc2886ff..5a13140db 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/cui/ServerCUIHandler.java @@ -27,7 +27,6 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; - import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; @@ -152,7 +151,6 @@ public class ServerCUIHandler { structureTag.put("showboundingbox", new ByteTag((byte) 1)); structureTag.put("id", new StringTag(BlockTypes.STRUCTURE_BLOCK.getId())); -// return BlockTypes.STRUCTURE_BLOCK.getDefaultState().toBaseBlock(new CompoundTag(structureTag)); return BlockTypes.STRUCTURE_BLOCK.getDefaultState().toBaseBlock(new CompoundTag(structureTag)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java index ef2a631c7..11c1ab12a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/SphereRegionSelector.java @@ -98,5 +98,4 @@ public class SphereRegionSelector extends EllipsoidRegionSelector { return "sphere"; } - }