Updated Gradle

This commit is contained in:
Matt
2016-02-22 23:11:28 -05:00
parent 7b15d50674
commit b69e31129d
407 changed files with 15242 additions and 15248 deletions

View File

@ -0,0 +1,60 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.PlotMessage;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ChatManager;
import com.plotsquared.bukkit.chat.FancyMessage;
import com.plotsquared.bukkit.object.BukkitPlayer;
import org.bukkit.ChatColor;
import java.util.ArrayList;
import java.util.List;
public class BukkitChatManager extends ChatManager<FancyMessage> {
@Override
public FancyMessage builder() {
return new FancyMessage("");
}
@Override
public void color(final PlotMessage m, final String color) {
m.$(this).color(ChatColor.getByChar(C.color(color).substring(1)));
}
@Override
public void tooltip(final PlotMessage m, final PlotMessage... tooltips) {
final List<FancyMessage> lines = new ArrayList<>();
for (final PlotMessage tooltip : tooltips) {
lines.add(tooltip.$(this));
}
m.$(this).formattedTooltip(lines);
}
@Override
public void command(final PlotMessage m, final String command) {
m.$(this).command(command);
}
@Override
public void text(final PlotMessage m, final String text) {
m.$(this).then(ChatColor.stripColor(text));
}
@Override
public void send(final PlotMessage m, final PlotPlayer player) {
if (ConsolePlayer.isConsole(player)) {
player.sendMessage(m.$(this).toOldMessageFormat());
} else {
m.$(this).send(((BukkitPlayer) player).player);
}
}
@Override
public void suggest(final PlotMessage m, final String command) {
m.$(this).suggest(command);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.commands.MainCommand;
import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.StringComparison;
import com.plotsquared.bukkit.commands.DebugUUID;
import com.plotsquared.general.commands.Command;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Created 2015-02-20 for PlotSquared
*
*/
public class BukkitCommand implements CommandExecutor, TabCompleter {
public BukkitCommand() {
MainCommand.getInstance().addCommand(new DebugUUID());
}
@Override
public boolean onCommand(final CommandSender commandSender, final org.bukkit.command.Command command, final String commandLabel,
final String[] args) {
if (commandSender instanceof Player) {
return MainCommand.onCommand(BukkitUtil.getPlayer((Player) commandSender), commandLabel, args);
}
if (commandSender == null || commandSender.getClass() == Bukkit.getConsoleSender().getClass()) {
return MainCommand.onCommand(ConsolePlayer.getConsole(), commandLabel, args);
}
@SuppressWarnings("deprecation")
ConsolePlayer sender = new ConsolePlayer() {
@Override
public void sendMessage(String message) {
commandSender.sendMessage(commandLabel);
}
@Override
public boolean hasPermission(String perm) {
return commandSender.hasPermission(commandLabel);
}
@Override
public String getName() {
if (commandSender.getName().equals("CONSOLE")) {
return "*";
}
return commandSender.getName();
}
};
sender.teleport(ConsolePlayer.getConsole().getLocationFull());
boolean result = MainCommand.onCommand(sender, commandLabel, args);
ConsolePlayer.getConsole().teleport(sender.getLocationFull());
return result;
}
@Override
public List<String> onTabComplete(final CommandSender commandSender, final org.bukkit.command.Command command, final String s,
final String[] strings) {
if (!(commandSender instanceof Player)) {
return null;
}
final PlotPlayer player = BukkitUtil.getPlayer((Player) commandSender);
if (strings.length < 1) {
if ((strings.length == 0) || "plots".startsWith(s)) {
return Collections.singletonList("plots");
}
}
if (strings.length > 1) {
return null;
}
final Set<String> tabOptions = new HashSet<>();
final String arg = strings[0].toLowerCase();
ArrayList<String> labels = new ArrayList<>();
for (final Command<PlotPlayer> cmd : MainCommand.getInstance().getCommands()) {
final String label = cmd.getCommand();
HashSet<String> aliases = new HashSet<>(cmd.getAliases());
aliases.add(label);
for (String alias : aliases) {
labels.add(alias);
if (alias.startsWith(arg)) {
if (Permissions.hasPermission(player, cmd.getPermission())) {
tabOptions.add(label);
} else {
break;
}
}
}
}
String best = new StringComparison<>(arg, labels).getBestMatch();
tabOptions.add(best);
if (!tabOptions.isEmpty()) {
return new ArrayList<>(tabOptions);
}
return null;
}
}

View File

@ -0,0 +1,98 @@
package com.plotsquared.bukkit.util;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import org.bukkit.plugin.RegisteredServiceProvider;
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.EconHandler;
import com.plotsquared.bukkit.object.BukkitOfflinePlayer;
import com.plotsquared.bukkit.object.BukkitPlayer;
public class BukkitEconHandler extends EconHandler {
private Economy econ;
private Permission perms;
public Economy getEconomy() {
init();
return econ;
}
public Permission getPermissions() {
init();
return perms;
}
public boolean init() {
if (econ == null || perms == null) {
setupPermissions();
setupEconomy();
}
return econ != null && perms != null;
}
private boolean setupPermissions() {
final RegisteredServiceProvider<Permission> permissionProvider =
Bukkit.getServer().getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class);
if (permissionProvider != null) {
perms = permissionProvider.getProvider();
}
return perms != null;
}
private boolean setupEconomy() {
final RegisteredServiceProvider<Economy> economyProvider =
Bukkit.getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if (economyProvider != null) {
econ = economyProvider.getProvider();
}
return econ != null;
}
@Override
public double getMoney(final PlotPlayer player) {
final double bal = super.getMoney(player);
if (Double.isNaN(bal)) {
return econ.getBalance(((BukkitPlayer) player).player);
}
return bal;
}
@Override
public void withdrawMoney(final PlotPlayer player, final double amount) {
econ.withdrawPlayer(((BukkitPlayer) player).player, amount);
}
@Override
public void depositMoney(final PlotPlayer player, final double amount) {
econ.depositPlayer(((BukkitPlayer) player).player, amount);
}
@Override
public void depositMoney(final OfflinePlotPlayer player, final double amount) {
econ.depositPlayer(((BukkitOfflinePlayer) player).player, amount);
}
@Override
public void setPermission(final String world, final String player, final String perm, final boolean value) {
if (value) {
perms.playerAdd(world, player, perm);
} else {
perms.playerRemove(world, player, perm);
}
}
@Override
public boolean hasPermission(final String world, final String player, final String perm) {
return perms.playerHas(world, Bukkit.getOfflinePlayer(player), perm);
}
@Override
public double getBalance(PlotPlayer player) {
return econ.getBalance(player.getName());
}
}

View File

@ -0,0 +1,127 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotCluster;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.Rating;
import com.intellectualcrafters.plot.util.EventUtil;
import com.plotsquared.bukkit.events.ClusterFlagRemoveEvent;
import com.plotsquared.bukkit.events.PlayerClaimPlotEvent;
import com.plotsquared.bukkit.events.PlayerEnterPlotEvent;
import com.plotsquared.bukkit.events.PlayerLeavePlotEvent;
import com.plotsquared.bukkit.events.PlayerPlotDeniedEvent;
import com.plotsquared.bukkit.events.PlayerPlotHelperEvent;
import com.plotsquared.bukkit.events.PlayerPlotTrustedEvent;
import com.plotsquared.bukkit.events.PlayerTeleportToPlotEvent;
import com.plotsquared.bukkit.events.PlotClearEvent;
import com.plotsquared.bukkit.events.PlotDeleteEvent;
import com.plotsquared.bukkit.events.PlotFlagAddEvent;
import com.plotsquared.bukkit.events.PlotFlagRemoveEvent;
import com.plotsquared.bukkit.events.PlotMergeEvent;
import com.plotsquared.bukkit.events.PlotRateEvent;
import com.plotsquared.bukkit.events.PlotUnlinkEvent;
import com.plotsquared.bukkit.object.BukkitPlayer;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import java.util.ArrayList;
import java.util.UUID;
public class BukkitEventUtil extends EventUtil {
public Player getPlayer(final PlotPlayer player) {
if (player instanceof BukkitPlayer) {
return ((BukkitPlayer) player).player;
}
return null;
}
public boolean callEvent(final Event event) {
Bukkit.getServer().getPluginManager().callEvent(event);
return !(event instanceof Cancellable) || !((Cancellable) event).isCancelled();
}
@Override
public boolean callClaim(final PlotPlayer player, final Plot plot, final boolean auto) {
return callEvent(new PlayerClaimPlotEvent(getPlayer(player), plot, auto));
}
@Override
public boolean callTeleport(final PlotPlayer player, final Location from, final Plot plot) {
return callEvent(new PlayerTeleportToPlotEvent(getPlayer(player), from, plot));
}
@Override
public boolean callClear(final Plot plot) {
return callEvent(new PlotClearEvent(plot));
}
@Override
public void callDelete(final Plot plot) {
callEvent(new PlotDeleteEvent(plot));
}
@Override
public boolean callFlagAdd(final Flag flag, final Plot plot) {
return callEvent(new PlotFlagAddEvent(flag, plot));
}
@Override
public boolean callFlagRemove(final Flag flag, final Plot plot) {
return callEvent(new PlotFlagRemoveEvent(flag, plot));
}
@Override
public boolean callMerge(final Plot plot, final ArrayList<PlotId> plots) {
return callEvent(new PlotMergeEvent(BukkitUtil.getWorld(plot.getArea().worldname), plot, plots));
}
@Override
public boolean callUnlink(final PlotArea area, final ArrayList<PlotId> plots) {
return callEvent(new PlotUnlinkEvent(BukkitUtil.getWorld(area.worldname), area, plots));
}
@Override
public void callEntry(final PlotPlayer player, final Plot plot) {
callEvent(new PlayerEnterPlotEvent(getPlayer(player), plot));
}
@Override
public void callLeave(final PlotPlayer player, final Plot plot) {
callEvent(new PlayerLeavePlotEvent(getPlayer(player), plot));
}
@Override
public void callDenied(final PlotPlayer initiator, final Plot plot, final UUID player, final boolean added) {
callEvent(new PlayerPlotDeniedEvent(getPlayer(initiator), plot, player, added));
}
@Override
public void callTrusted(final PlotPlayer initiator, final Plot plot, final UUID player, final boolean added) {
callEvent(new PlayerPlotHelperEvent(getPlayer(initiator), plot, player, added));
}
@Override
public void callMember(final PlotPlayer initiator, final Plot plot, final UUID player, final boolean added) {
callEvent(new PlayerPlotTrustedEvent(getPlayer(initiator), plot, player, added));
}
@Override
public boolean callFlagRemove(final Flag flag, final PlotCluster cluster) {
return callEvent(new ClusterFlagRemoveEvent(flag, cluster));
}
@Override
public Rating callRating(final PlotPlayer player, final Plot plot, final Rating rating) {
final PlotRateEvent event = new PlotRateEvent(player, rating, plot);
Bukkit.getServer().getPluginManager().callEvent(event);
return event.getRating();
}
}

View File

@ -0,0 +1,323 @@
package com.plotsquared.bukkit.util;
import java.util.HashSet;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.material.Directional;
import org.bukkit.material.MaterialData;
import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotAnalysis;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.TaskManager;
public class BukkitHybridUtils extends HybridUtils {
@Override
public void analyzeRegion(final String world, final RegionWrapper region, final RunnableVal<PlotAnalysis> whenDone) {
// int diff, int variety, int vertices, int rotation, int height_sd
/*
* diff: compare to base by looping through all blocks
* variety: add to HashSet for each PlotBlock
* height_sd: loop over all blocks and get top block
*
* vertices: store air map and compare with neighbours
* for each block check the adjacent
* - Store all blocks then go through in second loop
* - recheck each block
*
*/
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
final World worldObj = Bukkit.getWorld(world);
final ChunkGenerator gen = worldObj.getGenerator();
if (gen == null) {
return;
}
final BiomeGrid nullBiomeGrid = new BiomeGrid() {
@Override
public void setBiome(final int a, final int b, final Biome c) {
}
@Override
public Biome getBiome(final int a, final int b) {
return null;
}
};
final Location bot = new Location(world, region.minX, region.minY, region.minZ);
final Location top = new Location(world, region.maxX, region.maxY, region.maxZ);
final int bx = bot.getX();
final int bz = bot.getZ();
final int tx = top.getX();
final int tz = top.getZ();
final int cbx = bx >> 4;
final int cbz = bz >> 4;
final int ctx = tx >> 4;
final int ctz = tz >> 4;
final Random r = new Random();
MainUtil.initCache();
final int width = (tx - bx) + 1;
final int length = (tz - bz) + 1;
System.gc();
System.gc();
final short[][][] oldblocks = new short[256][width][length];
final short[][][] newblocks = new short[256][width][length];
final Runnable run = new Runnable() {
@Override
public void run() {
ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
// [chunkx, chunkz, pos1x, pos1z, pos2x, pos2z, isedge]
final int X = value[0];
final int Z = value[1];
final short[][] result = gen.generateExtBlockSections(worldObj, r, X, Z, nullBiomeGrid);
final int xb = ((X) << 4) - bx;
final int zb = ((Z) << 4) - bz;
for (int i = 0; i < result.length; i++) {
if (result[i] == null) {
for (int j = 0; j < 4096; j++) {
final int x = MainUtil.x_loc[i][j] + xb;
if ((x < 0) || (x >= width)) {
continue;
}
final int z = MainUtil.z_loc[i][j] + zb;
if ((z < 0) || (z >= length)) {
continue;
}
final int y = MainUtil.y_loc[i][j];
oldblocks[y][x][z] = 0;
}
continue;
}
for (int j = 0; j < result[i].length; j++) {
final int x = MainUtil.x_loc[i][j] + xb;
if ((x < 0) || (x >= width)) {
continue;
}
final int z = MainUtil.z_loc[i][j] + zb;
if ((z < 0) || (z >= length)) {
continue;
}
final int y = MainUtil.y_loc[i][j];
oldblocks[y][x][z] = result[i][j];
}
}
}
}, new Runnable() {
@Override
public void run() {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
final int size = width * length;
final int[] changes = new int[size];
final int[] faces = new int[size];
final int[] data = new int[size];
final int[] air = new int[size];
final int[] variety = new int[size];
int i = 0;
for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) {
final HashSet<Short> types = new HashSet<>();
for (int y = 0; y < 256; y++) {
final short old = oldblocks[y][x][z];
final short now = newblocks[y][x][z];
if (old != now) {
changes[i]++;
}
if (now == 0) {
air[i]++;
} else {
// check vertices
// modifications_adjacent
if ((x > 0) && (z > 0) && (y > 0) && (x < (width - 1)) && (z < (length - 1)) && (y < 255)) {
if (newblocks[y - 1][x][z] == 0) {
faces[i]++;
}
if (newblocks[y][x - 1][z] == 0) {
faces[i]++;
}
if (newblocks[y][x][z - 1] == 0) {
faces[i]++;
}
if (newblocks[y + 1][x][z] == 0) {
faces[i]++;
}
if (newblocks[y][x + 1][z] == 0) {
faces[i]++;
}
if (newblocks[y][x][z + 1] == 0) {
faces[i]++;
}
}
final Material material = Material.getMaterial(now);
final Class<? extends MaterialData> md = material.getData();
if (md.equals(Directional.class)) {
data[i] += 8;
} else if (!md.equals(MaterialData.class)) {
data[i]++;
}
types.add(now);
}
}
variety[i] = types.size();
i++;
}
}
// analyze plot
// put in analysis obj
// run whenDone
final PlotAnalysis analysis = new PlotAnalysis();
analysis.changes = (int) (MathMan.getMean(changes) * 100);
analysis.faces = (int) (MathMan.getMean(faces) * 100);
analysis.data = (int) (MathMan.getMean(data) * 100);
analysis.air = (int) (MathMan.getMean(air) * 100);
analysis.variety = (int) (MathMan.getMean(variety) * 100);
analysis.changes_sd = (int) (MathMan.getSD(changes, analysis.changes));
analysis.faces_sd = (int) (MathMan.getSD(faces, analysis.faces));
analysis.data_sd = (int) (MathMan.getSD(data, analysis.data));
analysis.air_sd = (int) (MathMan.getSD(air, analysis.air));
analysis.variety_sd = (int) (MathMan.getSD(variety, analysis.variety));
System.gc();
System.gc();
whenDone.value = analysis;
whenDone.run();
}
});
}
}, 5);
}
};
System.gc();
MainUtil.initCache();
ChunkManager.chunkTask(bot, top, new RunnableVal<int[]>() {
@Override
public void run(int[] value) {
final int X = value[0];
final int Z = value[1];
worldObj.loadChunk(X, Z);
int minX;
int minZ;
int maxX;
int maxZ;
if (X == cbx) {
minX = bx & 15;
} else {
minX = 0;
}
if (Z == cbz) {
minZ = bz & 15;
} else {
minZ = 0;
}
if (X == ctx) {
maxX = tx & 15;
} else {
maxX = 16;
}
if (Z == ctz) {
maxZ = tz & 15;
} else {
maxZ = 16;
}
final int cbx = X << 4;
final int cbz = Z << 4;
final int xb = (cbx) - bx;
final int zb = (cbz) - bz;
for (int x = minX; x <= maxX; x++) {
final int xx = cbx + x;
for (int z = minZ; z <= maxZ; z++) {
final int zz = cbz + z;
for (int y = 0; y < 256; y++) {
final Block block = worldObj.getBlockAt(xx, y, zz);
final int xr = xb + x;
final int zr = zb + z;
newblocks[y][xr][zr] = (short) block.getTypeId();
}
}
}
worldObj.unloadChunkRequest(X, Z, true);
}
}, new Runnable() {
@Override
public void run() {
TaskManager.runTaskAsync(run);
}
}, 5);
}
});
}
@Override
public int checkModified(final String worldname, final int x1, final int x2, final int y1, final int y2, final int z1, final int z2,
final PlotBlock[] blocks) {
final World world = BukkitUtil.getWorld(worldname);
int count = 0;
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) {
final Block block = world.getBlockAt(x, y, z);
final int id = block.getTypeId();
boolean same = false;
for (final PlotBlock p : blocks) {
if (id == p.id) {
same = true;
break;
}
}
if (!same) {
count++;
}
}
}
}
return count;
}
@Override
public int get_ey(final String worldname, final int sx, final int ex, final int sz, final int ez, final int sy) {
final World world = BukkitUtil.getWorld(worldname);
final int maxY = world.getMaxHeight();
int ey = sy;
for (int x = sx; x <= ex; x++) {
for (int z = sz; z <= ez; z++) {
for (int y = sy; y < maxY; y++) {
if (y > ey) {
final Block block = world.getBlockAt(x, y, z);
if (block.getTypeId() != 0) {
ey = y;
}
}
}
}
}
return ey;
}
}

