mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-06-28 11:44:42 +02:00
Updated Gradle
This commit is contained in:
@ -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
@ -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;
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
310
Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java
Normal file
310
Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java
Normal 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();
|
||||
}
|
||||
}
|
715
Bukkit/src/main/java/com/plotsquared/bukkit/util/Metrics.java
Normal file
715
Bukkit/src/main/java/com/plotsquared/bukkit/util/Metrics.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
1020
Bukkit/src/main/java/com/plotsquared/bukkit/util/NbtFactory.java
Normal file
1020
Bukkit/src/main/java/com/plotsquared/bukkit/util/NbtFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
}
|
193
Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java
Normal file
193
Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user