Remove CUI and other cleaning

This commit is contained in:
MattBDev 2019-06-06 18:39:51 -04:00
parent b42553116c
commit 229182aa63
28 changed files with 574 additions and 2653 deletions

View File

@ -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;

View File

@ -69,6 +69,7 @@ public class StructureCUI extends CUI {
private int viewDistance() {
Player player = this.<Player>getPlayer().parent;
//todo replace with PaperLib.isPaper()
if (Bukkit.getVersion().contains("paper")) {
return player.getViewDistance();
} else {

View File

@ -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.
*
* <p>If a matching world cannot be found, a {@link RuntimeException}
* will be thrown.</p>
*
* @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 <B extends BlockStateHolder<B>> 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);
}

View File

@ -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<Integer, ItemStack> overflow = inv.addItem(item);
if (!overflow.isEmpty()) {
TaskManager.IMP.sync(new RunnableVal<Object>() {
@ -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 <B extends BlockStateHolder<B>> 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());

View File

@ -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<CommandInfo> toRegister = new ArrayList<>();
BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher);
for (CommandMapping command : dispatcher.getCommands()) {
Description description = command.getDescription();
List<String> permissions = description.getPermissions();
@ -177,7 +177,7 @@ public class BukkitServerInterface implements MultiUserPlatform {
public Collection<Actor> getConnectedUsers() {
List<Actor> 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;
}

View File

@ -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<Plugin> plugins = (List<Plugin>) pluginsField.get(manager);
lookupNames = (Map<String, Plugin>) lookupNamesField.get(manager);
pluginsField.set(manager, plugins = new ArrayList<Plugin>(plugins) {
pluginsField.set(manager, new ArrayList<Plugin>(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<String, Plugin>(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<Property<?>, 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<Property<?>, 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<String> 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<String> 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.

View File

@ -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<Object> 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 ======");

View File

@ -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();
}

View File

@ -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());

View File

@ -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;
}
}
}

View File

@ -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<String> 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<String> 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();
}
}
});

View File

@ -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.
* <p>
* <p>
* ... [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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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];
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -23,7 +23,6 @@ public class ReflectionUtils {
return t.isInstance(o) ? t.cast(o) : null;
}
@SuppressWarnings("unchecked")
public static <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName) {
try {
return addEnum(enumType, enumName, new Class<?>[]{}, new Object[]{});

View File

@ -157,19 +157,6 @@ public class PlayerWrapper extends AbstractPlayerActor {
parent.setGameMode(gameMode);
}
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
/////////////////////////////////////////
@Override
public void findFreePosition(final Location searchPos) {
TaskManager.IMP.sync(new RunnableVal<Boolean>() {

View File

@ -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> T getField(Object from, String name) {
if (from instanceof Class)
return getField((Class) from, null, name);

View File

@ -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);

View File

@ -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 = "[<command>]",
aliases = { "help" },
usage = "[<command>]",
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);
}

View File

@ -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;

View File

@ -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<Map.Entry<Capability, Platform>> it = preferences.entrySet().iterator();
Iterator<Entry<Capability, Platform>> it = preferences.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Capability, Platform> entry = it.next();
Entry<Capability, Platform> 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 {
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -98,5 +98,4 @@ public class SphereRegionSelector extends EllipsoidRegionSelector {
return "sphere";
}
}