View File

@ -0,0 +1,126 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.object.PlotInventory;
import com.intellectualcrafters.plot.object.PlotItemStack;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.InventoryUtil;
import com.plotsquared.bukkit.object.BukkitPlayer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
public class BukkitInventoryUtil extends InventoryUtil {
public static ItemStack getItem(final PlotItemStack item) {
if (item == null) {
return null;
}
final ItemStack stack = new ItemStack(item.id, item.amount, item.data);
ItemMeta meta = null;
if (item.name != null) {
meta = stack.getItemMeta();
meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', item.name));
}
if (item.lore != null) {
if (meta == null) {
meta = stack.getItemMeta();
}
final List<String> lore = new ArrayList<>();
for (final String entry : item.lore) {
lore.add(ChatColor.translateAlternateColorCodes('&', entry));
}
meta.setLore(lore);
}
if (meta != null) {
stack.setItemMeta(meta);
}
return stack;
}
@Override
public void open(final PlotInventory inv) {
final BukkitPlayer bp = (BukkitPlayer) inv.player;
final Inventory inventory = Bukkit.createInventory(null, inv.size * 9, inv.getTitle());
final PlotItemStack[] items = inv.getItems();
for (int i = 0; i < inv.size * 9; i++) {
final PlotItemStack item = items[i];
if (item != null) {
inventory.setItem(i, getItem(item));
}
}
inv.player.setMeta("inventory", inv);
bp.player.openInventory(inventory);
}
@Override
public void close(final PlotInventory inv) {
if (!inv.isOpen()) {
return;
}
inv.player.deleteMeta("inventory");
final BukkitPlayer bp = (BukkitPlayer) inv.player;
bp.player.closeInventory();
}
@Override
public void setItem(final PlotInventory inv, final int index, final PlotItemStack item) {
final BukkitPlayer bp = (BukkitPlayer) inv.player;
final InventoryView opened = bp.player.getOpenInventory();
if (!inv.isOpen()) {
return;
}
opened.setItem(index, getItem(item));
bp.player.updateInventory();
}
public PlotItemStack getItem(final ItemStack item) {
if (item == null) {
return null;
}
final int id = item.getTypeId();
final short data = item.getDurability();
final int amount = item.getAmount();
String name = null;
String[] lore = null;
if (item.hasItemMeta()) {
final ItemMeta meta = item.getItemMeta();
if (meta.hasDisplayName()) {
name = meta.getDisplayName();
}
if (meta.hasLore()) {
final List<String> itemLore = meta.getLore();
lore = itemLore.toArray(new String[itemLore.size()]);
}
}
return new PlotItemStack(id, data, amount, name, lore);
}
@Override
public PlotItemStack[] getItems(final PlotPlayer player) {
final BukkitPlayer bp = (BukkitPlayer) player;
final PlayerInventory inv = bp.player.getInventory();
final PlotItemStack[] items = new PlotItemStack[36];
for (int i = 0; i < 36; i++) {
items[i] = getItem(inv.getItem(i));
}
return items;
}
@Override
public boolean isOpen(final PlotInventory inv) {
if (!inv.isOpen()) {
return false;
}
final BukkitPlayer bp = (BukkitPlayer) inv.player;
final InventoryView opened = bp.player.getOpenInventory();
return inv.isOpen() && opened.getType() == InventoryType.CRAFTING && opened.getTitle() == null;
}
}

View File

@ -0,0 +1,50 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.object.PlotMessage;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ChatManager;
import org.bukkit.ChatColor;
import java.util.ArrayList;
import java.util.List;
public class BukkitPlainChatManager extends ChatManager<List<StringBuilder>> {
@Override
public List<StringBuilder> builder() {
return new ArrayList<>();
}
@Override
public void color(final PlotMessage m, final String color) {
final List<StringBuilder> parts = m.$(this);
parts.get(parts.size() - 1).insert(0, color);
}
@Override
public void tooltip(final PlotMessage m, final PlotMessage... tooltips) {
}
@Override
public void command(final PlotMessage m, final String command) {
}
@Override
public void text(final PlotMessage m, final String text) {
m.$(this).add(new StringBuilder(ChatColor.stripColor(text)));
}
@Override
public void send(final PlotMessage m, final PlotPlayer player) {
final StringBuilder built = new StringBuilder();
for (final StringBuilder sb : m.$(this)) {
built.append(sb);
}
player.sendMessage(built.toString());
}
@Override
public void suggest(final PlotMessage m, final String command) {
}
}

View File

@ -0,0 +1,340 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU General Public License as published by /
// the Free Software Foundation; either version 3 of the License, or /
// (at your option) any later version. /
// /
// This program is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /
// GNU General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.plotsquared.bukkit.util;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import com.intellectualcrafters.jnbt.ByteArrayTag;
import com.intellectualcrafters.jnbt.CompoundTag;
import com.intellectualcrafters.jnbt.IntTag;
import com.intellectualcrafters.jnbt.ListTag;
import com.intellectualcrafters.jnbt.ShortTag;
import com.intellectualcrafters.jnbt.StringTag;
import com.intellectualcrafters.jnbt.Tag;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.object.schematic.StateWrapper;
/**
* Schematic Handler
*
*/
public class BukkitSchematicHandler extends SchematicHandler {
@Override
public void getCompoundTag(final String world, final Set<RegionWrapper> regions, final RunnableVal<CompoundTag> whenDone) {
// async
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
// Main positions
Location[] corners = MainUtil.getCorners(world, regions);
final Location bot = corners[0];
final Location top = corners[1];
final int width = (top.getX() - bot.getX()) + 1;
final int height = (top.getY() - bot.getY()) + 1;
final int length = (top.getZ() - bot.getZ()) + 1;
// Main Schematic tag
final HashMap<String, Tag> schematic = new HashMap<>();
schematic.put("Width", new ShortTag("Width", (short) width));
schematic.put("Length", new ShortTag("Length", (short) length));
schematic.put("Height", new ShortTag("Height", (short) height));
schematic.put("Materials", new StringTag("Materials", "Alpha"));
schematic.put("WEOriginX", new IntTag("WEOriginX", 0));
schematic.put("WEOriginY", new IntTag("WEOriginY", 0));
schematic.put("WEOriginZ", new IntTag("WEOriginZ", 0));
schematic.put("WEOffsetX", new IntTag("WEOffsetX", 0));
schematic.put("WEOffsetY", new IntTag("WEOffsetY", 0));
schematic.put("WEOffsetZ", new IntTag("WEOffsetZ", 0));
// Arrays of data types
final List<Tag> tileEntities = new ArrayList<>();
final byte[] blocks = new byte[width * height * length];
final byte[] blockData = new byte[width * height * length];
// Queue
final ArrayDeque<RegionWrapper> queue = new ArrayDeque<>(regions);
TaskManager.runTask(new Runnable() {
@Override
public void run() {
if (queue.isEmpty()) {
TaskManager.runTaskAsync(new Runnable() {
@Override
public void run() {
schematic.put("Blocks", new ByteArrayTag("Blocks", blocks));
schematic.put("Data", new ByteArrayTag("Data", blockData));
schematic.put("Entities", new ListTag("Entities", CompoundTag.class, new ArrayList<Tag>()));
schematic.put("TileEntities", new ListTag("TileEntities", CompoundTag.class, tileEntities));
whenDone.value = new CompoundTag("Schematic", schematic);
TaskManager.runTask(whenDone);
System.gc();
System.gc();
}
});
return;
}
final Runnable regionTask = this;
RegionWrapper region = queue.poll();
Location pos1 = new Location(world, region.minX, region.minY, region.minZ);
Location pos2 = new Location(world, region.maxX, region.maxY, region.maxZ);
final int bx = bot.getX();
final int bz = bot.getZ();
final int p1x = pos1.getX();
final int p1z = pos1.getZ();
final int p2x = pos2.getX();
final int p2z = pos2.getZ();
final int bcx = p1x >> 4;
final int bcz = p1z >> 4;
final int tcx = p2x >> 4;
final int tcz = p2z >> 4;
final int sy = pos1.getY();
final int ey = pos2.getY();
// Generate list of chunks
final ArrayList<ChunkLoc> chunks = new ArrayList<>();
for (int x = bcx; x <= tcx; x++) {
for (int z = bcz; z <= tcz; z++) {
chunks.add(new ChunkLoc(x, z));
}
}
final World worldObj = Bukkit.getWorld(world);
// Main thread
TaskManager.runTask(new Runnable() {
@Override
public void run() {
final long start = System.currentTimeMillis();
while ((!chunks.isEmpty()) && ((System.currentTimeMillis() - start) < 20)) {
// save schematics
final ChunkLoc chunk = chunks.remove(0);
final Chunk bc = worldObj.getChunkAt(chunk.x, chunk.z);
if (!bc.load(false)) {
continue;
}
final int X = chunk.x;
final int Z = chunk.z;
int xxb = X << 4;
int zzb = Z << 4;
int xxt = xxb + 15;
int zzt = zzb + 15;
if (X == bcx) {
xxb = p1x;
}
if (X == tcx) {
xxt = p2x;
}
if (Z == bcz) {
zzb = p1z;
}
if (Z == tcz) {
zzt = p2z;
}
for (int y = sy; y <= Math.min(255, ey); y++) {
final int ry = y - sy;
final int i1 = (ry * width * length);
for (int z = zzb; z <= zzt; z++) {
final int rz = z - bz;
final int i2 = i1 + (rz * width);
for (int x = xxb; x <= xxt; x++) {
final int rx = x - bx;
final int index = i2 + rx;
final Block block = worldObj.getBlockAt(x, y, z);
final int id = block.getTypeId();
switch (id) {
case 0:
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 24:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 122:
case 129:
case 133:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192: {
break;
}
case 54:
case 130:
case 142:
case 27:
case 137:
case 52:
case 154:
case 84:
case 25:
case 144:
case 138:
case 176:
case 177:
case 63:
case 68:
case 323:
case 117:
case 116:
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
case 23:
case 123:
case 124:
case 29:
case 33:
case 151:
case 178: {
// TODO implement fully
final BlockState state = block.getState();
if (state != null) {
final StateWrapper wrapper = new StateWrapper(state);
final CompoundTag rawTag = wrapper.getTag();
if (rawTag != null) {
final Map<String, Tag> values = new HashMap<String, Tag>();
for (final Entry<String, Tag> entry : rawTag.getValue().entrySet()) {
values.put(entry.getKey(), entry.getValue());
}
values.put("id", new StringTag("id", wrapper.getId()));
values.put("x", new IntTag("x", x));
values.put("y", new IntTag("y", y));
values.put("z", new IntTag("z", z));
final CompoundTag tileEntityTag = new CompoundTag(values);
tileEntities.add(tileEntityTag);
}
}
}
default: {
blockData[index] = block.getData();
}
}
// For optimization reasons, we are not supporting custom data types
// Especially since the most likely reason beyond this range is modded servers in which the blocks
// have NBT
// if (type > 255) {
// if (addBlocks == null) {
// addBlocks = new byte[(blocks.length >> 1) + 1];
// }
// addBlocks[index >> 1] = (byte) (((index & 1) == 0) ?
// (addBlocks[index >> 1] & 0xF0) | ((type >> 8) & 0xF) : (addBlocks[index >> 1] & 0xF) | (((type
// >> 8) & 0xF) << 4));
// }
blocks[index] = (byte) id;
}
}
}
}
if (!chunks.isEmpty()) {
TaskManager.runTaskLater(this, 1);
} else {
regionTask.run();
}
}
});
}
});
}
});
}
@Override
public void restoreTag(CompoundTag ct, short x, short y, short z, Schematic schem) {
new StateWrapper(ct).restoreTag(x, y, z, schem);
}
}

View File

@ -0,0 +1,204 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.configuration.ConfigurationSection;
import com.intellectualcrafters.configuration.file.YamlConfiguration;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.config.ConfigurationNode;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Objects;
public class BukkitSetupUtils extends SetupUtils {
@Override
public void updateGenerators() {
if (!SetupUtils.generators.isEmpty()) {
return;
}
final String testWorld = "CheckingPlotSquaredGenerator";
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (plugin.isEnabled()) {
final ChunkGenerator generator = plugin.getDefaultWorldGenerator(testWorld, "");
if (generator != null) {
PS.get().removePlotAreas(testWorld);
final String name = plugin.getDescription().getName();
GeneratorWrapper<?> wrapped;
if (generator instanceof GeneratorWrapper<?>) {
wrapped = (GeneratorWrapper<?>) generator;
} else {
wrapped = new BukkitPlotGenerator(testWorld, generator);
}
SetupUtils.generators.put(name, wrapped);
}
}
}
}
@Override
public String setupWorld(final SetupObject object) {
SetupUtils.manager.updateGenerators();
ConfigurationNode[] steps = object.step == null ? new ConfigurationNode[0] : object.step;
final String world = object.world;
int type = object.type;
String worldPath = "worlds." + object.world;
if (!PS.get().config.contains(worldPath)) {
PS.get().config.createSection(worldPath);
}
ConfigurationSection worldSection = PS.get().config.getConfigurationSection(worldPath);
switch (type) {
case 2: {
if (object.id != null) {
String areaname = object.id + "-" + object.min + "-" + object.max;
String areaPath = "areas." + areaname;
if (!worldSection.contains(areaPath)) {
worldSection.createSection(areaPath);
}
ConfigurationSection areaSection = worldSection.getConfigurationSection(areaPath);
HashMap<String, Object> options = new HashMap<>();
for (final ConfigurationNode step : steps) {
options.put(step.getConstant(), step.getValue());
}
options.put("generator.type", object.type);
options.put("generator.terrain", object.terrain);
options.put("generator.plugin", object.plotManager);
if ((object.setupGenerator != null) && !object.setupGenerator.equals(object.plotManager)) {
options.put("generator.init", object.setupGenerator);
}
for (Entry<String, Object> entry : options.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (worldSection.contains(key)) {
Object current = worldSection.get(key);
if (!Objects.equals(value, current)) {
areaSection.set(key, value);
}
} else {
worldSection.set(key, value);
}
}
}
GeneratorWrapper<?> gen = generators.get(object.setupGenerator);
if ((gen != null) && gen.isFull()) {
object.setupGenerator = null;
}
break;
}
case 1: {
for (final ConfigurationNode step : steps) {
worldSection.set(step.getConstant(), step.getValue());
}
PS.get().config.set("worlds." + world + "." + "generator.type", object.type);
PS.get().config.set("worlds." + world + "." + "generator.terrain", object.terrain);
PS.get().config.set("worlds." + world + "." + "generator.plugin", object.plotManager);
if ((object.setupGenerator != null) && !object.setupGenerator.equals(object.plotManager)) {
PS.get().config.set("worlds." + world + "." + "generator.init", object.setupGenerator);
}
GeneratorWrapper<?> gen = generators.get(object.setupGenerator);
if ((gen != null) && gen.isFull()) {
object.setupGenerator = null;
}
break;
}
case 0: {
for (final ConfigurationNode step : steps) {
worldSection.set(step.getConstant(), step.getValue());
}
break;
}
}
try {
PS.get().config.save(PS.get().configFile);
} catch (final IOException e) {
e.printStackTrace();
}
if (object.setupGenerator != null) {
if ((Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null) && Bukkit.getPluginManager().getPlugin("Multiverse-Core")
.isEnabled()) {
Bukkit.getServer()
.dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv create " + world + " normal -g " + object.setupGenerator);
setGenerator(world, object.setupGenerator);
if (Bukkit.getWorld(world) != null) {
return world;
}
}
if ((Bukkit.getPluginManager().getPlugin("MultiWorld") != null) && Bukkit.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw create " + world + " plugin:" + object.setupGenerator);
setGenerator(world, object.setupGenerator);
if (Bukkit.getWorld(world) != null) {
return world;
}
}
final WorldCreator wc = new WorldCreator(object.world);
wc.generator(object.setupGenerator);
wc.environment(Environment.NORMAL);
Bukkit.createWorld(wc);
setGenerator(world, object.setupGenerator);
} else {
if ((Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null) && Bukkit.getPluginManager().getPlugin("Multiverse-Core")
.isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv create " + world + " normal");
if (Bukkit.getWorld(world) != null) {
return world;
}
}
if ((Bukkit.getPluginManager().getPlugin("MultiWorld") != null) && Bukkit.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw create " + world);
if (Bukkit.getWorld(world) != null) {
return world;
}
}
Bukkit.createWorld(new WorldCreator(object.world).environment(World.Environment.NORMAL));
}
return object.world;
}
public void setGenerator(final String world, final String generator) {
if ((Bukkit.getWorlds().isEmpty()) || !Bukkit.getWorlds().get(0).getName().equals(world)) {
return;
}
final File file = new File("bukkit.yml").getAbsoluteFile();
final YamlConfiguration yml = YamlConfiguration.loadConfiguration(file);
yml.set("worlds." + world + ".generator", generator);
try {
yml.save(file);
} catch (final IOException e) {
e.printStackTrace();
}
}
@Override
public String getGenerator(final PlotArea plotworld) {
if (SetupUtils.generators.isEmpty()) {
updateGenerators();
}
final World world = Bukkit.getWorld(plotworld.worldname);
if (world == null) {
return null;
}
final ChunkGenerator generator = world.getGenerator();
if (!(generator instanceof BukkitPlotGenerator)) {
return null;
}
for (final Entry<String, GeneratorWrapper<?>> entry : generators.entrySet()) {
GeneratorWrapper<?> current = entry.getValue();
if (current.equals(generator)) {
return entry.getKey();
}
}
return null;
}
}

View File

@ -0,0 +1,45 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.BukkitMain;
import org.bukkit.Bukkit;
public class BukkitTaskManager extends TaskManager {
@Override
public int taskRepeat(final Runnable r, final int interval) {
return BukkitMain.THIS.getServer().getScheduler().scheduleSyncRepeatingTask(BukkitMain.THIS, r, interval, interval);
}
@SuppressWarnings("deprecation") @Override
public int taskRepeatAsync(final Runnable r, final int interval) {
return BukkitMain.THIS.getServer().getScheduler().scheduleAsyncRepeatingTask(BukkitMain.THIS, r, interval, interval);
}
@Override
public void taskAsync(final Runnable r) {
BukkitMain.THIS.getServer().getScheduler().runTaskAsynchronously(BukkitMain.THIS, r).getTaskId();
}
@Override
public void task(final Runnable r) {
BukkitMain.THIS.getServer().getScheduler().runTask(BukkitMain.THIS, r).getTaskId();
}
@Override
public void taskLater(final Runnable r, final int delay) {
BukkitMain.THIS.getServer().getScheduler().runTaskLater(BukkitMain.THIS, r, delay).getTaskId();
}
@Override
public void taskLaterAsync(final Runnable r, final int delay) {
BukkitMain.THIS.getServer().getScheduler().runTaskLaterAsynchronously(BukkitMain.THIS, r, delay);
}
@Override
public void cancelTask(final int task) {
if (task != -1) {
Bukkit.getScheduler().cancelTask(task);
}
}
}

View File

@ -0,0 +1,310 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.schematic.PlotItem;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.StringComparison;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.plotsquared.bukkit.object.BukkitPlayer;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import org.bukkit.material.Sandstone;
import org.bukkit.material.Step;
import org.bukkit.material.Tree;
import org.bukkit.material.WoodenStep;
import org.bukkit.material.Wool;
import java.util.Arrays;
import java.util.List;
public class BukkitUtil extends WorldUtil {
private static String lastString = null;
private static World lastWorld = null;
private static Player lastPlayer = null;
private static PlotPlayer lastPlotPlayer = null;
public static void removePlayer(final String plr) {
lastPlayer = null;
lastPlotPlayer = null;
}
public static PlotPlayer getPlayer(final OfflinePlayer op) {
if (op.isOnline()) {
return getPlayer(op.getPlayer());
}
final Player player = OfflinePlayerUtil.loadPlayer(op);
player.loadData();
return new BukkitPlayer(player, true);
}
public static PlotPlayer getPlayer(final Player player) {
if (player == lastPlayer) {
return lastPlotPlayer;
}
final String name = player.getName();
final PlotPlayer pp = UUIDHandler.getPlayer(name);
if (pp != null) {
return pp;
}
lastPlotPlayer = new BukkitPlayer(player);
UUIDHandler.getPlayers().put(name, lastPlotPlayer);
lastPlayer = player;
return lastPlotPlayer;
}
public static Location getLocation(final org.bukkit.Location loc) {
return new Location(loc.getWorld().getName(), MathMan.roundInt(loc.getX()), MathMan.roundInt(loc.getY()), MathMan.roundInt(loc.getZ()));
}
public static org.bukkit.Location getLocation(final Location loc) {
return new org.bukkit.Location(getWorld(loc.getWorld()), loc.getX(), loc.getY(), loc.getZ());
}
public static World getWorld(final String string) {
if (StringMan.isEqual(string, lastString)) {
if (lastWorld != null) {
return lastWorld;
}
}
final World world = Bukkit.getWorld(string);
lastString = string;
lastWorld = world;
return world;
}
public static String getWorld(final Entity entity) {
return entity.getWorld().getName();
}
public static List<Entity> getEntities(final String worldname) {
return getWorld(worldname).getEntities();
}
public static Location getLocation(final Entity entity) {
final org.bukkit.Location loc = entity.getLocation();
final String world = loc.getWorld().getName();
return new Location(world, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
public static Location getLocationFull(final Entity entity) {
final org.bukkit.Location loc = entity.getLocation();
return new Location(loc.getWorld().getName(), MathMan.roundInt(loc.getX()), MathMan.roundInt(loc.getY()), MathMan.roundInt(loc.getZ()),
loc.getYaw(), loc.getPitch());
}
@Override
public boolean isWorld(final String world) {
return getWorld(world) != null;
}
@Override
public String getBiome(final String world, final int x, final int z) {
return getWorld(world).getBiome(x, z).name();
}
@Override
public void setSign(final String worldname, final int x, final int y, final int z, final String[] lines) {
final World world = getWorld(worldname);
final Block block = world.getBlockAt(x, y, z);
// block.setType(Material.AIR);
block.setTypeIdAndData(Material.WALL_SIGN.getId(), (byte) 2, false);
final BlockState blockstate = block.getState();
if (blockstate instanceof Sign) {
final Sign sign = (Sign) blockstate;
for (int i = 0; i < lines.length; i++) {
sign.setLine(i, lines[i]);
}
sign.update(true);
TaskManager.runTaskLater(new Runnable() {
@Override
public void run() {
sign.update(true);
}
}, 20);
}
}
@Override
public String[] getSign(final Location loc) {
final Block block = getWorld(loc.getWorld()).getBlockAt(loc.getX(), loc.getY(), loc.getZ());
if (block != null) {
if (block.getState() instanceof Sign) {
final Sign sign = (Sign) block.getState();
return sign.getLines();
}
}
return null;
}
@Override
public Location getSpawn(final String world) {
final org.bukkit.Location temp = getWorld(world).getSpawnLocation();
return new Location(world, temp.getBlockX(), temp.getBlockY(), temp.getBlockZ(), temp.getYaw(), temp.getPitch());
}
@Override
public int getHighestBlock(final String world, final int x, final int z) {
return getWorld(world).getHighestBlockAt(x, z).getY();
}
@Override
public int getBiomeFromString(final String biomeStr) {
try {
final Biome biome = Biome.valueOf(biomeStr.toUpperCase());
if (biome == null) {
return -1;
}
return Arrays.asList(Biome.values()).indexOf(biome);
} catch (final IllegalArgumentException e) {
return -1;
}
}
@Override
public String[] getBiomeList() {
final Biome[] biomes = Biome.values();
final String[] list = new String[biomes.length];
for (int i = 0; i < biomes.length; i++) {
list[i] = biomes[i].name();
}
return list;
}
@Override
public boolean addItems(final String worldname, final PlotItem items) {
final World world = getWorld(worldname);
final Block block = world.getBlockAt(items.x, items.y, items.z);
if (block == null) {
return false;
}
final BlockState state = block.getState();
if (state instanceof InventoryHolder) {
final InventoryHolder holder = (InventoryHolder) state;
final Inventory inv = holder.getInventory();
for (int i = 0; i < items.id.length; i++) {
final ItemStack item = new ItemStack(items.id[i], items.amount[i], items.data[i]);
inv.addItem(item);
}
state.update(true);
return true;
}
return false;
}
@Override
public boolean isBlockSolid(final PlotBlock block) {
try {
final Material material = Material.getMaterial(block.id);
if (material.isBlock() && material.isSolid() && !material.hasGravity()) {
final Class<? extends MaterialData> data = material.getData();
if (data.equals(MaterialData.class) && !material.isTransparent() && material.isOccluding()
|| data.equals(Tree.class)
|| data.equals(Sandstone.class)
|| data.equals(Wool.class)
|| data.equals(Step.class)
|| data.equals(WoodenStep.class)) {
switch (material) {
case NOTE_BLOCK:
case MOB_SPAWNER:
return false;
default:
return true;
}
}
}
return false;
} catch (final Exception e) {
return false;
}
}
@Override
public String getClosestMatchingName(final PlotBlock block) {
try {
return Material.getMaterial(block.id).name();
} catch (final Exception e) {
return null;
}
}
@Override
public StringComparison<PlotBlock>.ComparisonResult getClosestBlock(String name) {
try {
final Material material = Material.valueOf(name.toUpperCase());
return new StringComparison<PlotBlock>().new ComparisonResult(0, new PlotBlock((short) material.getId(), (byte) 0));
} catch (IllegalArgumentException e) {
}
try {
byte data;
final String[] split = name.split(":");
if (split.length == 2) {
data = Byte.parseByte(split[1]);
name = split[0];
} else {
data = 0;
}
double match;
short id;
if (MathMan.isInteger(split[0])) {
id = Short.parseShort(split[0]);
match = 0;
} else {
final StringComparison<Material>.ComparisonResult comparison = new StringComparison<>(name, Material.values()).getBestMatchAdvanced();
match = comparison.match;
id = (short) comparison.best.getId();
}
final PlotBlock block = new PlotBlock(id, data);
final StringComparison<PlotBlock> outer = new StringComparison<>();
return outer.new ComparisonResult(match, block);
} catch (NumberFormatException e) {
}
return null;
}
@Override
public void setBiomes(final String worldname, RegionWrapper region, final String biomeStr) {
final World world = getWorld(worldname);
final Biome biome = Biome.valueOf(biomeStr.toUpperCase());
for (int x = region.minX; x <= region.maxX; x++) {
for (int z = region.minZ; z <= region.maxZ; z++) {
world.setBiome(x, z, biome);
}
}
}
@Override
public PlotBlock getBlock(final Location loc) {
final World world = getWorld(loc.getWorld());
final Block block = world.getBlockAt(loc.getX(), loc.getY(), loc.getZ());
if (block == null) {
return new PlotBlock((short) 0, (byte) 0);
}
return new PlotBlock((short) block.getTypeId(), block.getData());
}
@Override
public String getMainWorld() {
return Bukkit.getWorlds().get(0).getName();
}
}

View File

@ -0,0 +1,715 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU General Public License as published by /
// the Free Software Foundation; either version 3 of the License, or /
// (at your option) any later version. /
// /
// This program is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /
// GNU General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.plotsquared.bukkit.util;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.scheduler.BukkitTask;
import com.intellectualcrafters.configuration.InvalidConfigurationException;
import com.intellectualcrafters.configuration.file.YamlConfiguration;
import com.intellectualcrafters.plot.PS;
public class Metrics {
/**
* The current revision number
*/
private final static int REVISION = 7;
/**
* The base url of the metrics domain
*/
private static final String BASE_URL = "http://report.mcstats.org";
/**
* The url used to report a server's status
*/
private static final String REPORT_URL = "/plugin/%s";
/**
* Interval of time to ping (in minutes)
*/
private static final int PING_INTERVAL = 15;
/**
* The plugin this metrics submits for
*/
private final Plugin plugin;
/**
* All of the custom graphs to submit to metrics
*/
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
/**
* The plugin configuration file
*/
private final YamlConfiguration configuration;
/**
* The plugin configuration file
*/
private final File configurationFile;
/**
* Unique server id
*/
private final String guid;
/**
* Debug mode
*/
private final boolean debug;
/**
* Lock for synchronization
*/
private final Object optOutLock = new Object();
/**
* The scheduled task
*/
private volatile BukkitTask task = null;
public Metrics(final Plugin plugin) throws IOException {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
}
this.plugin = plugin;
// load the config
configurationFile = getConfigFile();
configuration = YamlConfiguration.loadConfiguration(configurationFile);
// add some defaults
configuration.addDefault("opt-out", false);
configuration.addDefault("guid", UUID.randomUUID().toString());
configuration.addDefault("debug", false);
// Do we need to create the file?
if (configuration.get("guid", null) == null) {
configuration.options().header("http://mcstats.org").copyDefaults(true);
configuration.save(configurationFile);
}
// Load the guid then
guid = configuration.getString("guid");
debug = configuration.getBoolean("debug", false);
}
/**
* GZip compress a string of bytes
*
* @param input
*
* @return byte[] the file as a byte array
*/
public static byte[] gzip(final String input) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = null;
try {
gzos = new GZIPOutputStream(baos);
gzos.write(input.getBytes("UTF-8"));
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (gzos != null) {
try {
gzos.close();
} catch (final IOException ignore) {
}
}
}
return baos.toByteArray();
}
/**
* Appends a json encoded key/value pair to the given string builder.
*
* @param json
* @param key
* @param value
*
* @throws UnsupportedEncodingException
*/
private static void appendJSONPair(final StringBuilder json, final String key, final String value) {
boolean isValueNumeric = false;
try {
if (value.equals("0") || !value.endsWith("0")) {
Double.parseDouble(value);
isValueNumeric = true;
}
} catch (final NumberFormatException e) {
isValueNumeric = false;
}
if (json.charAt(json.length() - 1) != '{') {
json.append(',');
}
json.append(escapeJSON(key));
json.append(':');
if (isValueNumeric) {
json.append(value);
} else {
json.append(escapeJSON(value));
}
}
/**
* Escape a string to create a valid JSON string
*
* @param text
*
* @return String
*/
private static String escapeJSON(final String text) {
final StringBuilder builder = new StringBuilder();
builder.append('"');
for (int index = 0; index < text.length(); index++) {
final char chr = text.charAt(index);
switch (chr) {
case '"':
case '\\':
builder.append('\\');
builder.append(chr);
break;
case '\b':
builder.append("\\b");
break;
case '\t':
builder.append("\\t");
break;
case '\n':
builder.append("\\n");
break;
case '\r':
builder.append("\\r");
break;
default:
if (chr < ' ') {
final String t = "000" + Integer.toHexString(chr);
builder.append("\\u" + t.substring(t.length() - 4));
} else {
builder.append(chr);
}
break;
}
}
builder.append('"');
return builder.toString();
}
/**
* Encode text as UTF-8
*
* @param text the text to encode
*
* @return the encoded text, as UTF-8
*/
private static String urlEncode(final String text) throws UnsupportedEncodingException {
return URLEncoder.encode(text, "UTF-8");
}
/**
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
* website. Plotters can be added to the graph object returned.
*
* @param name The name of the graph
*
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
*/
public Graph createGraph(final String name) {
if (name == null) {
throw new IllegalArgumentException("Graph name cannot be null");
}
// Construct the graph object
final Graph graph = new Graph(name);
// Now we can add our graph
graphs.add(graph);
// and return back
return graph;
}
/**
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend
*
* @param graph The name of the graph
*/
public void addGraph(final Graph graph) {
if (graph == null) {
throw new IllegalArgumentException("Graph cannot be null");
}
graphs.add(graph);
}
/**
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
* ticks.
*
* @return True if statistics measuring is running, otherwise false.
*/
public boolean start() {
synchronized (optOutLock) {
// Did we opt out?
if (isOptOut()) {
return false;
}
// Is metrics already running?
if (task != null) {
return true;
}
// Begin hitting the server with glorious data
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
private boolean firstPost = true;
@Override
public void run() {
try {
// This has to be synchronized or it can collide
// with
// the disable method.
synchronized (optOutLock) {
// Disable Task, if it is running and the
// server
// owner decided to opt-out
if (isOptOut() && task != null) {
task.cancel();
task = null;
// Tell all plotters to stop gathering
// information.
for (final Graph graph : graphs) {
graph.onOptOut();
}
}
}
// We use the inverse of firstPost because if it
// is the
// first time we are posting,
// it is not a interval ping, so it evaluates to
// FALSE
// Each time thereafter it will evaluate to
// TRUE, i.e
// PING!
postPlugin(!firstPost);
// After the first post we set firstPost to
// false
// Each post thereafter will be a ping
firstPost = false;
} catch (final IOException e) {
if (debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
}
}
}
}, 0, PING_INTERVAL * 1200);
return true;
}
}
/**
* Has the server owner denied plugin metrics?
*
* @return true if metrics should be opted out of it
*/
public boolean isOptOut() {
synchronized (optOutLock) {
try {
// Reload the metrics file
configuration.load(getConfigFile());
} catch (final IOException ex) {
if (debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
return true;
} catch (final InvalidConfigurationException ex) {
if (debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
return true;
}
return configuration.getBoolean("opt-out", false);
}
}
/**
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
*
* @throws java.io.IOException
*/
public void enable() throws IOException {
// This has to be synchronized or it can collide with the check in the
// task.
synchronized (optOutLock) {
// Check if the server owner has already set opt-out, if not, set
// it.
if (isOptOut()) {
configuration.set("opt-out", false);
configuration.save(configurationFile);
}
// Enable Task, if it is not running
if (task == null) {
start();
}
}
}
/**
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
*
* @throws java.io.IOException
*/
public void disable() throws IOException {
// This has to be synchronized or it can collide with the check in the
// task.
synchronized (optOutLock) {
// Check if the server owner has already set opt-out, if not, set
// it.
if (!isOptOut()) {
configuration.set("opt-out", true);
configuration.save(configurationFile);
}
// Disable Task, if it is running
if (task != null) {
task.cancel();
task = null;
}
}
}
/**
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status
*
* @return the File object for the config file
*/
public File getConfigFile() {
// I believe the easiest way to get the base folder (e.g craftbukkit set
// via -P) for plugins to use
// is to abuse the plugin object we already have
// plugin.getDataFolder() => base/plugins/PluginA/
// pluginsFolder => base/plugins/
// The base is not necessarily relative to the startup directory.
final File pluginsFolder = plugin.getDataFolder().getParentFile();
// return => base/plugins/PluginMetrics/config.yml
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
}
/**
* Generic method that posts a plugin to the metrics website
*/
private void postPlugin(final boolean isPing) throws IOException {
// Server software specific section
final PluginDescriptionFile description = plugin.getDescription();
final String pluginName = description.getName();
final boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE
// if
// online
// mode
// is
// enabled
final String pluginVersion = description.getVersion();
final String serverVersion = Bukkit.getVersion();
int playersOnline = 0;
try {
if (Bukkit.class.getMethod("getOnlinePlayers", new Class<?>[0]).getReturnType() == Collection.class) {
playersOnline = ((Collection<?>) Bukkit.class.getMethod("getOnlinePlayers", new Class<?>[0]).invoke(null)).size();
} else {
playersOnline = ((Player[]) Bukkit.class.getMethod("getOnlinePlayers", new Class<?>[0]).invoke(null)).length;
}
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
}
// END server software specific section -- all code below does not use
// any code outside of this class / Java
// Construct the post data
final StringBuilder json = new StringBuilder(1024);
json.append('{');
// The plugin's description file containg all of the plugin data such as
// name, version, author, etc
appendJSONPair(json, "guid", guid);
appendJSONPair(json, "plugin_version", pluginVersion);
appendJSONPair(json, "server_version", serverVersion);
appendJSONPair(json, "players_online", Integer.toString(playersOnline));
// New data as of R6
final String osname = System.getProperty("os.name");
String osarch = System.getProperty("os.arch");
final String osversion = System.getProperty("os.version");
final String java_version = System.getProperty("java.version");
final int coreCount = Runtime.getRuntime().availableProcessors();
// normalize os arch .. amd64 -> x86_64
if (osarch.equals("amd64")) {
osarch = "x86_64";
}
appendJSONPair(json, "osname", osname);
appendJSONPair(json, "osarch", osarch);
appendJSONPair(json, "osversion", osversion);
appendJSONPair(json, "cores", Integer.toString(coreCount));
appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0");
appendJSONPair(json, "java_version", java_version);
// If we're pinging, append it
if (isPing) {
appendJSONPair(json, "ping", "1");
}
if (!graphs.isEmpty()) {
synchronized (graphs) {
json.append(',');
json.append('"');
json.append("graphs");
json.append('"');
json.append(':');
json.append('{');
boolean firstGraph = true;
for (final Graph graph : graphs) {
final StringBuilder graphJson = new StringBuilder();
graphJson.append('{');
for (final Plotter plotter : graph.getPlotters()) {
appendJSONPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue()));
}
graphJson.append('}');
if (!firstGraph) {
json.append(',');
}
json.append(escapeJSON(graph.getName()));
json.append(':');
json.append(graphJson);
firstGraph = false;
}
json.append('}');
}
}
// close json
json.append('}');
// Create the url
final URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
// Connect to the website
URLConnection connection;
// Mineshafter creates a socks proxy, so we can safely bypass it
// It does not reroute POST requests so we need to go around it
if (isMineshafterPresent()) {
connection = url.openConnection(Proxy.NO_PROXY);
} else {
connection = url.openConnection();
}
final byte[] uncompressed = json.toString().getBytes();
final byte[] compressed = gzip(json.toString());
// Headers
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.setDoOutput(true);
if (debug) {
PS.debug("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
}
// Write the data
String response;
try (OutputStream os = connection.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
os.write(compressed);
os.flush();
// Now read the response
response = reader.readLine();
}
if (response == null || response.startsWith("ERR") || response.startsWith("7")) {
if (response == null) {
response = "null";
} else if (response.startsWith("7")) {
response = response.substring(response.startsWith("7,") ? 2 : 1);
}
throw new IOException(response);
} else {
// Is this the first update this hour?
if ("1".equals(response) || response.contains("This is your first update this hour")) {
synchronized (graphs) {
for (final Graph graph : graphs) {
for (final Plotter plotter : graph.getPlotters()) {
plotter.reset();
}
}
}
}
}
}
/**
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
*
* @return true if mineshafter is installed on the server
*/
private boolean isMineshafterPresent() {
try {
Class.forName("mineshafter.MineServer");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
/**
* Represents a custom graph on the website
*/
public static class Graph {
/**
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
* rejected
*/
private final String name;
/**
* The set of plotters that are contained within this graph
*/
private final Set<Plotter> plotters = new LinkedHashSet<>();
private Graph(final String name) {
this.name = name;
}
/**
* Gets the graph's name
*
* @return the Graph's name
*/
public String getName() {
return name;
}
/**
* Add a plotter to the graph, which will be used to plot entries
*
* @param plotter the plotter to add to the graph
*/
public void addPlotter(final Plotter plotter) {
plotters.add(plotter);
}
/**
* Remove a plotter from the graph
*
* @param plotter the plotter to remove from the graph
*/
public void removePlotter(final Plotter plotter) {
plotters.remove(plotter);
}
/**
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph
*
* @return an unmodifiable {@link java.util.Set} of the plotter objects
*/
public Set<Plotter> getPlotters() {
return Collections.unmodifiableSet(plotters);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(final Object object) {
if (!(object instanceof Graph)) {
return false;
}
final Graph graph = (Graph) object;
return graph.name.equals(name);
}
/**
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
*/
protected void onOptOut() {
}
}
/**
* Interface used to collect custom data for a plugin
*/
public static abstract class Plotter {
/**
* The plot's name
*/
private final String name;
/**
* Construct a plotter with the default plot name
*/
public Plotter() {
this("Default");
}
/**
* Construct a plotter with a specific plot name
*
* @param name the name of the plotter to use, which will show up on the website
*/
public Plotter(final String name) {
this.name = name;
}
/**
* Get the current value for the plotted point. Since this function defers to an external function it may or may
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
* from any thread so care should be taken when accessing resources that need to be synchronized.
*
* @return the current value for the point to be plotted.
*/
public abstract int getValue();
/**
* Get the column name for the plotted point
*
* @return the plotted point's column name
*/
public String getColumnName() {
return name;
}
/**
* Called after the website graphs have been updated
*/
public void reset() {
}
@Override
public int hashCode() {
return getColumnName().hashCode();
}
@Override
public boolean equals(final Object object) {
if (!(object instanceof Plotter)) {
return false;
}
final Plotter plotter = (Plotter) object;
return plotter.name.equals(name) && plotter.getValue() == getValue();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
package com.plotsquared.bukkit.util;
import static com.intellectualcrafters.plot.util.ReflectionUtils.callConstructor;
import static com.intellectualcrafters.plot.util.ReflectionUtils.callMethod;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getCbClass;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getNmsClass;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getUtilClass;
import static com.intellectualcrafters.plot.util.ReflectionUtils.makeConstructor;
import static com.intellectualcrafters.plot.util.ReflectionUtils.makeMethod;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.UUID;
public class OfflinePlayerUtil {
public static Player loadPlayer(final String name) {
return loadPlayer(Bukkit.getOfflinePlayer(name));
}
public static Player loadPlayer(final UUID id) {
return loadPlayer(Bukkit.getOfflinePlayer(id));
}
public static Player loadPlayer(final OfflinePlayer player) {
if (player == null) {
return null;
}
if (player instanceof Player) {
return (Player) player;
}
return loadPlayer(player.getUniqueId(), player.getName());
}
private static Player loadPlayer(final UUID id, final String name) {
final Object server = getMinecraftServer();
final Object interactManager = newPlayerInteractManager();
final Object worldServer = getWorldServer();
final Object profile = newGameProfile(id, name);
final Class<?> entityPlayerClass = getNmsClass("EntityPlayer");
final Constructor entityPlayerConstructor = makeConstructor(entityPlayerClass, getNmsClass("MinecraftServer"), getNmsClass("WorldServer"),
getUtilClass("com.mojang.authlib.GameProfile"),
getNmsClass("PlayerInteractManager"));
final Object entityPlayer = callConstructor(entityPlayerConstructor, server, worldServer, profile, interactManager);
return (Player) getBukkitEntity(entityPlayer);
}
private static Object newGameProfile(final UUID id, final String name) {
final Class<?> gameProfileClass = getUtilClass("com.mojang.authlib.GameProfile");
if (gameProfileClass == null) { //Before uuids
return name;
}
Constructor gameProfileConstructor = makeConstructor(gameProfileClass, UUID.class, String.class);
if (gameProfileConstructor == null) { //Verson has string constructor
gameProfileConstructor = makeConstructor(gameProfileClass, String.class, String.class);
return callConstructor(gameProfileConstructor, id.toString(), name);
} else { //Version has uuid constructor
return callConstructor(gameProfileConstructor, id, name);
}
}
private static Object newPlayerInteractManager() {
final Object worldServer = getWorldServer();
final Class<?> playerInteractClass = getNmsClass("PlayerInteractManager");
final Class<?> worldClass = getNmsClass("World");
final Constructor c = makeConstructor(playerInteractClass, worldClass);
return callConstructor(c, worldServer);
}
private static Object getWorldServer() {
final Object server = getMinecraftServer();
final Class<?> minecraftServerClass = getNmsClass("MinecraftServer");
final Method getWorldServer = makeMethod(minecraftServerClass, "getWorldServer", int.class);
return callMethod(getWorldServer, server, 0);
}
//NMS Utils
private static Object getMinecraftServer() {
return callMethod(makeMethod(getCbClass("CraftServer"), "getServer"), Bukkit.getServer());
}
private static Entity getBukkitEntity(final Object o) {
final Method getBukkitEntity = makeMethod(o.getClass(), "getBukkitEntity");
return callMethod(getBukkitEntity, o);
}
}

View File

@ -0,0 +1,193 @@
package com.plotsquared.bukkit.util;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.bukkit.object.BukkitPlayer;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
/**
* An utility that can be used to send chunks, rather than using bukkit code to do so (uses heavy NMS)
*
*/
public class SendChunk {
// // Ref Class
private final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer");
private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk");
private final RefClass classPacket = getRefClass("{nms}.Packet");
private final RefClass classConnection = getRefClass("{nms}.PlayerConnection");
private final RefClass classChunk = getRefClass("{nms}.Chunk");
private final RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer");
private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
private final RefMethod methodGetHandlePlayer;
private final RefMethod methodGetHandleChunk;
private final RefConstructor MapChunk;
private final RefField connection;
private final RefMethod send;
private final RefMethod methodInitLighting;
/**
* Constructor
*/
public SendChunk() {
methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle");
methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
methodInitLighting = classChunk.getMethod("initLighting");
MapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), boolean.class, int.class);
connection = classEntityPlayer.getField("playerConnection");
send = classConnection.getMethod("sendPacket", classPacket.getRealClass());
}
public void sendChunk(final Collection<Chunk> input) {
final HashSet<Chunk> chunks = new HashSet<Chunk>(input);
final HashMap<String, ArrayList<Chunk>> map = new HashMap<>();
final int view = Bukkit.getServer().getViewDistance();
for (final Chunk chunk : chunks) {
final String world = chunk.getWorld().getName();
ArrayList<Chunk> list = map.get(world);
if (list == null) {
list = new ArrayList<>();
map.put(world, list);
}
list.add(chunk);
final Object c = methodGetHandleChunk.of(chunk).call();
methodInitLighting.of(c).call();
}
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
PlotPlayer pp = entry.getValue();
final Plot plot = pp.getCurrentPlot();
Location loc = null;
String world;
if (plot != null) {
world = plot.getArea().worldname;
} else {
loc = pp.getLocation();
world = loc.getWorld();
}
final ArrayList<Chunk> list = map.get(world);
if (list == null) {
continue;
}
if (loc == null) {
loc = pp.getLocation();
}
final int cx = loc.getX() >> 4;
final int cz = loc.getZ() >> 4;
final Player player = ((BukkitPlayer) pp).player;
final Object entity = methodGetHandlePlayer.of(player).call();
for (final Chunk chunk : list) {
final int dx = Math.abs(cx - chunk.getX());
final int dz = Math.abs(cz - chunk.getZ());
if ((dx > view) || (dz > view)) {
continue;
}
final Object c = methodGetHandleChunk.of(chunk).call();
chunks.remove(chunk);
final Object con = connection.of(entity).get();
// if (dx != 0 || dz != 0) {
// Object packet = MapChunk.create(c, true, 0);
// send.of(con).call(packet);
// }
final Object packet = MapChunk.create(c, true, 65535);
send.of(con).call(packet);
}
}
for (final Chunk chunk : chunks) {
TaskManager.runTask(new Runnable() {
@Override
public void run() {
try {
chunk.unload(true, false);
} catch (final Throwable e) {
final String worldname = chunk.getWorld().getName();
PS.debug("$4Could not save chunk: " + worldname + ";" + chunk.getX() + ";" + chunk.getZ());
PS.debug("$3 - $4File may be open in another process (e.g. MCEdit)");
PS.debug("$3 - $4" + worldname + "/level.dat or " + worldname
+ "/level_old.dat may be corrupt (try repairing or removing these)");
}
}
});
}
//
//
// int diffx, diffz;
// << 4;
// for (final Chunk chunk : chunks) {
// if (!chunk.isLoaded()) {
// continue;
// }
// boolean unload = true;
// final Object c = methodGetHandle.of(chunk).call();
// final Object w = world.of(c).get();
// final Object p = players.of(w).get();
// for (final Object ep : (List<Object>) p) {
// final int x = ((Double) locX.of(ep).get()).intValue();
// final int z = ((Double) locZ.of(ep).get()).intValue();
// diffx = Math.abs(x - (chunk.getX() << 4));
// diffz = Math.abs(z - (chunk.getZ() << 4));
// if ((diffx <= view) && (diffz <= view)) {
// unload = false;
// if (v1_7_10) {
// chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
// chunk.load(true);
// }
// else {
// final Object pair = ChunkCoordIntPairCon.create(chunk.getX(), chunk.getZ());
// final Object pq = chunkCoordIntPairQueue.of(ep).get();
// ((List) pq).add(pair);
// }
// }
// }
// if (unload) {
// TaskManager.runTask(new Runnable() {
// @Override
// public void run() {
// try {
// chunk.unload(true, true);
// }
// catch (Exception e) {
// String worldname = chunk.getWorld().getName();
// PS.debug("$4Could not save chunk: " + worldname + ";" + chunk.getX() + ";" + chunk.getZ());
// PS.debug("$3 - $4File may be open in another process (e.g. MCEdit)");
// PS.debug("$3 - $4" + worldname + "/level.dat or " + worldname + "level_old.dat may be corrupt (try repairing
// or removing these)");
// }
// }
// });
// }
//
// }
}
public void sendChunk(final String worldname, final List<ChunkLoc> locs) {
final World myworld = Bukkit.getWorld(worldname);
final ArrayList<Chunk> chunks = new ArrayList<>();
for (final ChunkLoc loc : locs) {
chunks.add(myworld.getChunkAt(loc.x, loc.z));
}
sendChunk(chunks);
}
}

View File

@ -0,0 +1,57 @@
package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.util.SetupUtils;
import com.plotsquared.bukkit.generator.BukkitAugmentedGenerator;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
public class SetGenCB {
public static void setGenerator(final World world) throws Exception {
SetupUtils.manager.updateGenerators();
PS.get().removePlotAreas(world.getName());
final ChunkGenerator gen = world.getGenerator();
if (gen == null) {
return;
}
final String name = gen.getClass().getCanonicalName();
boolean set = false;
for (final GeneratorWrapper<?> wrapper : SetupUtils.generators.values()) {
ChunkGenerator newGen = (ChunkGenerator) wrapper.getPlatformGenerator();
if (newGen == null) {
newGen = (ChunkGenerator) wrapper;
}
if (newGen.getClass().getCanonicalName().equals(name)) {
// set generator
final Field generator = world.getClass().getDeclaredField("generator");
final Field populators = world.getClass().getDeclaredField("populators");
generator.setAccessible(true);
populators.setAccessible(true);
// Set populators (just in case)
populators.set(world, new ArrayList<>());
// Set generator
generator.set(world, newGen);
populators.set(world, newGen.getDefaultPopulators(world));
// end
set = true;
break;
}
}
if (!set) {
final Iterator<BlockPopulator> iter = world.getPopulators().iterator();
while (iter.hasNext()) {
if (iter.next() instanceof BukkitAugmentedGenerator) {
iter.remove();
}
}
}
PS.get().loadWorld(world.getName(), PS.get().IMP.getGenerator(world.getName(), null));
}
}

View File

@ -0,0 +1,246 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import java.util.Arrays;
public class FastChunk_1_8_3 extends PlotChunk<Chunk> {
public char[][] ids;
public short[] count;
public short[] air;
public short[] relight;
public int[][] biomes;
public Chunk chunk;
public FastChunk_1_8_3(final ChunkWrapper chunk) {
super(chunk);
ids = new char[16][];
count = new short[16];
air = new short[16];
relight = new short[16];
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return BukkitUtil.getWorld(loc.world).getChunkAt(loc.x, loc.z);
}
@Override
public Chunk getChunk() {
if (chunk == null) {
final ChunkWrapper cl = getChunkWrapper();
chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z);
}
return chunk;
}
@Override
public void setChunkWrapper(final ChunkWrapper loc) {
super.setChunkWrapper(loc);
chunk = null;
}
/**
* Get the number of block changes in a specified section
* @param i
* @return
*/
public int getCount(final int i) {
return count[i];
}
public int getAir(final int i) {
return air[i];
}
public void setCount(int i, short value) {
count[i] = value;
}
/**
* Get the number of block changes in a specified section
* @param i
* @return
*/
public int getRelight(final int i) {
return relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(count, (short) 1);
Arrays.fill(relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += relight[i];
}
return total;
}
/**
* Get the raw data for a section
* @param i
* @return
*/
public char[] getIdArray(final int i) {
return ids[i];
}
@Override
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
final int i = MainUtil.CACHE_I[y][x][z];
final int j = MainUtil.CACHE_J[y][x][z];
char[] vs = ids[i];
if (vs == null) {
vs = ids[i] = new char[4096];
count[i]++;
} else if (vs[j] == 0) {
count[i]++;
}
switch (id) {
case 0:
air[i]++;
vs[j] = (char) 1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (char) (id << 4);
return;
case 130:
case 76:
case 62:
relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = (char) ((id << 4) + data);
return;
}
}
@Override
public PlotChunk clone() {
FastChunk_1_8_3 toReturn = new FastChunk_1_8_3(getChunkWrapper());
toReturn.air = air.clone();
toReturn.count = count.clone();
toReturn.relight = relight.clone();
toReturn.ids = new char[ids.length][];
for (int i = 0; i < ids.length; i++) {
char[] matrix = ids[i];
if (matrix != null) {
toReturn.ids[i] = new char[matrix.length];
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
FastChunk_1_8_3 toReturn = new FastChunk_1_8_3(getChunkWrapper());
toReturn.air = air;
toReturn.count = count;
toReturn.relight = relight;
toReturn.ids = ids;
return toReturn;
}
@Override
public void setBiome(int x, int z, int biome) {
if (biomes == null) {
biomes = new int[16][16];
}
biomes[x][z] = biome;
}
}

View File

@ -0,0 +1,181 @@
package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.SendChunk;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class FastQueue_1_7 extends SlowQueue {
public final RefClass classBlock = getRefClass("{nms}.Block");
public final RefClass classChunk = getRefClass("{nms}.Chunk");
public final RefClass classWorld = getRefClass("{nms}.World");
public final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
public final RefMethod methodGetHandle;
public final RefMethod methodGetChunkAt;
public final RefMethod methodA;
public final RefMethod methodGetById;
public final RefMethod methodInitLighting;
public final SendChunk chunksender;
public HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
public FastQueue_1_7() throws NoSuchMethodException, RuntimeException {
methodGetHandle = classCraftWorld.getMethod("getHandle");
methodGetChunkAt = classWorld.getMethod("getChunkAt", int.class, int.class);
methodA = classChunk.getMethod("a", int.class, int.class, int.class, classBlock, int.class);
methodGetById = classBlock.getMethod("getById", int.class);
methodInitLighting = classChunk.getMethod("initLighting");
chunksender = new SendChunk();
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (toUpdate.isEmpty()) {
return;
}
int count = 0;
final ArrayList<Chunk> chunks = new ArrayList<>();
final Iterator<Entry<ChunkWrapper, Chunk>> i = toUpdate.entrySet().iterator();
while (i.hasNext() && (count < 128)) {
chunks.add(i.next().getValue());
i.remove();
count++;
}
if (count == 0) {
return;
}
update(chunks);
}
}, 1);
MainUtil.initCache();
}
public void update(final Collection<Chunk> chunks) {
if (chunks.isEmpty()) {
return;
}
if (!MainUtil.canSendChunk) {
for (final Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
chunksender.sendChunk(chunks);
} catch (final Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
/**
* This should be overridden by any specialized queues
* @param pc
*/
@Override
public void execute(PlotChunk<Chunk> pc) {
SlowChunk sc = (SlowChunk) pc;
Chunk chunk = pc.getChunk();
ChunkWrapper wrapper = pc.getChunkWrapper();
if (!toUpdate.containsKey(wrapper)) {
toUpdate.put(wrapper, chunk);
}
chunk.load(true);
World world = chunk.getWorld();
final Object w = methodGetHandle.of(world).call();
final Object c = methodGetChunkAt.of(w).call(wrapper.x, wrapper.z);
for (int i = 0; i < sc.result.length; i++) {
PlotBlock[] result2 = sc.result[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
final int x = MainUtil.x_loc[i][j];
final int y = MainUtil.y_loc[i][j];
final int z = MainUtil.z_loc[i][j];
PlotBlock newBlock = result2[j];
if (newBlock.id == -1) {
chunk.getBlock(x, y, z).setData(newBlock.data, false);
continue;
}
final Object block = methodGetById.call(newBlock.id);
methodA.of(c).call(x, y, z, block, newBlock.data);
}
}
int[][] biomes = sc.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
}
/**
* This should be overridden by any specialized queues
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new SlowChunk(wrap);
}
/**
* This should be overriden by any specialized queues
* @param chunk
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
Object c = methodGetHandle.of(chunk.getChunk()).call();
methodInitLighting.of(c).call();
return true;
}
/**
* This should be overridden by any specialized queues
* @param world
* @param locs
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locs) {
World worldObj = BukkitUtil.getWorld(world);
for (ChunkLoc loc : locs) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
if (!toUpdate.containsKey(wrapper)) {
toUpdate.put(wrapper, worldObj.getChunkAt(loc.x, loc.z));
}
}
}
}

View File

@ -0,0 +1,384 @@
package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.SendChunk;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class FastQueue_1_8 extends SlowQueue {
public final RefMethod methodInitLighting;
private final RefClass classBlock = getRefClass("{nms}.Block");
private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
private final RefClass classIBlockData = getRefClass("{nms}.IBlockData");
private final RefClass classChunk = getRefClass("{nms}.Chunk");
private final RefClass classWorld = getRefClass("{nms}.World");
private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
public HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
private RefMethod methodGetHandle;
private RefMethod methodGetChunkAt;
private RefMethod methodA;
private RefMethod methodGetByCombinedId;
private RefConstructor constructorBlockPosition;
private SendChunk chunksender;
public FastQueue_1_8() throws NoSuchMethodException, RuntimeException {
methodInitLighting = classChunk.getMethod("initLighting");
constructorBlockPosition = classBlockPosition.getConstructor(int.class, int.class, int.class);
methodGetByCombinedId = classBlock.getMethod("getByCombinedId", int.class);
methodGetHandle = classCraftWorld.getMethod("getHandle");
methodGetChunkAt = classWorld.getMethod("getChunkAt", int.class, int.class);
methodA = classChunk.getMethod("a", classBlockPosition, classIBlockData);
chunksender = new SendChunk();
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (toUpdate.isEmpty()) {
return;
}
int count = 0;
final ArrayList<Chunk> chunks = new ArrayList<Chunk>();
final Iterator<Entry<ChunkWrapper, Chunk>> i = toUpdate.entrySet().iterator();
while (i.hasNext() && (count < 128)) {
chunks.add(i.next().getValue());
i.remove();
count++;
}
if (count == 0) {
return;
}
update(chunks);
}
}, 1);
MainUtil.initCache();
}
public void update(final Collection<Chunk> chunks) {
if (chunks.isEmpty()) {
return;
}
if (!MainUtil.canSendChunk) {
for (final Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
chunksender.sendChunk(chunks);
} catch (final Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
/**
* This should be overriden by any specialized queues
* @param pc
*/
@Override
public void execute(PlotChunk<Chunk> pc) {
SlowChunk sc = (SlowChunk) pc;
Chunk chunk = pc.getChunk();
ChunkWrapper wrapper = pc.getChunkWrapper();
if (!toUpdate.containsKey(wrapper)) {
toUpdate.put(wrapper, chunk);
}
chunk.load(true);
World world = chunk.getWorld();
final Object w = methodGetHandle.of(world).call();
final Object c = methodGetChunkAt.of(w).call(wrapper.x, wrapper.z);
for (int i = 0; i < sc.result.length; i++) {
PlotBlock[] result2 = sc.result[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
final int x = MainUtil.x_loc[i][j];
final int y = MainUtil.y_loc[i][j];
final int z = MainUtil.z_loc[i][j];
PlotBlock newBlock = result2[j];
if (newBlock.id == -1) {
chunk.getBlock(x, y, z).setData(newBlock.data, false);
continue;
}
// Start blockstate workaround //
switch (newBlock.id) {
case 54:
case 130:
case 142:
case 132:
case 27:
case 137:
case 52:
case 154:
case 84:
case 25:
case 144:
case 138:
case 176:
case 177:
case 119:
case 63:
case 68:
case 323:
case 117:
case 116:
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
case 23:
case 123:
case 124:
case 29:
case 33:
case 151:
case 178: {
final Block block = world.getBlockAt(x, y, z);
if (block.getData() == newBlock.data) {
if (block.getTypeId() != newBlock.id) {
block.setTypeId(newBlock.id, false);
}
} else {
if (block.getTypeId() == newBlock.id) {
block.setData(newBlock.data, false);
} else {
block.setTypeIdAndData(newBlock.id, newBlock.data, false);
}
}
continue;
}
}
// Start data value shortcut
final Block block = world.getBlockAt(x, y, z);
final int currentId = block.getTypeId();
if (currentId == newBlock.id) {
switch (newBlock.id) {
case 0:
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 25:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 52:
case 54:
case 55:
case 56:
case 57:
case 58:
case 60:
case 61:
case 62:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 117:
case 121:
case 122:
case 123:
case 124:
case 129:
case 133:
case 138:
case 137:
case 140:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 176:
case 177:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192: {
continue;
}
}
if (block.getData() == newBlock.data) {
return;
}
block.setData(newBlock.data, false);
return;
}
// blockstate
switch (currentId) {
case 54:
case 130:
case 132:
case 142:
case 27:
case 137:
case 52:
case 154:
case 84:
case 25:
case 144:
case 138:
case 176:
case 177:
case 63:
case 68:
case 323:
case 117:
case 119:
case 116:
case 28:
case 66:
case 157:
case 61:
case 62:
case 140:
case 146:
case 149:
case 150:
case 158:
case 23:
case 123:
case 124:
case 29:
case 33:
case 151:
case 178: {
if (block.getData() == newBlock.data) {
block.setTypeId(newBlock.id, false);
} else {
block.setTypeIdAndData(newBlock.id, newBlock.data, false);
}
continue;
}
}
// End blockstate workaround //
// check sign
final Object pos = constructorBlockPosition.create(x, y, z);
final Object combined = methodGetByCombinedId.call(newBlock.id + (newBlock.data << 12));
methodA.of(chunk).call(pos, combined);
}
}
int[][] biomes = sc.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
}
/**
* This should be overridden by any specialized queues
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new SlowChunk(wrap);
}
/**
* This should be overridden by any specialized queues
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
Object c = methodGetHandle.of(chunk.getChunk()).call();
methodInitLighting.of(c).call();
return true;
}
/**
* This should be overridden by any specialized queues
* @param locs
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locs) {
World worldObj = BukkitUtil.getWorld(world);
for (ChunkLoc loc : locs) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
if (!toUpdate.containsKey(wrapper)) {
toUpdate.put(wrapper, worldObj.getChunkAt(loc.x, loc.z));
}
}
}
}

View File

@ -0,0 +1,421 @@
package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod.RefExecutor;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.SendChunk;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
public class FastQueue_1_8_3 extends SlowQueue {
public final SendChunk chunksender;
private final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer");
private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk");
private final RefClass classPacket = getRefClass("{nms}.Packet");
private final RefClass classConnection = getRefClass("{nms}.PlayerConnection");
private final RefClass classChunk = getRefClass("{nms}.Chunk");
private final RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer");
private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
private final RefClass classWorld = getRefClass("{nms}.World");
private final RefField mustSave = classChunk.getField("mustSave");
private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
public HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
private RefMethod methodGetHandlePlayer;
private RefMethod methodGetHandleChunk;
private RefConstructor MapChunk;
private RefField connection;
private RefMethod send;
private RefMethod methodInitLighting;
private RefConstructor classBlockPositionConstructor;
private RefConstructor classChunkSectionConstructor;
private RefMethod methodX;
private RefMethod methodAreNeighborsLoaded;
private RefField fieldSections;
private RefField fieldWorld;
private RefMethod methodGetIdArray;
public FastQueue_1_8_3() throws NoSuchMethodException, RuntimeException {
methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle");
methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
methodInitLighting = classChunk.getMethod("initLighting");
MapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), boolean.class, int.class);
connection = classEntityPlayer.getField("playerConnection");
send = classConnection.getMethod("sendPacket", classPacket.getRealClass());
classBlockPositionConstructor = classBlockPosition.getConstructor(int.class, int.class, int.class);
methodX = classWorld.getMethod("x", classBlockPosition.getRealClass());
fieldSections = classChunk.getField("sections");
fieldWorld = classChunk.getField("world");
methodGetIdArray = classChunkSection.getMethod("getIdArray");
methodAreNeighborsLoaded = classChunk.getMethod("areNeighborsLoaded", int.class);
classChunkSectionConstructor = classChunkSection.getConstructor(int.class, boolean.class, char[].class);
chunksender = new SendChunk();
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (toUpdate.isEmpty()) {
return;
}
int count = 0;
final ArrayList<Chunk> chunks = new ArrayList<Chunk>();
final Iterator<Entry<ChunkWrapper, Chunk>> i = toUpdate.entrySet().iterator();
while (i.hasNext() && (count < 128)) {
chunks.add(i.next().getValue());
i.remove();
count++;
}
if (count == 0) {
return;
}
update(chunks);
}
}, 1);
MainUtil.initCache();
}
public void update(final Collection<Chunk> chunks) {
if (chunks.isEmpty()) {
return;
}
if (!MainUtil.canSendChunk) {
for (final Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
chunksender.sendChunk(chunks);
} catch (final Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
/**
* This should be overridden by any specialized queues
* @param pc
*/
@Override
public void execute(PlotChunk<Chunk> pc) {
FastChunk_1_8_3 fs = (FastChunk_1_8_3) pc;
Chunk chunk = pc.getChunk();
final World world = chunk.getWorld();
ChunkWrapper wrapper = pc.getChunkWrapper();
if (!toUpdate.containsKey(wrapper)) {
toUpdate.put(wrapper, chunk);
}
chunk.load(true);
try {
final boolean flag = world.getEnvironment() == Environment.NORMAL;
// Sections
final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle");
final Object c = getHandele.invoke(chunk);
final Class<? extends Object> clazz = c.getClass();
final Field sf = clazz.getDeclaredField("sections");
sf.setAccessible(true);
final Field tf = clazz.getDeclaredField("tileEntities");
final Field ef = clazz.getDeclaredField("entitySlices");
final Object[] sections = (Object[]) sf.get(c);
final HashMap<?, ?> tiles = (HashMap<?, ?>) tf.get(c);
final List<?>[] entities = (List<?>[]) ef.get(c);
Method xm = null;
Method ym = null;
Method zm = null;
// Trim tiles
final Set<Entry<?, ?>> entryset = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet();
final Iterator<Entry<?, ?>> iter = entryset.iterator();
while (iter.hasNext()) {
final Entry<?, ?> tile = iter.next();
final Object pos = tile.getKey();
if (xm == null) {
final Class<? extends Object> clazz2 = pos.getClass().getSuperclass();
xm = clazz2.getDeclaredMethod("getX");
ym = clazz2.getDeclaredMethod("getY");
zm = clazz2.getDeclaredMethod("getZ");
}
final int lx = (int) xm.invoke(pos) & 15;
final int ly = (int) ym.invoke(pos);
final int lz = (int) zm.invoke(pos) & 15;
final int j = MainUtil.CACHE_I[ly][lx][lz];
final int k = MainUtil.CACHE_J[ly][lx][lz];
final char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
if (array[k] != 0) {
iter.remove();
}
}
// Trim entities
for (int i = 0; i < 16; i++) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
entities[i].clear();
}
}
// Efficiently merge sections
for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) {
continue;
}
final char[] newArray = fs.getIdArray(j);
if (newArray == null) {
continue;
}
Object section = sections[j];
if ((section == null) || (fs.getCount(j) >= 4096)) {
section = sections[j] = newChunkSection(j << 4, flag, newArray);
continue;
}
final char[] currentArray = getIdArray(section);
boolean fill = true;
for (int k = 0; k < newArray.length; k++) {
final char n = newArray[k];
switch (n) {
case 0:
fill = false;
continue;
case 1:
fill = false;
currentArray[k] = 0;
continue;
default:
currentArray[k] = n;
continue;
}
}
if (fill) {
fs.setCount(j, Short.MAX_VALUE);
}
}
// Clear
} catch (IllegalAccessException | IllegalArgumentException | NoSuchMethodException | SecurityException | InvocationTargetException |
NoSuchFieldException e) {
e.printStackTrace();
}
int[][] biomes = fs.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
}
public Object newChunkSection(final int i, final boolean flag, final char[] ids) {
return classChunkSectionConstructor.create(i, flag, ids);
}
public char[] getIdArray(final Object obj) {
return (char[]) methodGetIdArray.of(obj).call();
}
/**
* This should be overridden by any specialized queues
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new FastChunk_1_8_3(wrap);
}
/**
* This should be overridden by any specialized queues
* @param pc
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> pc, boolean fixAll) {
try {
FastChunk_1_8_3 bc = (FastChunk_1_8_3) pc;
final Chunk chunk = bc.getChunk();
if (!chunk.isLoaded()) {
chunk.load(false);
} else {
chunk.unload(true, false);
chunk.load(false);
}
// Initialize lighting
final Object c = methodGetHandleChunk.of(chunk).call();
if (fixAll && !(boolean) methodAreNeighborsLoaded.of(c).call(1)) {
World world = chunk.getWorld();
ChunkWrapper wrapper = bc.getChunkWrapper();
String worldname = wrapper.world;
for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) {
for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
if (x != 0 && z != 0) {
Chunk other = world.getChunkAt(x, z);
while (!other.isLoaded()) {
other.load(true);
}
ChunkManager.manager.loadChunk(worldname, new ChunkLoc(x, z), true);
}
}
}
if (!(boolean) methodAreNeighborsLoaded.of(c).call(1)) {
return false;
}
}
methodInitLighting.of(c).call();
if ((bc.getTotalRelight() == 0 && !fixAll)) {
return true;
}
final Object[] sections = (Object[]) fieldSections.of(c).get();
final Object w = fieldWorld.of(c).get();
final int X = chunk.getX() << 4;
final int Z = chunk.getZ() << 4;
RefExecutor relight = methodX.of(w);
for (int j = 0; j < sections.length; j++) {
final Object section = sections[j];
if (section == null) {
continue;
}
if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) {
continue;
}
final char[] array = getIdArray(section);
int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.length; k++) {
final int i = array[k];
if (i < 16) {
continue;
}
final short id = (short) (i >> 4);
switch (id) { // Lighting
default:
if (!fixAll) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
continue;
}
case 10:
case 11:
case 39:
case 40:
case 50:
case 51:
case 62:
case 74:
case 76:
case 89:
case 122:
case 124:
case 130:
case 138:
case 169:
final int x = MainUtil.x_loc[j][k];
final int y = MainUtil.y_loc[j][k];
final int z = MainUtil.z_loc[j][k];
if (isSurrounded(sections, x, y, z)) {
continue;
}
final Object pos = classBlockPositionConstructor.create(X + x, y, Z + z);
relight.call(pos);
}
}
}
return true;
} catch (final Throwable e) {
e.printStackTrace();
}
return false;
}
public boolean isSurrounded(Object[] sections, int x, int y, int z) {
return isSolid(getId(sections, x, y + 1, z))
&& isSolid(getId(sections, x + 1, y - 1, z))
&& isSolid(getId(sections, x - 1, y, z))
&& isSolid(getId(sections, x, y, z + 1))
&& isSolid(getId(sections, x, y, z - 1));
}
public boolean isSolid(int i) {
return i != 0 && Material.getMaterial(i).isOccluding();
}
public int getId(Object[] sections, int x, int y, int z) {
if (x < 0 || x > 15 || z < 0 || z > 15) {
return 1;
}
if (y < 0 || y > 255) {
return 1;
}
int i = MainUtil.CACHE_I[y][x][z];
Object section = sections[i];
if (section == null) {
return 0;
}
char[] array = getIdArray(section);
int j = MainUtil.CACHE_J[y][x][z];
return array[j] >> 4;
}
/**
* This should be overridden by any specialized queues
* @param world
* @param locs
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locs) {
World worldObj = BukkitUtil.getWorld(world);
for (ChunkLoc loc : locs) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
if (!toUpdate.containsKey(wrapper)) {
toUpdate.put(wrapper, worldObj.getChunkAt(loc.x, loc.z));
}
}
}
}

View File

@ -0,0 +1,105 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
public class GenChunk extends PlotChunk<Chunk> {
public final Biome[] biomes;
public Chunk chunk;
public short[][] result;
public byte[][] result_data;
public ChunkData cd;
public boolean modified = false;
public BiomeGrid grid;
public GenChunk(Chunk chunk, ChunkWrapper wrap) {
super(wrap);
if ((this.chunk = chunk) == null) {
World world = BukkitUtil.getWorld(wrap.world);
if (world != null) {
chunk = world.getChunkAt(wrap.x, wrap.z);
}
}
this.biomes = Biome.values();
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper wrap = getChunkWrapper();
if (wrap.x != chunk.getX() || wrap.z != chunk.getZ()) {
chunk = BukkitUtil.getWorld(wrap.world).getChunkAt(wrap.x, wrap.z);
}
return chunk;
}
@Override
public void setBiome(int x, int z, int biome) {
modified = true;
grid.setBiome(x, z, biomes[biome]);
}
public void setBiome(int x, int z, Biome biome) {
if (grid != null) {
grid.setBiome(x, z, biome);
}
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
if (result == null) {
modified = true;
cd.setBlock(x, y, z, id, data);
return;
}
int i = MainUtil.CACHE_I[y][x][z];
short[] v = result[i];
if (v == null) {
modified = true;
result[i] = v = new short[4096];
}
v[MainUtil.CACHE_J[y][x][z]] = (short) id;
if (data != 0) {
getChunk().getBlock(x, y, z).setData(data);
}
}
@Override
public PlotChunk clone() {
GenChunk toReturn = new GenChunk(getChunkAbs(), getChunkWrapper());
if (result != null) {
for (int i = 0; i < result.length; i++) {
short[] matrix = result[i];
if (matrix != null) {
toReturn.result[i] = new short[matrix.length];
System.arraycopy(matrix, 0, toReturn.result[i], 0, matrix.length);
}
}
for (int i = 0; i < result_data.length; i++) {
byte[] matrix = result_data[i];
if (matrix != null) {
toReturn.result_data[i] = new byte[matrix.length];
System.arraycopy(matrix, 0, toReturn.result_data[i], 0, matrix.length);
}
}
}
toReturn.cd = cd;
return toReturn;
}
@Override
public PlotChunk shallowClone() {
GenChunk toReturn = new GenChunk(getChunkAbs(), getChunkWrapper());
toReturn.result = result;
toReturn.result_data = result_data;
toReturn.cd = cd;
return toReturn;
}
}

View File

@ -0,0 +1,64 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Chunk;
public class SlowChunk extends PlotChunk<Chunk> {
public PlotBlock[][] result = new PlotBlock[16][];
public int[][] biomes;
private PlotBlock lastBlock;
public SlowChunk(ChunkWrapper chunk) {
super(chunk);
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return BukkitUtil.getWorld(loc.world).getChunkAt(loc.x, loc.z);
}
@Override
public void setBiome(int x, int z, int biome) {
if (biomes == null) {
biomes = new int[16][16];
}
biomes[x][z] = biome;
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
if (result[y >> 4] == null) {
result[y >> 4] = new PlotBlock[4096];
}
if (id == lastBlock.id && data == lastBlock.data) {
result[MainUtil.CACHE_I[x][y][z]][MainUtil.CACHE_J[x][y][z]] = lastBlock;
} else {
result[MainUtil.CACHE_I[x][y][z]][MainUtil.CACHE_J[x][y][z]] = new PlotBlock((short) id, data);
}
}
@Override
public PlotChunk clone() {
SlowChunk toReturn = new SlowChunk(getChunkWrapper());
for (int i = 0; i < result.length; i++) {
PlotBlock[] matrix = result[i];
if (matrix != null) {
toReturn.result[i] = new PlotBlock[matrix.length];
System.arraycopy(matrix, 0, toReturn.result[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
SlowChunk toReturn = new SlowChunk(getChunkWrapper());
toReturn.result = result;
return toReturn;
}
}

View File

@ -0,0 +1,278 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
public class SlowQueue implements PlotQueue<Chunk> {
private final ConcurrentHashMap<ChunkWrapper, PlotChunk<Chunk>> blocks = new ConcurrentHashMap<>();
public SlowQueue() {
MainUtil.initCache();
}
@Override
public boolean setBlock(String world, int x, int y, int z, short id, byte data) {
if (y > 255 || y < 0) {
return false;
}
final ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
PlotChunk<Chunk> result = blocks.get(wrap);
if (result == null) {
result = getChunk(wrap);
result.setBlock(x, y, z, id, data);
final PlotChunk<Chunk> previous = blocks.put(wrap, result);
if (previous == null) {
return true;
}
blocks.put(wrap, previous);
result = previous;
}
result.setBlock(x, y, z, id, data);
return true;
}
@Override
public void setChunk(PlotChunk<Chunk> chunk) {
blocks.put(chunk.getChunkWrapper(), chunk);
}
@Override
public PlotChunk<Chunk> next() {
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be called from main thread!");
}
try {
if (blocks.isEmpty()) {
return null;
}
final Iterator<Entry<ChunkWrapper, PlotChunk<Chunk>>> iter = blocks.entrySet().iterator();
final PlotChunk<Chunk> toReturn = iter.next().getValue();
if (SetQueue.IMP.isWaiting()) {
return null;
}
iter.remove();
execute(toReturn);
fixLighting(toReturn, true);
return toReturn;
} catch (final Throwable e) {
e.printStackTrace();
return null;
}
}
@Override
public PlotChunk<Chunk> next(ChunkWrapper wrap, boolean fixLighting) {
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be called from main thread!");
}
try {
if (blocks.isEmpty()) {
return null;
}
final PlotChunk<Chunk> toReturn = blocks.remove(wrap);
if (toReturn == null) {
return null;
}
execute(toReturn);
fixLighting(toReturn, fixLighting);
return toReturn;
} catch (final Throwable e) {
e.printStackTrace();
return null;
}
}
@Override
public void clear() {
blocks.clear();
}
/**
* This should be overriden by any specialized queues
* @param pc
*/
public void execute(PlotChunk<Chunk> pc) {
SlowChunk sc = (SlowChunk) pc;
Chunk chunk = pc.getChunk();
chunk.load(true);
for (int i = 0; i < sc.result.length; i++) {
PlotBlock[] result2 = sc.result[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
final int x = MainUtil.x_loc[i][j];
final int y = MainUtil.y_loc[i][j];
final int z = MainUtil.z_loc[i][j];
Block block = chunk.getBlock(x, y, z);
PlotBlock newBlock = result2[j];
switch (newBlock.id) {
case -1:
if (block.getData() == newBlock.data) {
continue;
}
block.setData(newBlock.data);
continue;
case 0:
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 25:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 52:
case 54:
case 55:
case 56:
case 57:
case 58:
case 60:
case 61:
case 62:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 117:
case 121:
case 122:
case 123:
case 124:
case 129:
case 133:
case 138:
case 137:
case 140:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 176:
case 177:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
if (block.getTypeId() == newBlock.id) {
continue;
}
block.setTypeId(newBlock.id, false);
continue;
default:
if (block.getTypeId() == newBlock.id && block.getData() == newBlock.data) {
continue;
}
if (newBlock.data == 0) {
block.setTypeId(newBlock.id, false);
} else {
block.setTypeIdAndData(newBlock.id, newBlock.data, false);
}
continue;
}
}
}
int[][] biomes = sc.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
}
/**
* This should be overriden by any specialized queues
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new SlowChunk(wrap);
}
/**
* This should be overriden by any specialized queues
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
// Do nothing
return true;
}
/**
* This should be overriden by any specialized queues
* @param locs
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locs) {
// Do nothing
}
}